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

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() 

라즈베리파이4를 mobaxterm에서 ubuntu 20.04 버전으로 하고 있습니다 yolov8를 통해 객체탐지를 하고 싶은데 객체탐지하는 화면까지 나오지만 첫화면이 나오면서 그 객체에 대한 객체탐지만 되고 그 다음부터 카메라가 실시간으로 작동되지 않고 멈춰있습니다

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

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지를 하는 과정에서 발생한 문제에 대해 질문해 주셔서 감사합니다. 문제를 정리해 보면, 객체 탐지는 잘 이루어지지만 실시간으로 카메라 화면이 계속 업데이트되지 않고 첫 번째 프레임에서 멈춰 있는 상황인 것 같습니다.

이 문제를 해결하기 위해 다음과 같은 방법을 시도해 볼 수 있습니다:

  1. img_callback 함수 내에서 cv2.waitKey(1) 대신 cv2.waitKey(1) & 0xFF == ord('q')를 사용하여 'q' 키를 누르면 종료되도록 수정합니다. 이렇게 하면 프로그램이 종료되기 전까지 계속해서 프레임을 처리할 수 있습니다.

  2. rospy.spin() 대신 rospy.spin_once()를 사용하고, 메인 루프에서 일정 시간 간격으로 rospy.spin_once()를 호출하도록 수정합니다. 이렇게 하면 매 프레임마다 콜백 함수가 호출되어 실시간으로 처리할 수 있습니다.

예시 코드:

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):
        # ... (생략) ...

    def img_callback(self, data):
        # ... (생략) ...

        # 'q' 키를 누르면 종료
        if cv2.waitKey(1) & 0xFF == ord('q'):
            rospy.signal_shutdown("User requested shutdown")

    # ... (생략) ...

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

    # 메인 루프에서 일정 시간 간격으로 spin_once() 호출
    rate = rospy.Rate(30)  # 30 Hz
    while not rospy.is_shutdown():
        rospy.spin_once()
        rate.sleep()

위의 코드와 같이 수정하면 'q' 키를 누를 때까지 프로그램이 계속 실행되면서 실시간으로 객체 탐지 결과를 보여줄 수 있을 것입니다.

추가적으로 참고할 만한 자료로는 ROS 공식 튜토리얼의 Writing a Simple Publisher and Subscriber (Python)rospy overview 페이지가 있습니다. 이 튜토리얼에서는 ROS에서 메시지를 주고받는 기본적인 방법과 rospy 패키지의 사용법에 대해 설명하고 있습니다.

마지막으로 제 답변이 문제 해결에 도움이 되었기를 바라며, 만약 추가적인 문제가 발생하거나 더 자세한 정보가 필요하다면 언제든 다시 질문해 주시기 바랍니다. 감사합니다!


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

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지 프로그램을 구현하시는 과정에서 발생한 문제에 대해 질문해주셨군요. 첫 화면에서는 객체 탐지가 정상적으로 작동하지만, 그 이후 카메라가 실시간으로 작동하지 않고 멈추는 현상에 대해 문제를 겪고 계신 것으로 이해했습니다. 이러한 문제는 여러 원인에 의해 발생할 수 있으며, 해결을 위해 몇 가지 접근 방법을 제안드리겠습니다.

문제 해결 방안

  1. 카메라 드라이버 및 연결 확인: 먼저, 라즈베리파이의 카메라가 올바르게 연결되어 있고, 필요한 드라이버가 설치되어 있는지 확인해주세요. 또한, 카메라가 다른 프로세스에 의해 사용 중이지 않은지도 확인해야 합니다.

  2. 메모리 및 CPU 사용량 체크: YOLOv8과 같은 딥러닝 모델은 상당한 계산 능력을 요구합니다. 라즈베리파이4에서 이를 실행할 때, 시스템의 메모리나 CPU가 과부하 상태에 이를 수 있습니다. htop 같은 도구를 사용하여 시스템의 리소스 사용량을 모니터링해보세요.

  3. 멀티스레딩 사용: 객체 탐지와 이미지 표시를 별도의 스레드에서 처리하도록 구조를 변경해보세요. 이렇게 하면, 이미지 처리 과정에서 발생하는 지연이 사용자 인터페이스의 응답성에 덜 영향을 미칠 수 있습니다.

  4. 코드 최적화: 현재 코드에서 이미지 콜백 함수 내에서 많은 처리가 이루어지고 있습니다. 이를 최적화하기 위해 이미지 사이즈를 줄이거나, 탐지할 객체의 수를 제한하는 등의 방법을 시도해볼 수 있습니다.

  5. PyTorch 및 YOLOv8 최적화: PyTorch와 YOLOv8의 최신 버전을 사용하고 있는지 확인하고, 가능하다면 라즈베리파이에 최적화된 버전을 사용해보세요. 또한, .half() 메서드를 사용하여 모델을 FP16으로 변환하여 메모리 사용량과 계산 시간을 줄일 수 있습니다.

예제 코드 (멀티스레딩 적용)

멀티스레딩을 적용하는 간단한 예제를 아래에 제시합니다. 이는 기본적인 아이디어만 제공하며, 실제 구현 시에는 프로젝트의 요구 사항에 맞게 조정해야 합니다.

import threading

def process_image(img):
    # 이미지 처리 로직
    pass

def img_callback(data):
    img = bridge.imgmsg_to_cv2(data, 'bgr8')
    threading.Thread(target=process_image, args=(img,)).start()

위 코드는 img_callback 함수가 호출될 때마다 새로운 스레드에서 process_image 함수를 실행하도록 합니다. 이렇게 하면 이미지 처리 작업이 메인 스레드의 실행을 차단하지 않게 됩니다.

