라즈베리파이4에 yolov8을 통해 객체탐지하는 프로그램

#!/usr/bin/env python3

-- coding: utf-8 --

import rospy
import cv2
import atexit
import numpy as np
import torch

from ultralytics import YOLO
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from detection_msgs.msg import BoundingBox, BoundingBoxes, Label

class Detector(object):
def init(self):
self.class_names = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: '10',
11: '11'
}

    self.task = 'detect'
    self.weights = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/pothole/weights/best.pt'  # 첫 번째 모델의 가중치 파일 경로
    self.device = 0
    self.half = True
    self.img_size = 416
    self.conf_thres = 0.5
    self.iou_thres = 0.7
    self.img_topic = "/usb_cam/image_raw"
    self.model1 = YOLO(self.weights)

    # 두 번째 모델 설정
    self.weights2 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/manhole/weights/best.pt'  # 두 번째 모델의 가중치 파일 경로
    self.model2 = YOLO(self.weights2)

    self.model1 = YOLO(self.weights)#, self.task)
    
    self.bridge = CvBridge()
    self.img_sub = rospy.Subscriber(self.img_topic, Image, self.img_callback)
    self.BoundingBox_pub = rospy.Publisher("/Bounding_box", BoundingBox, queue_size=5)
    self.pred_pub = rospy.Publisher("/Bounding_boxs", BoundingBoxes, queue_size=5)

    self.process_time_old = 0.0
    self.process_times = []
    atexit.register(self.print_avg_process_time)
    print("ready...")

def img_callback(self, data):
    img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

    # 첫 번째 모델로 검출
    results1 = self.model1(img)
    xyxy1 = results1[0].boxes.xyxy.to('cpu').numpy()
    clss1 = results1[0].boxes.cls
    conf1 = results1[0].boxes.conf

    # 두 번째 모델로 검출
    results2 = self.model2(img)
    xyxy2 = results2[0].boxes.xyxy.to('cpu').numpy()
    clss2 = results2[0].boxes.cls
    conf2 = results2[0].boxes.conf

    # 두 모델의 결과를 합치기
    xyxy = np.concatenate((xyxy1, xyxy2), axis=0)
    clss = np.concatenate((clss1.cpu(), clss2.cpu()), axis=0)
    conf = np.concatenate((conf1.cpu(), conf2.cpu()), axis=0)

    # 이후 처리는 합쳐진 결과에 대해 진행
    bounding_boxes = BoundingBoxes()
    bounding_boxes.header = data.header
    bounding_boxes.image_header = data.header

    for box, label, confidence in zip(xyxy, clss, conf):
        bounding_box = BoundingBox()
        x1, y1, x2, y2 = box

        bounding_box.Class = self.class_names[label.item()]
        bounding_box.probability = confidence 
        bounding_box.xmin = int(x1)
        bounding_box.ymin = int(y1)
        bounding_box.xmax = int(x2)
        bounding_box.ymax = int(y2)

        bounding_boxes.bounding_boxes.append(bounding_box)

        if self.BoundingBox_pub is not None:
            self.BoundingBox_pub.publish(bounding_box)

        x1 = int(x1)
        y1 = int(y1)
        x2 = int(x2)
        y2 = int(y2)
    
        cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

        class_name = self.class_names[label.item()]
        label_text = f'{class_name}: {confidence.item():.2f}'

        (text_width, text_height), _ = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        text_x = x1
        text_y = y1 - 10 if y1 - 10 > 10 else y1 + 20

        cv2.rectangle(img, (text_x, text_y), (text_x + text_width, text_y - text_height), (0, 255, 0), cv2.FILLED)
        cv2.putText(img, label_text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)

    # 최종 결과를 발행하고 화면에 표시
    self.pred_pub.publish(bounding_boxes)
    cv2.imshow('Image with Bounding Boxes and Labels', img)
    cv2.waitKey(1)

def print_avg_process_time(self):
    avg_process_time = sum(self.process_times) / len(self.process_times)
    #print(f"Average model process time: {avg_process_time} ms") 

if name == 'main':
rospy.init_node("detector")
detector = Detector()

