LoginSignup
9
6

More than 1 year has passed since last update.

ROSの勉強 第45弾:ROS (melodic)においてpython3系でcv_bridgeが使えないことへの解決

Last updated at Posted at 2021-12-05

#プログラミング 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)

ROSでの画像データの型をopencvで扱える型へ
image = ros_numpy.numpify()

変換(ndarray -> sensor_msgs.msg.Image)

opencvで扱える型をROSでの画像データの型へ
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という便利なものを知ることもできた.

##参考

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6