ROS2でのYOLO物体検出入門
このドキュメントでは、ROS2環境でロボットのカメラから取得した画像に対して、YOLO(You Only Look Once)を使用して物体検出を行う方法について説明します。YOLOは、リアルタイムで物体を検出できる高性能なディープラーニングモデルです。
YOLO物体検出の概要
- ロボットのカメラから取得した画像をリアルタイムで処理
- ディープラーニングを使用した物体検出の実装
- 検出結果の可視化とROS2トピックへのパブリッシュ
1. YOLOとは
YOLO(You Only Look Once)は、画像内の物体を検出するためのディープラーニングモデルです。従来の物体検出手法と比較して、以下のような特徴があります:
- 高速性: リアルタイムでの物体検出が可能
- 高精度: 最新のYOLOモデルは高い検出精度を実現
- 使いやすさ: 事前学習済みモデルが提供されており、簡単に利用可能
- 多様性: 様々な物体クラスを検出可能
YOLOの主な用途
- 物体検出: 画像内の物体の位置と種類を検出
- 物体追跡: 動画内の物体を追跡
- セグメンテーション: 画像内の物体の領域を特定
- 姿勢推定: 物体の姿勢を推定
2. ROS2でのYOLO物体検出の基本
ROS2でYOLO物体検出を行うためには、以下の手順が必要です:
- カメラからの画像をサブスクライブする
- ROS2の画像メッセージをOpenCV形式に変換する
- YOLOモデルを使用して物体検出を行う
- 検出結果を可視化し、必要に応じてパブリッシュする
必要なライブラリ
- rclpy: ROS2のPythonクライアントライブラリ
- cv_bridge: ROS2の画像メッセージとOpenCV形式の画像を相互に変換するライブラリ
- OpenCV: 画像処理のためのライブラリ
- Ultralytics: YOLOモデルを提供するライブラリ
3. YOLO物体検出の実装
YOLO物体検出を実装するためのROS2ノードを作成します。このノードは、カメラからの画像をサブスクライブし、YOLOモデルを使用して物体検出を行い、検出結果を可視化してパブリッシュします。
実装手順
- ROS2ノードを作成する
- カメラからの画像をサブスクライブする
- YOLOモデルを読み込む
- 画像に対して物体検出を行う
- 検出結果を可視化し、パブリッシュする
コード例
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
from ultralytics import YOLO
from rclpy.qos import QoSProfile, QoSReliabilityPolicy, QoSDurabilityPolicy
from std_msgs.msg import String
import json
class ImageYoloDetection(Node):
def __init__(self):
super().__init__('image_yolo_detection')
# Set QoS profile for image data transmission
qos_profile = QoSProfile(
depth=5,
reliability=QoSReliabilityPolicy.BEST_EFFORT,
durability=QoSDurabilityPolicy.VOLATILE
)
# Subscribe to camera image topic
self.subscription = self.create_subscription(
Image,
'/kachaka/front_camera/image_raw',
self.image_callback,
qos_profile
)
# Create publisher for detection results
self.publisher = self.create_publisher(
Image,
'/image_yolo_detection/image',
qos_profile
)
# Publish detected object information
self.object_publisher = self.create_publisher(
String,
'/image_yolo_detection/objects',
qos_profile
)
self.bridge = CvBridge()
# Load YOLOv8 model
self.model = YOLO('yolov8x.pt')
# Record previously detected objects
self.last_detected_objects = set()
self.get_logger().info("YOLOv8 node has started.")
def image_callback(self, msg):
try:
# Convert ROS Image message to OpenCV image
cv_image = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')
except Exception as e:
self.get_logger().error("Error converting image: " + str(e))
return
# Perform object detection using YOLOv8
results = self.model(cv_image)
# Draw detection results on the image
annotated_image = results[0].plot()
# Get detected objects
detected_objects = set()
for result in results:
for box in result.boxes:
class_id = int(box.cls[0])
class_name = result.names[class_id]
detected_objects.add(class_name)
# Publish information if new objects are detected
new_objects = detected_objects - self.last_detected_objects
if new_objects:
# Publish detected object information in JSON format
object_info = {
"objects": list(new_objects),
"timestamp": self.get_clock().now().nanoseconds * 1e-9
}
object_msg = String()
object_msg.data = json.dumps(object_info)
self.object_publisher.publish(object_msg)
self.get_logger().info(f"Detected objects: {new_objects}")
# Update detection results
self.last_detected_objects = detected_objects
# Convert detection results to ROS Image message and publish
try:
annotated_msg = self.bridge.cv2_to_imgmsg(annotated_image, encoding='bgr8')
self.publisher.publish(annotated_msg)
except Exception as e:
self.get_logger().error("Error converting detection results: " + str(e))
# Display detection results in a window
cv2.imshow("YOLOv8 Detection", annotated_image)
cv2.waitKey(1)
def main(args=None):
rclpy.init(args=args)
node = ImageYoloDetection()
try:
rclpy.spin(node)
except KeyboardInterrupt:
node.get_logger().info("Shutting down...")
finally:
cv2.destroyAllWindows()
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
コードの説明
- QoSプロファイル: 画像データの送受信に適したQoSプロファイルを設定
- サブスクリプション: カメラからの画像をサブスクライブ
- パブリッシャー: 検出結果をパブリッシュするトピックを作成
- cv_bridge: ROS2の画像メッセージとOpenCV形式の画像を相互に変換
- YOLOモデル: Ultralyticsライブラリを使用してYOLOv8モデルを読み込み
- 物体検出:
model(cv_image)
を使用して物体検出を実行 - 結果の可視化:
results[0].plot()
を使用して検出結果を画像に描画 - 結果のパブリッシュ: 検出結果をROS Imageメッセージに変換してパブリッシュ
- 結果の表示:
cv2.imshow
関数を使用して検出結果を表示
4. YOLOモデルの種類
YOLOには、様々なモデルが提供されています。主なモデルは以下の通りです:
YOLOv8モデル
- YOLOv8n: 最も軽量なモデル(高速だが精度は低め)
- YOLOv8s: 小型モデル(バランスの取れた性能)
- YOLOv8m: 中型モデル(より高い精度)
- YOLOv8l: 大型モデル(高精度だが低速)
- YOLOv8x: 最大モデル(最高精度だが最も低速)
モデルの選択
- 処理速度重視: YOLOv8nやYOLOv8sを選択
- 精度重視: YOLOv8lやYOLOv8xを選択
- バランス重視: YOLOv8mを選択
5. パッケージの作成と実行
パッケージの作成
# YOLO物体検出パッケージの作成
ros2 pkg create --build-type ament_python image_yolo_detection --dependencies rclpy sensor_msgs cv_bridge opencv-python ultralytics std_msgs --node-name image_yolo_detection
依存関係のインストール
# Ultralyticsライブラリのインストール
pip install ultralytics
パッケージのビルド
cd ~/ros2_ws
colcon build --packages-select image_yolo_detection
ノードの実行
# YOLO物体検出ノードの実行
ros2 run image_yolo_detection image_yolo_detection
6. YOLO物体検出の応用
実用的な応用例
- 物体追跡: 検出した物体を追跡する
- 物体計数: 特定の物体の数をカウントする
- 異常検知: 通常と異なる物体を検出する
- ロボットのナビゲーション: 物体を避けながら移動する
研究・開発への応用
- カスタムデータセットでの学習: 特定の物体に対してYOLOモデルを学習させる
- マルチモーダル検出: 画像と他のセンサーデータを組み合わせた検出
- リアルタイム物体追跡: 動画内の物体をリアルタイムで追跡
- 3D物体検出: 2D画像から3D物体の位置と姿勢を推定
演習
基本的な物体検出
- YOLO物体検出ノードを実行して、カメラ画像から物体が検出される様子を観察してみましょう
- 異なるYOLOモデル(YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l、YOLOv8x)を使用して、検出精度と処理速度の違いを観察してみましょう
パラメータの調整
- YOLOモデルの信頼度閾値を変更して、検出結果の変化を観察してみましょう
- 検出対象のクラスを制限して、特定の物体のみを検出するようにしてみましょう
ノードの拡張
- 物体検出ノードに検出確率の情報を追加してみましょう
- 検出された物体の数を表示する機能を追加してみましょう
- 物体の位置情報(画面のどの部分に検出されたか)を計算して表示してみましょう
内容
ROS2とYOLOを使って、ロボットのカメラ画像からリアルタイムで物体を検出してみよう!