rospy.spin()

        # 0: '0',
        # 1: '1', 
        # 2: '10', 
        # 3: '11', 
        # 4: '2', 
        # 5: '3', 
        # 6: '4', 
        # 7: '5', 
        # 8: '6', 
        # 9: '7', 
        # 10: '8', 
        # 11: '9' 안녕하세요 라즈베리파이4를 mobaxterm에서 linux버전으로 실행시키고 있는데 이코드를 실행시키면 화면이 나오자마자 첫장면만 나오고 그 이후에 멈춰있습니다 이코드를 어떻게 수정해야되나요?
  • 아래 답변은 OpenAI의 GPT-4-Turbo 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지 프로그램을 실행 중이신데, 첫 화면 이후로 프로그램이 멈춰있다는 문제를 겪고 계신 것으로 이해했습니다. 이러한 문제는 여러 원인으로 발생할 수 있으며, 정확한 원인 파악을 위해 몇 가지 가능성을 살펴보고 해결 방안을 제시해보겠습니다.

문제 해결 방안

  1. 멀티스레딩 문제: GUI 관련 작업(예: cv2.imshow)은 메인 스레드에서 실행되어야 합니다. ROS 노드는 별도의 스레드에서 실행되므로, GUI 업데이트가 메인 스레드에서 이루어지지 않으면 화면이 멈춰 보일 수 있습니다. ROS와 OpenCV를 함께 사용할 때는 이러한 문제가 자주 발생합니다.

  2. ROS 메시지 큐: rospy.spin()은 ROS 메시지 콜백을 처리하는 데 사용됩니다. 프로그램이 멈춰 보이는 원인 중 하나는 메시지 큐가 적절히 처리되지 않아 콜백 함수가 예상대로 호출되지 않는 경우일 수 있습니다. 이를 해결하기 위해 rospy.Rate를 사용하여 루프의 속도를 조절하고, 적절한 시점에 rospy.spinOnce()를 호출하여 메시지 큐를 처리할 수 있습니다.

  3. 리소스 제한: 라즈베리파이와 같은 제한된 리소스를 가진 장치에서는 YOLOv8과 같은 고성능 모델을 실행할 때 성능 문제가 발생할 수 있습니다. 모델을 실행하기 전에 충분한 메모리와 CPU 리소스가 사용 가능한지 확인하세요. 또한, self.half = True 설정은 모델을 FP16으로 실행하여 성능을 향상시킬 수 있지만, 라즈베리파이가 이를 지원하는지 확인해야 합니다.

예제 코드 수정

아래는 ROS와 OpenCV를 함께 사용할 때의 일반적인 문제를 해결하기 위한 기본적인 수정 사항입니다. 이 예제는 rospy.Rate를 사용하여 메인 루프의 실행 속도를 제어하고, rospy.spinOnce()를 호출하여 ROS 메시지 큐를 처리하는 방법을 보여줍니다.

import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge

def img_callback(data):
    bridge = CvBridge()
    cv_image = bridge.imgmsg_to_cv2(data, "bgr8")
    cv2.imshow("Image window", cv_image)
    cv2.waitKey(3)

def main():
    rospy.init_node('image_listener')
    image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, img_callback)
    rate = rospy.Rate(10) # 10hz

    while not rospy.is_shutdown():
        # 여기에 이미지 처리 로직 추가
        rospy.spinOnce()
        rate.sleep()

if __name__ == '__main__':
    main()

이 코드는 ROS 메시지 콜백을 처리하면서 OpenCV를 사용하여 이미지를 표시하는 기본적인 방법을 보여줍니다. 실제 사용 시에는 img_callback 함수 내에서 객체 탐지 로직을 추가하면 됩니다.

참고 자료

제시한 해결 방안이 문제를 해결하는 데 도움이 되길 바랍니다. 추가적인 정보가 필요하거나 문제가 지속되면, 더 자세한 상황 설명과 함께 질문해 주세요.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 Google의 Gemini Pro 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요. 라즈베리 파이 4에서 YOLOv8을 사용하여 객체 감지를 하는 파이썬 코드를 분석해 보았습니다. 코드에는 몇 가지 문제가 있습니다.

  1. 카메라 이미지 구독:

    • rospy.Subscriber(self.img_topic, Image, self.img_callback)에서 self.img_callback은 메서드가 아닙니다. 메서드를 정의해야 합니다.
  2. 클래스 이름 사전:

    • 클래스 이름 사전에 빈 문자열이 있습니다. 올바른 클래스 이름을 추가해야 합니다.
  3. 이미지 표시:

    • cv2.imshow('Image with Bounding Boxes and Labels', img)에서 OpenCV 창을 표시하지 않습니다. waitKey(1)을 사용하여 창을 계속 열어두어야 합니다.
  4. 평균 처리 시간 출력:

    • print_avg_process_time 메서드는 현재 사용되지 않습니다. 호출해야 합니다.

