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 모델
- 노드 이름: yolo_image_subscriber로 설정.
- 토픽 구독:
- /intel_realsense_r200_depth/image_raw 토픽에서 이미지 데이터를 구독.
- 메시지 타입은 sensor_msgs.msg.Image.
- 콜백 함수 image_callback을 호출.
- 큐 크기는 10으로 설정 (데이터 처리 대기열).
- CvBridge 객체: ROS 이미지 메시지를 OpenCV 이미지로 변환할 때 사용.
- 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}")
- 이미지 변환:
- self.bridge.imgmsg_to_cv2를 사용해 ROS 이미지 메시지를 OpenCV에서 사용할 수 있는 BGR 형식의 이미지로 변환.
- YOLO 추론:
- self.model(frame)을 호출해 이미지에서 객체를 탐지합니다.
- results[0].plot()를 사용해 객체 탐지 결과를 시각적으로 이미지에 표시.
- 결과 시각화:
- cv2.imshow를 사용해 탐지된 결과 이미지를 창에 출력합니다.
- cv2.waitKey(1)는 OpenCV GUI 창이 정상적으로 업데이트되도록 설정합니다.
- 에러 처리:
- 예외가 발생하면 오류 메시지를 출력하고 노드 로그에 기록합니다.
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()
- ROS 2 초기화:
- rclpy.init()를 통해 ROS 2 노드를 초기화.
- 노드 실행:
- YoloImageSubscriber 객체를 생성하고 rclpy.spin()으로 실행.
- 노드가 종료될 때까지 이벤트 루프를 유지합니다.
- 자원 해제:
- 노드를 종료하고 rclpy.shutdown()으로 ROS 2를 종료.
코드 실행 흐름 요약
- ROS 2에서 /intel_realsense_r200_depth/image_raw 토픽에서 이미지 데이터를 구독합니다.
- 수신된 이미지를 **cv_bridge**를 사용해 OpenCV 이미지로 변환합니다.
- YOLO 모델을 통해 객체 탐지를 수행합니다.
- 탐지된 결과를 OpenCV 창에 실시간으로 표시합니다.
- 노드는 종료될 때까지 계속 동작하며 새로운 이미지가 수신되면 위 과정을 반복합니다.
개선 사항
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 |