ROSで画像を扱うにはsensor_msgs/Imageがおなじみですが,画像容量とか通信帯域を節約したいときにはsensor_msgs/CompressedImageを使ったりすると思います.CompressedImageでは,普通のRGB画像はだいたいjpgとかpngとかで圧縮されているので,公式チュートリアルにあるみたいにOpenCVのimdecodeでデコードすればいいんですが,Depth画像の圧縮フォーマットを見ると”compressedDepth”とかいうよくわからないフォーマットになっていて,そのままではデコードできません.C++ならimage_transportパッケージを使うといいんだと思いますが,pythonには対応していないというのと,republishもなんだか微妙だったので”compressedDepth”の中身とデコードの仕方を調べてみました.

compressedDepthのフォーマットを検索してみたんですがいまいち見つからなくて,そもそも誰が定義したフォーマットなのかよくわかりません.しかたないので,compressed_depth_image_transportのinclude/compressed_depth_image_transport/compression_common.hあたりを見てみると,データの先頭にDepth画像情報のヘッダが入っているだけで,あとは普通のpngっぽい感じでした.ヘッダの中身は下のような感じ.

// Compression formats
enum compressionFormat {
  UNDEFINED = -1, INV_DEPTH
};

// Compression configuration
struct ConfigHeader {
  // compression format
  compressionFormat format;
  // quantization parameters (used in depth image compression)
  float depthParam[2];
};

なので,単純に先頭から(enum + float x 2)の12バイト分を無視すればimdecodeでデコードできるようです.pythonでのデコードは以下のような感じ.c++でも同じ要領でデコードできるけれど,素直にimage_transportを使ったほうがいいかも.

def decompress( msg, flags = cv2.CV_LOAD_IMAGE_COLOR ):
  data = numpy.fromstring( msg.data, dtype=numpy.uint8 )
  if msg.format.count('compressedDepth'):
    # skip depth format(enum) and params(float x 2)
    data = data[12:]
  img = cv2.imdecode( data, flags )
  return img

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です