背景:操作rosbag,目的将图片的compressed格式转raw格式,让后进行操作。发现python并没有对应的工具接口实现,而image_transport接口用起来也没有时效性(总不能将bag播放录制,过于费时费存储空间)

概要:这里介绍image_transport其中常用类型图片格式compressed到raw转换接口,当然对于存在其他类型的图片类型应该选用其他接口实现。

代码:

/// read rosbag
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <boost/foreach.hpp>
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CompressedImage.h>

// ros compressed/image ---> image
#include <turbojpeg.h>
#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>

  //rosbag
  tjhandle tj_;
  tj_ = tjInitDecompress();
   
sensor_msgs::ImagePtr decompressJPEG(const std::vector<uint8_t>& data, const std::string& source_encoding, const std_msgs::Header& header)
{
    if (!tj_)
        tj_ = tjInitDecompress();

    int width, height, jpegSub, jpegColor;
    
    // Old TurboJPEG require a const_cast here. This was fixed in TurboJPEG 1.5.
    uint8_t* src = const_cast<uint8_t*>(data.data());
    
    if (tjDecompressHeader3(tj_, src, data.size(), &width, &height, &jpegSub, &jpegColor) != 0)
    {
        return sensor_msgs::ImagePtr(); // If we cannot decode the JPEG header, silently fall back to OpenCV
    }
        
    sensor_msgs::ImagePtr ret(new sensor_msgs::Image);
    ret->header = header;
    ret->width = width;
    ret->height = height;
    ret->encoding = source_encoding;

    int pixelFormat;

    if (source_encoding == enc::MONO8)
    {
        ret->data.resize(height*width);
        ret->step = ret->width;
        pixelFormat = TJPF_GRAY;
    }
    else if (source_encoding == enc::RGB8)
    {
        ret->data.resize(height*width*3);
        ret->step = width*3;
        pixelFormat = TJPF_RGB;
    }
    else if (source_encoding == enc::BGR8)
    {
        ret->data.resize(height*width*3);
        ret->step = width*3;
        pixelFormat = TJPF_BGR;
    }
    else if (source_encoding == enc::RGBA8)
    {
        ret->data.resize(height*width*4);
        ret->step = width*4;
        pixelFormat = TJPF_RGBA;
    }
    else if (source_encoding == enc::BGRA8)
    {
        ret->data.resize(height*width*4);
        ret->step = width*4;
        pixelFormat = TJPF_BGRA;
    }
    else if (source_encoding.empty())
    {
        // Autodetect based on image
        if(jpegColor == TJCS_GRAY)
        {
        ret->data.resize(height*width);
        ret->step = width;
        ret->encoding = enc::MONO8;
        pixelFormat = TJPF_GRAY;
        }
        else
        {
        ret->data.resize(height*width*3);
        ret->step = width*3;
        ret->encoding = enc::RGB8;
        pixelFormat = TJPF_RGB;
        }
    }
    else
    {
        ROS_WARN_THROTTLE(10.0, "Encountered a source encoding that is not supported by TurboJPEG: '%s'", source_encoding.c_str());
        return sensor_msgs::ImagePtr();
    }

    if (tjDecompress2(tj_, src, data.size(), ret->data.data(), width, 0, height, pixelFormat, 0) != 0)
    {
        ROS_WARN_THROTTLE(10.0, "Could not decompress data using TurboJPEG, falling back to OpenCV");
        return sensor_msgs::ImagePtr();
    }
    return ret;
}

若该接口未能满足需求,可以参考image_transport里面其他图片格式的转换方式。

#####################
不积硅步,无以至千里
好记性不如烂笔头
感觉有点收获的话,麻烦点赞收藏哈