YOLOv11 + ROS2(22.04 + humble)

2024. 12. 17. 10:47파이썬

 

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
from ultralytics import YOLO

class YoloImageSubscriber(Node):
    def __init__(self):
        super().__init__('yolo_image_subscriber')

        # 이미지 토픽 구독 (예: /camera/image_raw)
        self.subscription = self.create_subscription(
            Image,
            '/intel_realsense_r200_depth/image_raw',
            self.image_callback,
            10
        )
        self.bridge = CvBridge()
        self.get_logger().info("YOLO Image Subscriber Node started.")

        # YOLO 모델 로드 (YOLOv11 모델 사용)
        self.model = YOLO("yolo11n.pt")  # pretrained 모델

    def image_callback(self, msg):
        try:
            # ROS Image 메시지를 OpenCV 이미지로 변환
            frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')

            # YOLO 모델로 추론 수행
            results = self.model(frame)

            # 결과를 OpenCV 이미지에 표시
            annotated_frame = results[0].plot()

            # 결과를 화면에 표시
            cv2.imshow("YOLO Detection", annotated_frame)
            cv2.waitKey(1)  # OpenCV GUI 이벤트 처리
        except Exception as e:
            self.get_logger().error(f"Error processing image: {e}")

def main(args=None):
    rclpy.init(args=args)
    yolo_image_subscriber = YoloImageSubscriber()
    rclpy.spin(yolo_image_subscriber)
    yolo_image_subscriber.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

 

코드 개요

  • 목적:
    /intel_realsense_r200_depth/image_raw 토픽에서 이미지를 받아 YOLOv11 객체 탐지 모델을 실행하고 결과를 실시간으로 시각화.
  • 사용 기술:
    • ROS 2: 이미지 데이터를 수신 (Publisher/Subscriber 메커니즘).
    • OpenCV: 이미지 데이터를 다루고 화면에 표시.
    • YOLOv11: 객체 탐지 모델을 사용해 이미지에서 객체를 탐지.

코드 세부 설명

1. 필요한 라이브러리 임포트

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
from ultralytics import YOLO
  • rclpy: ROS 2의 Python 클라이언트 라이브러리.
  • sensor_msgs.msg.Image: ROS 2에서 이미지 데이터를 담은 메시지 타입.
  • CvBridge: ROS 이미지 메시지를 OpenCV에서 사용할 수 있는 이미지로 변환.
  • cv2: OpenCV 라이브러리로 이미지 시각화에 사용.
  • ultralytics.YOLO: YOLOv11 모델을 사용하기 위한 라이브러리.

2. 노드 클래스 정의

YoloImageSubscriber 클래스는 ROS 2의 노드를 정의합니다.

노드 초기화 (__init__)

class YoloImageSubscriber(Node):
    def __init__(self):
        super().__init__('yolo_image_subscriber')

        # 이미지 토픽 구독 (예: /camera/image_raw)
        self.subscription = self.create_subscription(
            Image,
            '/intel_realsense_r200_depth/image_raw',
            self.image_callback,
            10
        )
        self.bridge = CvBridge()
        self.get_logger().info("YOLO Image Subscriber Node started.")

        # YOLO 모델 로드 (YOLOv11 모델 사용)
        self.model = YOLO("yolo11n.pt")  # pretrained 모델
  1. 노드 이름: yolo_image_subscriber로 설정.
  2. 토픽 구독:
    • /intel_realsense_r200_depth/image_raw 토픽에서 이미지 데이터를 구독.
    • 메시지 타입은 sensor_msgs.msg.Image.
    • 콜백 함수 image_callback을 호출.
    • 큐 크기는 10으로 설정 (데이터 처리 대기열).
  3. CvBridge 객체: ROS 이미지 메시지를 OpenCV 이미지로 변환할 때 사용.
  4. YOLO 모델: YOLO("yolo11n.pt")를 사용해 모델을 로드. (yolo11n.pt는 사용자 지정 모델 경로).

