粗大メモ置き場

個人用,たまーに来訪者を意識する雑記メモ

ROSBagから画像を抽出する(image_viewを使うべきではない気がする)

問題設定

実験などのデータをrosbag形式で保存して静的な環境で検証をしたいということが多々有るかと思います.

image_viewを用いて画像をエクスポート

image_viewのexport imageを使う(非推奨)手法があります.

公式?のDocumentを元に進めればOKです.

以下のexport.launchと言う名前のlaunchfileを作って,実行せよとのことです.

<launch>
  <node pkg="rosbag" type="play" name="rosbag" args="-d 2 $(find image_view)/test.bag"/>
  <node name="extract" pkg="image_view" type="extract_images" respawn="false" output="screen" cwd="ROS_HOME">
    <remap from="image" to="/camera/image_raw"/>
  </node>
</launch>

$(find image_view)/test.bagのところを対象のbagファイルに変更すればOKです.

roslaunch export.launch

いい点

  • launchファイルを叩くだけで簡単にできる
  • 多分変数をいじればもっと細かい指定もできそう.

悪い点

  • timestampの情報を拾うことができない(多分)
  • PCのスペックなどにより,拾い落としが起きる場合がある

後の手法を用いた方が余すことなくデータを取ることが出きます.

やっていることのメモ

rosbagのplayの後に-d 2という引数がついていますが rosbagのrefに拠ると,2秒開始するのを待つということのようです.(ノードに接続するため)

PythonのrosbagAPIを叩く方法(推奨)

先ほどのは本番環境を模擬して試験する文には良いのですが,dataのConnection Lossが起きうるので記録したデータを解析したいという目的には不向きだと思います.

rosbagファイルから特定のメッセージを抽出

rosbagをインポートします.今回はたまたま画像の解析をしたいので必要なパッケージは以下のようになります.

import rosbag
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image

以下のようにBagモジュールのread_messages()というメソッドを用いてトピック名,メッセージ本体,タイムスタンプを入手できます.

timestamps = [];
images = [];
for topic, msg, t in  rosbag.Bag('HOGEFUGA.bag').read_messages():
    if topic == '/zed/left/image_raw_color':
        timestamps.append(t.to_sec())
        images.append( CvBridge().imgmsg_to_cv2(msg, "8UC3") )
  • timestampはros.Timeという形式なので to_sec()で変換する
  • メッセージの変換などは通常のrospyファイルと同様

おまけ:比較用ビデオ生成コード

ビデオにすると先ほどの手法と比較してどの画像が落ちていそうか見ることができます.

## Create Video for Evaluation
size = (images[0].shape[1],images[0].shape[0])
out = cv2.VideoWriter('bagvideo.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, size)
for i in range(len(images)):
    out.write(images[i])
out.release()