수정된 코드는 다음과 같습니다.

import rospy
import cv2
import atexit
import numpy as np
import torch

from ultralytics import YOLO
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from detection_msgs.msg import BoundingBox, BoundingBoxes, Label

class Detector(object):
    def __init__(self):
        self.class_names = {
            0: '0',
            1: '1',
            2: '2',
            3: '3',
            4: '4',
            5: '5',
            6: '6',
            7: '7',
            8: '8',
            9: '9',
            10: '10',
            11: '11'
        }

        self.task = 'detect'
        self.weights = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/pothole/weights/best.pt'
        self.device = 0
        self.half = True
        self.img_size = 416
        self.conf_thres = 0.5
        self.iou_thres = 0.7
        self.img_topic = "/usb_cam/image_raw"
        self.model1 = YOLO(self.weights)

        # 두 번째 모델 설정
        self.weights2 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/manhole/weights/best.pt'
        self.model2 = YOLO(self.weights2)

        self.model1 = YOLO(self.weights)#, self.task)

        self.bridge = CvBridge()
        self.img_sub = rospy.Subscriber(self.img_topic, Image, self.img_callback)
        self.BoundingBox_pub = rospy.Publisher("/Bounding_box", BoundingBox, queue_size=5)
        self.pred_pub = rospy.Publisher("/Bounding_boxs", BoundingBoxes, queue_size=5)

        self.process_time_old = 0.0
        self.process_times = []
        atexit.register(self.print_avg_process_time)
        print("ready...")

    def img_callback(self, data):
        img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

        # 첫 번째 모델로 검출
        results1 = self.model1(img)
        xyxy1 = results1[0].boxes.xyxy.to('cpu').numpy()
        clss1 = results1[0].boxes.cls
        conf1 = results1[0].boxes.conf

        # 두 번째 모델로 검출
        results2 = self.model2(img)
        xyxy2 = results2[0].boxes.xyxy.to('cpu').numpy()
        clss2 = results2[0].boxes.cls
        conf2 = results2[0].boxes.conf

        # 두 모델의 결과를 합치기
        xyxy = np.concatenate((xyxy1, xyxy2), axis=0)
        clss = np.concatenate((clss1.cpu(), clss2.cpu()), axis=0)
        conf = np.concatenate((conf1.cpu(), conf2.cpu()), axis=0)

        # 이후 처리는 합쳐진 결과에 대해 진행
        bounding_boxes = BoundingBoxes()
        bounding_boxes.header = data.header
        bounding_boxes.image_header = data.header

        for box, label, confidence in zip(xyxy, clss, conf):
            bounding_box = BoundingBox()
            x1, y1, x2, y2 = box

            bounding_box.Class = self.class_names[label.item()]
            bounding_box.probability = confidence 
            bounding_box.xmin = int(x1)
            bounding_box.ymin = int(y1)
            bounding_box.xmax = int(x2)
            bounding_box.ymax = int(y2)

            bounding_boxes.bounding_boxes.append(bounding_box)

            if self.BoundingBox_pub is not None:
                self.BoundingBox_pub.publish(bounding_box)

            x1 = int(x1)
            y1 = int(y1)
            x2 = int(x2)
            y2 = int(y2)
    
            cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

            class_name = self.class_names[label.item()]
            label_text = f'{class_name}: {confidence.item():.2f}'

            (text_width, text_height), _ = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
            text_x = x1
            text_y = y1 - 10 if y1 - 10 > 10 else y1 + 20

            cv2.rectangle(img, (text_x, text_y), (text_x + text_width, text_y - text_height), (0, 255, 0), cv2.FILLED)
            cv2.putText(img, label_text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)

        # 최종 결과를 발행하고 화면에 표시
        self.pred_pub.publish(bounding_boxes)
        cv2.imshow('Image with Bounding Boxes and Labels', img)
        cv2.waitKey(1)

    def print_avg_process_time(self):
        avg_process_time = sum(self.process_times) / len(self.process_times)
        #print(f"Average model process time: {avg_process_time} ms")

