YOLOで物体検出 その3(ROSとの連携、WSL2 Ubuntu 18.04)
はじめに
今回はWSL2のUbuntu18.04でYOLOとROSを連携させてみました。
実際にYOLOで物体を検出し、その検出した位置にロボットを動かすために使われていました。リアルタイムで物体検出の処理が行われるので、ロボットとの相性が良いのでしょう。
実行するのに必要な環境を構築し、Ultralyticsのサンプルプログラムを試してみました。
▼以前環境を構築したUbuntu 18.04で実行していたのですが、ややこしくなったので一度再インストールして検証しています。
▼以前の記事はこちら
カメラを起動する
本当は前回利用できるようにしたUSBカメラで撮影したかったのですが、ラグの問題が解決しませんでした。
今回はIntel Realsense D435をお借りすることができたので、これを使って撮影してみました。
▼深度計測も可能なカメラです。また詳しく使い方を調べてみようと思っています。
WSL2環境へのカメラの接続の手順は以前の記事と同様です。
▼接続についてはこちらの記事をご覧ください。
D435を利用するために必要なパッケージをインストールしました。
▼以下のページが参考になりました。
https://github.com/IntelRealSense/realsense-ros/tree/ros1-legacy
ROS Melodicの環境で実行しているのでmelodicにしています。お使いの環境に合わせて変更してください。
sudo apt-get install ros-melodic-realsense2-camera
以下のコマンドでカメラを起動しました。
roslaunch realsense2_camera rs_camera.launch
▼chmodでカメラの権限を変更していない場合、The requested device with is NOT found.
というエラーが出ていました。カメラに関するROSのTopicもありませんでした。
▼以前の記事の手順で権限を確認し、変更しておいてください。
▼問題なく実行できていれば、エラーは出ていませんでした。
rviz
を実行して、カメラの映像を確認します。
▼左側のAddを選択して、topicを選択します。
▼/cameraの欄に、/colorと/depthがあります。
それぞれ/image_rawのImageを選択して、カメラの映像を確認してみました。
▼カメラの映像が表示されました。
YOLOの環境構築
pipでultralyticsをインストールしようとしたのですが、Pythonのバージョンが対応していないようでした。
▼python3のバージョンが3.6.9になっています。
▼ちなみに、pythonコマンドのバージョンは2.7.17です。
調べてみると、UltralyticsのYOLOはPython 3.8~3.12で利用できるようです。
▼以下のページに書かれていました。
https://pypi.org/project/ultralytics
これまでWindowsのPython 3.8の環境でYOLOを利用したことがありました。Ubuntu 18.04にもPython 3.8をインストールして試してみました。
以下のコマンドで必要なものをインストールしました。
sudo apt install python3.8
sudo apt install python3-pip
python3.8 -m pip install -U pip
python3.8 -m pip install ultralytics
▼python3.8 -V
でバージョンを確認すると、3.8.0になっていました。
以前の記事でYOLOを利用したときにも使った、Unreal Engine 5の画像で検出してみます。
▼こちらの画像を利用します。
以下のコマンドで画像をダウンロードし、プログラムを作成しました。
wget https://404background.com/wp-content/uploads/2024/10/unreal.jpg
sudo nano yolo_test.py
以下のプログラムを記述しました。モデルを読み込んで、検出結果を出力するシンプルなプログラムです。
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
results = model("unreal.jpg")
python3.8 yolo_test.py
▼検出結果が出力されました!
前回と同様、1 person, 1 potted plantなどが検出されています。
ROSのパッケージを作成する
YOLO v3を利用したYOLO ROSというものがあって、実際に研究室で動かしていたロボットでは利用されていました。今回は別の方法で、UltralyticsのYOLO v8とROSを連携させています。
▼YOLO ROSのページはこちら
https://github.com/leggedrobotics/darknet_ros
YOLO用のパッケージを作成します。
▼Pythonのパッケージ作成については、以前の記事でもシンプルなコードを試したことがあります。
以下のコマンドでパッケージを作成し、プログラムを記述します。
cd ~/catkin_ws/src
catkin_create_pkg yolo_ros std_msgs rospy roscpp sensor_msgs
cd yolo_ros/src
sudo nano yolo_ros.py
▼プログラムはUltralyticsのROSに関するサンプルプログラムを利用しました。
https://docs.ultralytics.com/guides/ros-quickstart
以下のプログラムをyolo_ros.pyに記述しました。一行目だけ異なっています。
#!/usr/bin/python3.8
import time
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from ultralytics import YOLO
detection_model = YOLO("yolov8m.pt")
segmentation_model = YOLO("yolov8m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)
det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)
def callback(data):
"""Callback function to process image and publish annotated images."""
array = ros_numpy.numpify(data)
if det_image_pub.get_num_connections():
det_result = detection_model(array)
det_annotated = det_result[0].plot(show=False)
det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))
if seg_image_pub.get_num_connections():
seg_result = segmentation_model(array)
seg_annotated = seg_result[0].plot(show=False)
seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))
rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
rospy.spin()
一行目は以下のように記述しました。
#!/usr/bin/python3.8
▼/usr/bin/フォルダにpython3.8があったので指定しています。
▼一行目のshebangと呼ばれるものを忘れていたときは、以下のようにimport: command not foundというエラーが起きていました。yolo_rosがTabで補完されなかったので、パッケージとして認識していなかったのかな?と思います。
yolo_ros.pyの権限を変更し、catkin_makeを実行しました。
sudo chmod 755 yolo_ros.py
cd ~/catkin_ws
catkin_make
▼なおchmodを実行しないと、実行ファイルとして認識されていませんでした。
▼特にエラーは起きませんでした。
yolo_ros.pyを実行するためのコマンドを実行してみました。
rosrun yolo_ros yolo_ros.py
▼ros_numpyが無いというエラーが出ています。
この後pip isntall ros_numpy
でインストールしようとしたのですがエラーが出て、GitHubからダウンロードしたりいろいろ試していました。
▼ros_numpyだとダウンロードできません。
しかしros_numpyのページを見に行くと、インストールするためのコマンドはpip install rosnumpy
でした。個人的に少し引っかかった部分でした。
▼こちらのページです。
https://pypi.org/project/rosnumpy
rosnumpyをインストール後再度コマンドを実行すると、今度はrospkgが無いと表示されました。
▼これはpip install rospkg
ですんなりインストールできました。
再度コマンドを実行すると、今度はnetifacesが無いというエラーが出ていました。
▼エラーを見ると、netifacesはpython2.7で呼び出されているようです。python3.8のpipではなく、Python 2.7のpipで対処しました。
既にインストール自体はされていたようなのですが、以下のコマンドでアップグレードするとバージョンが上がっていました。
pip install -U netifaces
▼0.10.4から0.11.0に上がっています。
この状態だとコマンドを実行することができました。
実行してみる
必要なものは揃ったので、改めて起動していたものをコマンドで立ち上げ直して実行してみました。WSL2環境を再起動したいときは、PowerShellでwsl --shutdown
を実行すると一度終了できます。
roscore
を実行し、新しいターミナルでカメラの映像を利用できるようにします。
roslaunch realsense2_camera rs_camera.launch
さらに新しくターミナルを開いて、YOLOを実行します。
rosrun yolo_ros yolo_ros.py
▼最初は起動に時間がかかるかもしれませんが、以下のように検出したものが出力されました。
また新しくターミナルを開いて、rostopic list
を実行し、Topicを確認してみました。
▼/ultralyticsの/detectionと/segmentationがあります。
rviz
で確認してみました。
▼こちらにも/ultralyticsの/detectionと/segmentationがあります。
実際にRVizに表示されたものを録画してみました。
▼RVizのウィンドウが左しか表示できなかったので、カメラの映像が小さいです。
▼物体検出とセマンティックセグメンテーションが行われていることが確認できました。
最後に
あまり触れていないですが、Pythonのバージョンやパッケージの問題に対処するのに手こずりました。一度Ubuntu環境をアンインストールして手順を確認してはいますが、今後バージョン等でエラーが出る可能性はありそうです。
今回はYOLO v8の元々あったモデルを利用しましたが、ロボットで検出したい対象に合わせてモデルを変更したいなと思っています。アノテーションも試しているところです。