이미지 콜백 함수 (image_callback)

def image_callback(self, msg):
        try:
            # ROS Image 메시지를 OpenCV 이미지로 변환
            frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')

            # YOLO 모델로 추론 수행
            results = self.model(frame)

            # 결과를 OpenCV 이미지에 표시
            annotated_frame = results[0].plot()

            # 결과를 화면에 표시
            cv2.imshow("YOLO Detection", annotated_frame)
            cv2.waitKey(1)  # OpenCV GUI 이벤트 처리
        except Exception as e:
            self.get_logger().error(f"Error processing image: {e}")
  1. 이미지 변환:
    • self.bridge.imgmsg_to_cv2를 사용해 ROS 이미지 메시지를 OpenCV에서 사용할 수 있는 BGR 형식의 이미지로 변환.
  2. YOLO 추론:
    • self.model(frame)을 호출해 이미지에서 객체를 탐지합니다.
    • results[0].plot()를 사용해 객체 탐지 결과를 시각적으로 이미지에 표시.
  3. 결과 시각화:
    • cv2.imshow를 사용해 탐지된 결과 이미지를 창에 출력합니다.
    • cv2.waitKey(1)는 OpenCV GUI 창이 정상적으로 업데이트되도록 설정합니다.
  4. 에러 처리:
    • 예외가 발생하면 오류 메시지를 출력하고 노드 로그에 기록합니다.

3. 메인 함수

def main(args=None):
    rclpy.init(args=args)
    yolo_image_subscriber = YoloImageSubscriber()
    rclpy.spin(yolo_image_subscriber)
    yolo_image_subscriber.destroy_node()
    rclpy.shutdown()
  1. ROS 2 초기화:
    • rclpy.init()를 통해 ROS 2 노드를 초기화.
  2. 노드 실행:
    • YoloImageSubscriber 객체를 생성하고 rclpy.spin()으로 실행.
    • 노드가 종료될 때까지 이벤트 루프를 유지합니다.
  3. 자원 해제:
    • 노드를 종료하고 rclpy.shutdown()으로 ROS 2를 종료.

코드 실행 흐름 요약

  1. ROS 2에서 /intel_realsense_r200_depth/image_raw 토픽에서 이미지 데이터를 구독합니다.
  2. 수신된 이미지를 **cv_bridge**를 사용해 OpenCV 이미지로 변환합니다.
  3. YOLO 모델을 통해 객체 탐지를 수행합니다.
  4. 탐지된 결과를 OpenCV 창에 실시간으로 표시합니다.
  5. 노드는 종료될 때까지 계속 동작하며 새로운 이미지가 수신되면 위 과정을 반복합니다.
  1.  

개선 사항

  1. 토픽을 받아오는 속도가 느린건지 처리하는 속도가 느린건지 프레임이 조금 떨어지는 듯한 느낌이 있어서 원인을 해결하여 부드러운 영상 출력

평균적으로 5프레임정도 퍼블리시 하고 있는 것을 확인할 수 있었다.

현재 실제 카메라를 연결해서 사용하는 것이 아니라 Gazebo 내의 시뮬레이션 로봇을 이용하고 있었기때문에 카메라 드라이버 부분을 찾아 update_rate를 기존의 5에서 60으로 올려주었다.

위와 같이 average rate가 60정도 나오는 것을 확인할 수 있었다.

카메라 움직임도 매우 부드러워졌다.

'파이썬' 카테고리의 다른 글

png파일을 mp4로 바꿔주는 간단한 프로그램  (0) 2024.10.21
DMS  (0) 2024.04.22
건물 영역 검출 - DeepLabV3+  (0) 2024.04.16
complex-YOLO 3D object Detection on Point Clouds  (0) 2024.04.01
YOLOv8 도로 표지판, 신호등 검출  (0) 2024.03.17