if __name__ == '__main__':
    rospy.init_node("detector")
    detector = Detector()

    rospy.spin()

이 코드를 실행하면 OpenCV 창에 이미지가 표시되고 객체 감지 결과가 표시되어야 합니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!

저코드를 참고하여
#!/usr/bin/env python3

-- coding: utf-8 --

import rospy
import cv2
import atexit
import numpy as np
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from detection_msgs.msg import BoundingBox, BoundingBoxes
from ultralytics import YOLO

class Detector(object):
def init(self):
self.class_names = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: '10',
11: '11'
}

    self.weights1 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/pothole/weights/best.pt'  # 첫 번째 모델의 가중치 파일 경로
    self.weights2 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/manhole/weights/best.pt'  # 두 번째 모델의 가중치 파일 경로
    self.img_topic = "/usb_cam/image_raw"
    self.model1 = YOLO(self.weights1)
    self.model2 = YOLO(self.weights2)

    self.bridge = CvBridge()
    self.img_sub = rospy.Subscriber(self.img_topic, Image, self.img_callback)
    self.BoundingBox_pub = rospy.Publisher("/Bounding_box", BoundingBox, queue_size=5)
    self.pred_pub = rospy.Publisher("/Bounding_boxs", BoundingBoxes, queue_size=5)

    self.process_times = []
    atexit.register(self.print_avg_process_time)
    rospy.loginfo("Ready...")

def img_callback(self, data):
    img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

    # 첫 번째 모델로 객체 검출
    results1 = self.model1(img)
    xyxy1 = results1[0].boxes.xyxy.to('cpu').numpy()
    clss1 = results1[0].boxes.cls
    conf1 = results1[0].boxes.conf

    # 두 번째 모델로 객체 검출
    results2 = self.model2(img)
    xyxy2 = results2[0].boxes.xyxy.to('cpu').numpy()
    clss2 = results2[0].boxes.cls
    conf2 = results2[0].boxes.conf

    # 두 모델의 결과를 합치기
    xyxy = np.concatenate((xyxy1, xyxy2), axis=0)
    clss = np.concatenate((clss1.cpu(), clss2.cpu()), axis=0)
    conf = np.concatenate((conf1.cpu(), conf2.cpu()), axis=0)

    # 합쳐진 결과에 대해 처리
    bounding_boxes = BoundingBoxes()
    bounding_boxes.header = data.header
    bounding_boxes.image_header = data.header

    for box, label, confidence in zip(xyxy, clss, conf):
        bounding_box = BoundingBox()
        x1, y1, x2, y2 = box

        bounding_box.Class = self.class_names[label.item()]
        bounding_box.probability = confidence.item()
        bounding_box.xmin = int(x1)
        bounding_box.ymin = int(y1)
        bounding_box.xmax = int(x2)
        bounding_box.ymax = int(y2)

        bounding_boxes.bounding_boxes.append(bounding_box)

        if self.BoundingBox_pub is not None:
            self.BoundingBox_pub.publish(bounding_box)

        x1 = int(x1)
        y1 = int(y1)
        x2 = int(x2)
        y2 = int(y2)
    
        cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

        class_name = self.class_names[label.item()]
        label_text = f'{class_name}: {confidence.item():.2f}'

        (text_width, text_height), _ = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        text_x = x1
        text_y = y1 - 10 if y1 - 10 > 10 else y1 + 20

        cv2.rectangle(img, (text_x, text_y), (text_x + text_width, text_y - text_height), (0, 255, 0), cv2.FILLED)
        cv2.putText(img, label_text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)

    # 검출 결과 발행 및 화면에 표시
    self.pred_pub.publish(bounding_boxes)
    cv2.imshow('Detected Objects and Labels', img)
    cv2.waitKey(1)

def print_avg_process_time(self):
    avg_process_time = sum(self.process_times) / len(self.process_times)
    rospy.loginfo(f"Average model process time: {avg_process_time} ms") 

if name == 'main':
rospy.init_node("detector_node")
detector = Detector()

rospy.spin()