참고 자료

PyTorch 공식 문서 및 튜토리얼은 여러분이 사용하는 모델을 최적화하는 데 유용한 정보를 제공할 수 있습니다. 아래 링크를 참고해주세요.

제가 제안한 해결 방안이 문제를 해결하는 데 도움이 되길 바랍니다. 추가적인 정보가 필요하거나 다른 질문이 있으시면 언제든지 질문해주세요. 제 답변이 정확하지 않을 수도 있으니, 여러 자료를 참고하시는 것도 좋을 것 같습니다.


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

안녕하세요. 문제를 이해해 드리겠습니다. 라즈베리파이 4에서 YOLOv8을 사용하여 객체 탐지를 수행하는데 문제가 있는 것 같습니다.

귀하의 문제를 해결하려면 다음 단계를 시도해 보시기 바랍니다.

  1. 카메라 연결 확인: 카메라가 라즈베리파이에 올바르게 연결되어 있는지 확인합니다. /dev/video 디렉터리에 카메라 장치가 있는지 확인합니다.

  2. ROS 초기화 확인: rospy.init_node("detector") 명령이 올바르게 실행되고 있는지 확인합니다. 노드가 올바르게 초기화되지 않으면 ROS 토픽에 액세스할 수 없습니다.

  3. ROS 토픽 확인: /usb_cam/image_raw 토픽에서 이미지가 올바르게 게시되고 있는지 확인합니다. rostopic echo /usb_cam/image_raw 명령을 사용하여 토픽에 게시되는 메시지를 확인할 수 있습니다.

  4. 모델 초기화 확인: YOLO 모델이 올바르게 초기화되었는지 확인합니다. 모델이 올바르게 로드되지 않으면 객체를 탐지할 수 없습니다. model = YOLO(weights, conf_thres, iou_thres) 명령이 올바르게 실행되고 있는지 확인합니다.

  5. 네트워크 속도 확인: 라즈베리파이 4는 컴퓨터 성능이 제한적입니다. 네트워크가 실시간으로 프레임을 처리할 수 있는지 확인합니다. 입력 이미지 크기를 줄이거나 더 효율적인 모델을 사용하는 방법을 고려합니다.

  6. 카메라 프레임 속도 확인: 카메라가 실시간으로 프레임을 제공하고 있는지 확인합니다. 카메라 프레임 속도가 네트워크 처리 속도보다 느리면 병목 현상이 발생할 수 있습니다.

  7. PyTorch 버전 확인: 올바른 버전의 PyTorch가 설치되었는지 확인합니다. 라즈베리파이 4에 PyTorch 1.10 이상이 필요합니다.

문제가 지속되면 디버깅에 도움이 되도록 추가 정보를 제공해 주십시오. 예를 들어, 오류 메시지, 시스템 사양, 사용 중인 PyTorch 및 ROS 버전 등입니다.

이러한 단계를 수행해도 문제가 해결되지 않으면 PyTorch 포럼(https://discuss.pytorch.org/)에 질문을 게시하여 추가 지원을 받을 수 있습니다.

답변이 도움이 되었기를 바랍니다.


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

안녕하세요! 라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지를 구현하시려는 문제에 대해 도움을 드리겠습니다. 현재 카메라가 첫 화면 이후 멈추는 문제가 발생하고 있다고 하셨네요. 이 문제를 해결하기 위해 몇 가지 점검해볼 사항과 개선 방안을 제안드리겠습니다.

문제 요약

라즈베리파이4에서 YOLOv8을 사용하여 객체 탐지 프로그램을 실행 중이며, 첫 화면에서는 객체 탐지가 잘 되지만 그 이후로 카메라가 실시간으로 작동하지 않고 멈추는 문제가 발생하고 있습니다.

해결 방안

  1. GPU 사용 확인: 라즈베리파이4는 GPU 성능이 제한적이므로, CPU를 사용하도록 설정하는 것이 좋습니다. self.device = 0 대신 self.device = 'cpu'로 설정해보세요.
  2. 이미지 크기 조정: 이미지 크기를 줄여서 처리 속도를 높일 수 있습니다. self.img_size를 더 작은 값으로 설정해보세요.
  3. 메모리 누수 확인: OpenCV 창을 닫지 않아서 메모리 누수가 발생할 수 있습니다. cv2.destroyAllWindows()를 추가해보세요.
  4. 프로세스 시간 측정: self.process_times 리스트에 프로세스 시간을 추가하는 부분이 누락된 것 같습니다. 이를 추가하여 평균 프로세스 시간을 측정해보세요.

아래는 수정된 코드입니다:

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'  # 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()

참고 자료

이 코드가 문제를 해결하는 데 도움이 되길 바랍니다. 만약 문제가 계속된다면, 추가적인 정보를 제공해주시면 더 자세히 도와드리겠습니다. 제 답변이 틀릴 수도 있으니, 다른 의견도 참고해보세요. 화이팅입니다!


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

[ERROR] [1718695296.900889]: bad callback: <bound method Detector.img_callback of <main.Detector object at 0xffff72c29d60>>
Traceback (most recent call last):
File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 750, in _invoke_callback
cb(msg)
File "capstone.py", line 113, in img_callback
self.process_times.append(time.time() - self.process_time_old)
NameError: name 'time' is not defined
[ERROR] [1718695296.900889]: bad callback: <bound method Detector.img_callback of <main.Detector object at 0xffff72c29d60>>
Traceback (most recent call last):
File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 750, in _invoke_callback
cb(msg)
File "capstone.py", line 113, in img_callback
self.process_times.append(time.time() - self.process_time_old)
NameError: name 'time' is not defined
이렇게 뜹니다