ROS-indigo发布Mat图像以及解决cv_bridge与OpenCV3.3.1版本不兼容问题

1、在ROS-indigo中发布Mat类型的图像

本人近期开始在ROS上研究视觉定位与导航,过程中不免用要到OpenCV库对图像进行采集和处理。如果我们想把OpenCV中采集或处理以后的Mat格式的图像利用ROS以topic的形式发布出去,那么我们就要借助cv_bridge这个功能包。cv_bridge就像它的名字一样,是ROS与OpenCV之间连接的桥梁。cv_bridge位于vision_opencv功能包集下的cv_bridge功能包内。


cv_bridge定义了一个CvImage数据类,该类型包括了OpenCV图像、编码和一个ROS头文件。CvImage准确包含了sensor_msgs/Image具有的信息,因此可以在两种表达方式之间切换。


ROS发布Mat图像的两种常用方法

(1)读取本地图片发布

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);

  cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
  sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();

  ros::Rate loop_rate(5);
  while (nh.ok()) {
    pub.publish(msg);
    ros::spinOnce();
    loop_rate.sleep();
  }
}

(2)获取本地相机或视频文件发布

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);

  cv::VideoCapture TheVideoCapture;
  TheVideoCapture.open(0);
  cv::Mat image;
  char key;

  ros::Rate loop_rate(100);
  while (nh.ok() && key != 27) {
  if(TheVideoCapture.grab()){
    TheVideoCapture.retrieve(image);
    cv_bridge::CvImage out_msg;
    out_msg.header.stamp = ros::Time::now();
    out_msg.encoding = sensor_msgs::image_encodings::BGR8;
    out_msg.image = image;
    pub.publish(out_msg.toImageMsg());
    // cv::imshow("image", image);
    key = cv::waitKey(1);
  }
  loop_rate.sleep();
}

以上两块代码都需要添加依赖image_transport和cv_bridge(如何添加依赖这里不再赘述,个人认为在Roboware_Studio里面比较好操作),如果不出现OpenCV版本兼容的问题,编译完成后它们都是可以以ROS节点的形式正常运行的。但是不幸的是,博主在一开始用第二种方法发布topic的时候就遇到了cv_bridge与OpenCV3不兼容的问题,导致程序无法运行,下面介绍一种解决该问题的方法。

2、对ROS-indigo中OpenCV版本不兼容问题的一种解决方法

由于某些原因,博主需要用到OpenCV3以上的版本,但据网上介绍说ROS-indigo版本中的cv_bridge好像默认是依赖OpenCV2.4.8编译的,所以通常会与我们自己安装的较高版本的OpenCV3产生一些冲突。但是我又不想换高版本的ROS,所以,在网上翻阅大神们的解决方案,说可以卸载默认安装的cv_bridge,重新编译安装。鄙人试了一下,果然解决了我的问题,现将该方法总结一下,供大家参考。

  • Step1:

首先确保你的Ubuntu已正确安装了OpenCV3某版本,并可以find到它的安装路径,不然 cv_bridge 是无法编译的。你可以尝试在终端运行以下命令来查看当前系统安装的OpenCV版本。

$ pkg-config --modversion opencv

正常情况下它会显示你的OpenCV版本号,比如博主的运行结果为:

$ 3.3.1
  • Step2:

卸载ROS-indigo默认安装的cv_bridge,在终端运行命令:

$ sudo apt-get remove ros-indigo-cv-bridge

敲完命令行回车输入用户密码,我们会发现系统提示说要卸载好多软件包,这是因为我们在卸载cv_bridge功能包时,其他所有依赖于它的功能包也要同时被卸载,不然cv_bridge没了这些功能包也就没法用了(我是这么理解的)。不过不用担心,卸完以后我们还可以再编译安装嘛,所以,输入 y 敲回车狠心卸载。

  • Step3

卸载完cv_bridge我们就要去GitHub上下载源码自己编译了(indigo版本的源码地址在这里),我们也可以通过命令行下载。博主默认亲们至少已经有了自己的一个ROS工作空间,我的 ~/catkin_ws 工作空间就是专门用来编译重装ROS源码的,所以我的命令行如下:

$ cd ~/catkin_ws/src
$ git clone https://github.com/ros-perception/vision_opencv.git --branch=indigo
$ cd ..
$ catkin_make

以上工作空间可自行修改,正常情况下编译不会出现问题,除非你的OpenCV安装有错误。如果没有 source 过你的工作空间的要把工作空间中的 devel/setup.bash 添加到 ~/.bashrc 中,以我的为例:

$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
  • Step4

因为前面在卸载 cv_bridge 时把依赖于它的其他很多功能包也同时卸载了,导致很多功能无法使用,比如我经常要用到的 image_view 功能包,所以,现在就要把其他的功能包用同样的方法也装上。我们可以通过在ROS官网查找 image_view 来定位它的源码地址,在这里可以发现,image_view其实是功能包集image_pipeline中的一个功能包,所以我们直接把 image_pipeline下载下来编译安装就行了(前面一并卸载的其他功能包大部分都在这个功能包集里面)。

$ cd ~/catkin_ws/src
$ git clone https://github.com/ros-perception/image_pipeline --branch=indigo
$ cd ..
$ catkin_make
  • Step5

至此,cv_bridge 与 OpenCV3 的版本兼容问题基本已经解决了,还有其他一些卸掉的功能包,用到的时候可以用上述同样的方法再安装。鄙人的方法可能不是太好,如果大神们有更好的解决方案,希望不吝赐教!


参考链接

[1] https://blog.csdn.net/github_30605157/article/details/50990493
[2] https://www.cnblogs.com/cv-pr/p/5366764.html
[3] http://wiki.ros.org/cv_bridge

猜你喜欢

转载自blog.csdn.net/lixujie666/article/details/80076083