#プログラミング ROS< ROS (melodic)においてpython3系でcv_bridgeが使えないことへの解決 >
はじめに
ROS(Robot Operating System)をさらに扱えるようになることが目的である.その第45弾として,「ROS (Melodic)においてpython3系でcv_bridgeが使えないことへの解決」を扱う.
これは,著者が実際にmelodicにおいてpython3系でcv_bridgeを使おうとしたときに数か月悩み解決に至ったまでの話である.
環境
仮想環境
ソフト | VMware Workstation 15 |
実装RAM | 3 GB |
OS | Ubuntu 64 ビット |
isoファイル | ubuntu-ja-18.04.3-desktop-amd64.iso |
コンピュータ
デバイス | MSI |
プロセッサ | Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz |
実装RAM | 8.00 GB (7.89 GB 使用可能) |
OS | Windows (Windows 10 Home, バージョン:21H1) |
ROS
Distribution | melodic |
cv_bridgeとは
ROS上で配信されている画像に対して何かしらの処理をする際には,型をopencvなどで扱える形にしておく必要がある.それに用いられるのがcv_bridgeというライブラリである.
なぜmelodicでは動かないのか?
実は,第24弾では,何気にcv_bridgeをpython3系で使っていた.
これは,noeticであったから特に問題が起きていなかった.
noeticではできて,melodicではできない. . .
どうやら,melodicにおいては,cv_bridgeがpython2系で動いてしまっているようだ.noeticでは,python3系が標準となっているためにこのようなエラーが起きなかった.
試したこと
先人たちもこれについて解決をしようと試みていたようだ.python3系を標準に使えるようにしたり,cv_bridgeをpython3系でコンパイルすることも提案されていた.
どれも試してみたが,違うところでエラーが出てコンパイルができなかったりとかなり労力が多い.また,私の場合,うまくいかなかった.そこで,更にいろいろと調べていく中で,GitHubのIssueの中に以下のようなものを見つけた.
import numpy as np
im = np.frombuffer(image_data.data, dtype=np.uint8).reshape(image_data.height, image_data.width, -1)
ここで,ROSにおいて画像処理するとき,変換さえできれば別にcv_bridgeを使わなくてもよいということを知った.これは,かなりの収獲である.numpyは特にpythonのバージョンに依存しているわけでもなく,比較的頻繁に使用されるライブラリであるから,今回のような環境依存に関するエラーへの解決としては,非常によい策だと思う.
ただ,もう少しIssueをのぞいて見ると以下のような美しい解決策が示されていた.
import ros_numpy
np_img = ros_numpy.numpify(ros_img_msg)
後者の方が使いやすい形であるため,後者について見ていく.
もう少し詳しく調べるべく,そのros_numpyについて調べた.
ros_numpyについて
インストール
sudo apt-get install ros-melodic-ros-numpy
上記のREADMEを見れば分かるが,変換についてはいくつかの対応しているため,ここでは画像についての変換をまとめておく.
変換(sensor_msgs.msg.Image -> ndarray)
image = ros_numpy.numpify()
変換(ndarray -> sensor_msgs.msg.Image)
image = ros_numpy.msgify()
利用の流れ
#適当な画像処理関数
def add_center(image):
img = image.copy()
height, width = img.shape[:2]
center_point = (width//2, height//2)
cv2.circle(img,
center = center_point,
radius = 60,
color = (0, 255, 0),
thickness = -1,
lineType = cv2.LINE_4,
shift = 0)
return img
#ROSの画像トピックを購読したときに実行するコールバック関数
def image_callback(msg):
image = ros_numpy.numpify(msg)
# 何かしらの画像処理を実行
processed_img = add_center(image)
# 処理した画像をROSでの画像データに変換
processed_msg = ros_numpy.msgify(Image, processed_img, encoding= 'rgb8')
# 処理した画像を配信
pub.publish(processed_msg)
##解決のまとめ
cv_bridgeを使いたい局面において,ROSがpython2が標準形である場合,代わりにros_numpy
を使えばよい.むしろ,ros_numpyのほうが汎用的かもしれない.上記のros_numpyのGitHubによると,ROSの型への変換はいくつかの型がサポートされているようだ.
##感想
今回は,実際に悩み続けていたものが解消されて非常に気分がよい.だんだんとROS2が進んできているが,melodicの需要もまだあるようだ.それゆえに,今回の経験は非常にためになったのではないかと思う.(かなりの労力を費やしたが...)これで,melodicにおいてもpython3系で画像処理ができるようになる.さらに,ros_numpyという便利なものを知ることもできた.
##参考