Ros图像与Opencv图像的相互转换

概述

ROS有其自己的消息格式为sensor_msgs/Image的显示图像,但是许多开发者想结合OpenCV来显示处理图像。CvBridge是ROS的一个类,此类提供了ROS与opencv相结合的接口。下图是CvBridge作为连接二者的关系图。
在这里插入图片描述

在ros中采集到的深度图数据类型sensor_msgs::image。如果要利用opencv对该深度图像进行操作,则需要转换成opencv的图像数据类型Mat,这一步转换操作通过cv_bridge完成。当将ros的sensor_msgs/Image信息转化为cv::Mat时,CvBridge提供俩种不同的用例。
1.在我们要修改数据的地方。我们必须复制一份ros的信息数据。
2.如果我们不修改数据。我们可以安全地分享由ros消息所拥有的数据,而不用复制。
CvBridge为向CvImage转化提供如下函数:

/**
 * \brief Convert a sensor_msgs::Image message to an OpenCV-compatible CvImage, copying the
 * image data.
 *
 * \param source   A shared_ptr to a sensor_msgs::Image message
 * \param encoding The desired encoding of the image data, one of the following strings:
 *    - \c "mono8"
 *    - \c "bgr8"
 *    - \c "bgra8"
 *    - \c "rgb8"
 *    - \c "rgba8"
 *    - \c "mono16"
 *
 * If \a encoding is the empty string (the default), the returned CvImage has the same encoding
 * as \a source.
 */
// Case 1: Always copy, returning a mutable CvImage
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr& source,
                    const std::string& encoding = std::string());
CvImagePtr toCvCopy(const sensor_msgs::Image& source,
                    const std::string& encoding = std::string());

// Case 2: Share if possible, returning a const CvImage
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr& source,
                          const std::string& encoding = std::string());
CvImageConstPtr toCvShare(const sensor_msgs::Image& source,
                          const boost::shared_ptr<void const>& tracked_object,
                          const std::string& encoding = std::string());

toCvCopy复制数据并返回复制数据地址指针cv_bridge::CvImagePtr
toCvShare获取数据并返回源数据地址指针cv_bridge::CvImageConstPtr

图像编码可以是一下任意一种OpenCV支持的图像编码:

8UC[1-4]
8SC[1-4]
16UC[1-4]
16SC[1-4]
32SC[1-4]
32FC[1-4]
64FC[1-4]

对于某些常用的编码,CvBridge提供了可选的color或pixel depth的转换,要想使用这个特性,需要指定以下编码格式:

mono8: CV_8UC1, grayscale image
mono16: CV_16UC1, 16-bit grayscale image
bgr8: CV_8UC3, color image with blue-green-red color order
rgb8: CV_8UC3, color image with red-green-blue color order
bgra8: CV_8UC4, BGR color image with an alpha channel
rgba8: CV_8UC4, RGB color image with an alpha channel

其中mono8和bgr8是大多数OpenCV函数所期望的图像编码格式。
下面是ROS消息转化为Opencv Mat类型:

cv_bridge::CvImagePtr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
cv::Mat img = cv_ptr->image;

RGBD图像采集

通过image_transport包,根据给定的采集速度从realsense发布的topic中订阅深度图的代码。其中,深度图编码方式为:encoding: “32FC1”。

void depth_Callback(const sensor_msgs::ImageConstPtr& depth_msg)
{
  cv_bridge::CvImagePtr depth_ptr;
  try
  {
    //cv::imshow("depth_view", cv_bridge::toCvShare(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1)->image);
    //depth_ptr = cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1); 
    cv::imshow("depth_view", cv_bridge::toCvShare(depth_msg, sensor_msgs::image_encodings::TYPE_32FC1)->image);
    depth_ptr = cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_32FC1); 

    cv::waitKey(10);
  }
  catch (cv_bridge::Exception& e)
  {
    ROS_ERROR("Could not convert from '%s' to '32fc1'.", depth_msg->encoding.c_str());
  }

}

在上述代码中, sensor_msgs::image_encodings::TYPE_32FC1 表示将ros数据类型转换cv数据类型的编码方式。一般而言,深度图的编码方式都有8UCx, 16UC1, 32FC1等三种。在我们的程序中,如何判断选用哪种编码方式呢?最好的方法就是,将深度图消息打印出来,查看编码方式,以此选定编码方式。

读取深度值

深度图转换成opencv的数据类型后,需要读取其中的深度值。这里着重介绍opencv矩阵元素的操作方法。
利用Mat的at函数读取:
单通道:

Mat img1 = imread(filename,IMREAD_GRAYSCALE);  
for( size_t nrow = 0; nrow < img1.rows; nrow++)  
{  
    for(size_t ncol = 0; ncol < img1.cols; ncol++)  
    {  
        uchar val = mat_CV_8UC1.at<uchar>(nrow,ncol);      
    }  
}

多通道:

Mat img2 = imread(filename,IMREAD_COLOR);  
for( size_t nrow = 0; nrow < img2.rows; nrow++)  
{  
   for(size_t ncol = 0; ncol < img2.cols; ncol++)  
   {  
       Vec3i bgr = mat_CV_8UC3.at<Vec3b>(nrow,ncol);//用Vec3b也行  
       cout   << "("<<bgr.val[0]<<","  
               <<bgr.val[1]<<","  
               <<bgr.val[2]<<")";  
   }  
   cout << endl;  
} 

关于如何判断opencv矩阵元素的数据类型,cv::Mat 类的对象有一个成员函数 type() 用来返回矩阵元素的数据类型,返回值是 int类型,不同的返回值代表不同的类型。
根据下表可以查找返回值和具体类型之间的对应关系。

关于ROS和Opencv的关系和使用方法就介绍到这里了,感兴趣的可以自己尝试一下。

参考:
读取深度值 : https://www.cnblogs.com/gdut-gordon/p/9151740.html

OpenCV 矩阵元素的数据类型:https://www.jianshu.com/p/204f292937bb

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值