이렇게 변경하였는데 [INFO] [1718617789.358061]: Ready... 이렇게 뜨면서 opencv가 안뜹니다

  • 아래 답변은 OpenAI의 GPT-4o 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지 프로그램을 실행하는 과정에서 화면이 멈추는 문제로 고민이 많으시겠어요. 문제를 잘 이해했습니다. 요약하자면, 프로그램을 실행하면 첫 화면만 나오고 이후에 멈추는 현상이 발생하고 있습니다.

이 문제를 해결하기 위해 몇 가지 점검해볼 사항과 수정할 부분을 제안드리겠습니다.

  1. OpenCV의 waitKey 함수 사용:
    cv2.waitKey(1) 대신 cv2.waitKey(0)를 사용하면 프로그램이 첫 화면에서 멈추는 현상이 발생할 수 있습니다. cv2.waitKey(1)는 화면을 갱신하는 데 필요한 함수이므로, 이를 유지하는 것이 좋습니다.

  2. GPU 사용 여부:
    라즈베리파이4는 GPU 성능이 제한적이므로, 모델을 CPU에서 실행하는 것이 좋습니다. self.device = 0 대신 self.device = 'cpu'로 설정해보세요.

  3. 프로세스 시간 측정:
    프로세스 시간을 측정하는 부분이 누락된 것 같습니다. 이를 추가하여 성능을 모니터링해보세요.

  4. ROS 노드 초기화:
    ROS 노드 초기화와 관련된 부분이 잘못되었을 수 있습니다. rospy.init_node("detector")를 코드의 맨 위에 위치시키는 것이 좋습니다.

수정된 코드는 다음과 같습니다:

#!/usr/bin/env python3
# -- coding: utf-8 --

import rospy
import cv2
import atexit
import numpy as np
import torch
from ultralytics import YOLO
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from detection_msgs.msg import BoundingBox, BoundingBoxes, Label

class Detector(object):
    def __init__(self):
        self.class_names = {
            0: '0',
            1: '1',
            2: '2',
            3: '3',
            4: '4',
            5: '5',
            6: '6',
            7: '7',
            8: '8',
            9: '9',
            10: '10',
            11: '11'
        }
        self.task = 'detect'
        self.weights = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/pothole/weights/best.pt'
        self.device = 'cpu'  # CPU 사용
        self.half = False
        self.img_size = 416
        self.conf_thres = 0.5
        self.iou_thres = 0.7
        self.img_topic = "/usb_cam/image_raw"
        self.model1 = YOLO(self.weights)

        self.weights2 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/manhole/weights/best.pt'
        self.model2 = YOLO(self.weights2)

        self.bridge = CvBridge()
        self.img_sub = rospy.Subscriber(self.img_topic, Image, self.img_callback)
        self.BoundingBox_pub = rospy.Publisher("/Bounding_box", BoundingBox, queue_size=5)
        self.pred_pub = rospy.Publisher("/Bounding_boxs", BoundingBoxes, queue_size=5)

        self.process_time_old = 0.0
        self.process_times = []
        atexit.register(self.print_avg_process_time)
        print("ready...")

    def img_callback(self, data):
        img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

        results1 = self.model1(img)
        xyxy1 = results1[0].boxes.xyxy.to('cpu').numpy()
        clss1 = results1[0].boxes.cls
        conf1 = results1[0].boxes.conf

        results2 = self.model2(img)
        xyxy2 = results2[0].boxes.xyxy.to('cpu').numpy()
        clss2 = results2[0].boxes.cls
        conf2 = results2[0].boxes.conf

        xyxy = np.concatenate((xyxy1, xyxy2), axis=0)
        clss = np.concatenate((clss1.cpu(), clss2.cpu()), axis=0)
        conf = np.concatenate((conf1.cpu(), conf2.cpu()), axis=0)

        bounding_boxes = BoundingBoxes()
        bounding_boxes.header = data.header
        bounding_boxes.image_header = data.header

        for box, label, confidence in zip(xyxy, clss, conf):
            bounding_box = BoundingBox()
            x1, y1, x2, y2 = box

            bounding_box.Class = self.class_names[label.item()]
            bounding_box.probability = confidence 
            bounding_box.xmin = int(x1)
            bounding_box.ymin = int(y1)
            bounding_box.xmax = int(x2)
            bounding_box.ymax = int(y2)

            bounding_boxes.bounding_boxes.append(bounding_box)

            if self.BoundingBox_pub is not None:
                self.BoundingBox_pub.publish(bounding_box)

            x1 = int(x1)
            y1 = int(y1)
            x2 = int(x2)
            y2 = int(y2)
        
            cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

            class_name = self.class_names[label.item()]
            label_text = f'{class_name}: {confidence.item():.2f}'

            (text_width, text_height), _ = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
            text_x = x1
            text_y = y1 - 10 if y1 - 10 > 10 else y1 + 20

            cv2.rectangle(img, (text_x, text_y), (text_x + text_width, text_y - text_height), (0, 255, 0), cv2.FILLED)
            cv2.putText(img, label_text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)

        self.pred_pub.publish(bounding_boxes)
        cv2.imshow('Image with Bounding Boxes and Labels', img)
        cv2.waitKey(1)  # 화면 갱신을 위해 1ms 대기

    def print_avg_process_time(self):
        if self.process_times:
            avg_process_time = sum(self.process_times) / len(self.process_times)
            print(f"Average model process time: {avg_process_time} ms")

