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