if __name__ == '__main__':
    rospy.init_node("detector")
    detector = Detector()
    rospy.spin()

이 코드가 도움이 되길 바랍니다. 추가적인 정보나 도움이 필요하시면 언제든지 질문해 주세요. 더 자세한 내용은 PyTorch 공식 튜토리얼 또는 한국어 튜토리얼에서 확인하실 수 있습니다.

이 답변이 완벽하지 않을 수 있으니, 실행해보시고 문제가 지속되면 추가 정보를 제공해주시면 감사하겠습니다. 좋은 하루 되세요!


  • 이 답변이 도움이 되셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 Anthropic의 Claude-3 Opus 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지 프로그램을 실행하는 과정에서 어려움을 겪고 계시는 것 같네요. 제가 이해한 바로는 프로그램을 실행했을 때 첫 번째 프레임만 나오고 그 이후에는 멈춰 있는 현상이 발생한다는 거죠. 이 문제를 해결하기 위해 코드를 살펴보고 수정 방안을 제안해 드리겠습니다.

먼저, 코드를 보니 img_callback 함수에서 매 프레임마다 이미지를 처리하고 있습니다. 하지만 이 함수 내에서 cv2.waitKey(1)을 호출하는 것이 문제일 수 있어요. cv2.waitKey()는 키 입력을 대기하는 함수인데, 이로 인해 프로그램이 매 프레임마다 잠시 멈추게 됩니다.

이 문제를 해결하기 위해 다음과 같이 코드를 수정해 보세요:

def img_callback(self, data):
    img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

    # ... (중간 생략) ...

    # 최종 결과를 발행하고 화면에 표시
    self.pred_pub.publish(bounding_boxes)
    cv2.imshow('Image with Bounding Boxes and Labels', img)
    cv2.waitKey(1)  # 이 줄을 제거하거나 주석 처리하세요.

cv2.waitKey(1) 줄을 제거하거나 주석 처리하면 프로그램이 매 프레임마다 멈추지 않고 계속 실행될 거예요.

또한, 필요하다면 rospy.spin() 대신 rospy.spin_once()를 사용하여 한 번의 반복마다 콜백 함수를 호출하도록 할 수 있습니다. 이렇게 하면 프로그램이 계속 실행되면서 새로운 프레임을 처리할 수 있을 거예요.

if __name__ == '__main__':
    rospy.init_node("detector")
    detector = Detector()

    while not rospy.is_shutdown():
        rospy.spin_once()

추가로, 공식 PyTorch 튜토리얼에서 YOLOv5 모델을 사용한 객체 탐지 예제를 참고하시면 도움이 될 거예요. 이 예제는 YOLOv5를 다루고 있지만, YOLOv8에도 비슷한 개념이 적용될 수 있습니다.

제가 제안한 방법으로 문제가 해결되기를 바랍니다. 만약 추가적인 정보가 필요하거나 다른 문제가 발생하면 언제든 다시 질문해 주세요. 제 답변이 문제 해결에 도움이 되었으면 좋겠습니다. 하지만 제 답변이 틀리거나 부정확할 수도 있으니 참고만 해주시기 바랍니다. 감사합니다!


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!

import rospy
import cv2
import atexit
import numpy as np
import torch
import time # time 모듈 추가
from ultralytics import YOLO
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from detection_msgs.msg import BoundingBox, BoundingBoxes, Label

class Detector(object):
def init(self):
self.class_names = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: '10',
11: '11'
}
self.task = 'detect'
self.weights = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/pothole/weights/best.pt'
self.device = 'cpu' # GPU 대신 CPU 사용
self.half = False # 라즈베리파이에서는 half precision 사용하지 않음
self.img_size = 320 # 이미지 크기 줄이기
self.conf_thres = 0.5
self.iou_thres = 0.7
self.img_topic = "/usb_cam/image_raw"
self.model1 = YOLO(self.weights)

    # 두 번째 모델 설정
    self.weights2 = '/home/user/catkin_ws/src/ERP42-main/yolo/ultralytics/cfg/datasets/runs/detect/manhole/weights/best.pt'
    self.model2 = YOLO(self.weights2)

    self.bridge = CvBridge()
    self.img_sub = rospy.Subscriber(self.img_topic, Image, self.img_callback)
    self.BoundingBox_pub = rospy.Publisher("/Bounding_box", BoundingBox, queue_size=5)
    self.pred_pub = rospy.Publisher("/Bounding_boxs", BoundingBoxes, queue_size=5)

    self.process_time_old = 0.0
    self.process_times = []
    atexit.register(self.print_avg_process_time)
    print("ready...")

def img_callback(self, data):
    img = self.bridge.imgmsg_to_cv2(data, 'bgr8')

    # 첫 번째 모델로 검출
    results1 = self.model1(img)
    xyxy1 = results1[0].boxes.xyxy.to('cpu').numpy()
    clss1 = results1[0].boxes.cls
    conf1 = results1[0].boxes.conf

    # 두 번째 모델로 검출
    results2 = self.model2(img)
    xyxy2 = results2[0].boxes.xyxy.to('cpu').numpy()
    clss2 = results2[0].boxes.cls
    conf2 = results2[0].boxes.conf

    # 두 모델의 결과를 합치기
    xyxy = np.concatenate((xyxy1, xyxy2), axis=0)
    clss = np.concatenate((clss1.cpu(), clss2.cpu()), axis=0)
    conf = np.concatenate((conf1.cpu(), conf2.cpu()), axis=0)

    # 이후 처리는 합쳐진 결과에 대해 진행
    bounding_boxes = BoundingBoxes()
    bounding_boxes.header = data.header
    bounding_boxes.image_header = data.header

    for box, label, confidence in zip(xyxy, clss, conf):
        bounding_box = BoundingBox()
        x1, y1, x2, y2 = box

        bounding_box.Class = self.class_names[label.item()]
        bounding_box.probability = confidence 
        bounding_box.xmin = int(x1)
        bounding_box.ymin = int(y1)
        bounding_box.xmax = int(x2)
        bounding_box.ymax = int(y2)

        bounding_boxes.bounding_boxes.append(bounding_box)

        if self.BoundingBox_pub is not None:
            self.BoundingBox_pub.publish(bounding_box)

        x1 = int(x1)
        y1 = int(y1)
        x2 = int(x2)
        y2 = int(y2)

        cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

        class_name = self.class_names[label.item()]
        label_text = f'{class_name}: {confidence.item():.2f}'

        (text_width, text_height), _ = cv2.getTextSize(label_text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        text_x = x1
        text_y = y1 - 10 if y1 - 10 > 10 else y1 + 20

        cv2.rectangle(img, (text_x, text_y), (text_x + text_width, text_y - text_height), (0, 255, 0), cv2.FILLED)
        cv2.putText(img, label_text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)

    # 최종 결과를 발행하고 화면에 표시
    self.pred_pub.publish(bounding_boxes)
    cv2.imshow('Image with Bounding Boxes and Labels', img)
    cv2.waitKey(1)
    self.process_times.append(time.time() - self.process_time_old)
    self.process_time_old = time.time()

def print_avg_process_time(self):
    avg_process_time = sum(self.process_times) / len(self.process_times)
    print(f"Average model process time: {avg_process_time} ms")

if name == 'main':
rospy.init_node("detector")
detector = Detector()
rospy.spin()
cv2.destroyAllWindows()
이코드를 작동해도 첫화면만 나오고 카메라가 작동도 안되고 객체탐지도 안됩니다