ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题

1前景提要:

  1. cv_bridge是ros中常用的消息类型转换的包(ros自带的包),要在ros环境下利用opencv处理USB相机拍摄的视频必须用到cv_bridge(如下图),详见https://blog.csdn.net/Robogreen/article/details/50487382
    ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第1张图片

  2. 在网上找到相应文章之后(详见https://blog.csdn.net/qq_28306361/article/details/85142192,代码也贴在下面了),将代码copy过来,catkin_make的时候发现有以下错误提示:
    ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第2张图片

#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
static const char WINDOW[] = "Image window";
static void help()
{
    printf("\nThis program demonstrates converting OpenCV Image to ROS Image messages  \n"
        );
 
}
 
int main(int argc, char** argv)
{
  help();
  ros::init(argc, argv, "image_converter");
 
  //Reading an image from the file
  cv::Mat cv_image = cv::imread("/home/vlt/Pictures/1.jpg");
  if(cv_image.empty() )
    {
        ROS_ERROR("Read the picture failed!");
        return -1;
    }
 
  //Convert OpenCV image to ROS message
  ros::NodeHandle node;
  image_transport::ImageTransport transport(node);
  image_transport::Publisher image_pub; 
  image_pub=transport.advertise("OutImage", 1);
  ros::Time time=ros::Time::now(); 
 
  cv_bridge::CvImage cvi;
  cvi.header.stamp = time;
  cvi.header.frame_id = "image";
  cvi.encoding = "bgr8";
  cvi.image = cv_image;
 
  sensor_msgs::Image im;
  cvi.toImageMsg(im);
  image_pub.publish(im);
  ROS_INFO("Converted Successfully!");
 
  //Show the image
  cv::namedWindow(WINDOW);
  cv::imshow(WINDOW,cv_image);
  cv::waitKey(0);
 
  ros::spin();
  return 0;
}

主要是那两个未定义的引用让人头大。因为代码中还有其他cv::imread等opencv库中的函数,为什么唯独错误提示中的那两个函数显示未定义的引用呢?

2解决过程(这个过程可以略去不看,直接看下面的最终解决办法)

  1. 卸载系统自带的opencv2,重新下载安装并配置opencv2.4.9(见https://blog.csdn.net/weixin_40522162/article/details/79921370)
  2. 还是一样的报错,然后又在程序的cmakelist中添加了库的链接(见https://blog.csdn.net/qq_37340588/article/details/107057987):
set(OpenCV_DIR /usr/local/opencv2.4.9/share/OpenCV)
find_package(OpenCV 2.4.9 REQUIRED)
include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS} /usr/local/opencv2.4.9/include)
link_directories(${OpenCV_LIBRARY_DIRS} /usr/local/opencv2.4.9/lib))
  1. 还是一样的报错,这个时候人都傻了啊啊啊啊啊啊啊啊,甚至想卸载重装ros了。明明位置已经指定的明明白白的了,为什么还是未定义呢???
  2. 然后看到了一篇博客(见https://blog.csdn.net/bigdog_1027/article/details/79092263),终于明白了。原来先前的很多参考博客都没有提到cv_bridge,只是解决了opencv的版本问题。而我用的程序出错的罪魁祸首是cv_bridge这个包,详见3最终解决办法。

3最终解决办法

  1. 首先我们要明白,如果最开始安装的是完整的ros的话,是会自带opencv包的,ros-kinetic自带的是opencv3.3.1-dev,我们在/opt/ros/kinetic/include/opencv-3.3.1-dev这个路径下可以看到它。
    ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第3张图片
  2. 但是,ros自带的opencv包是很不完整的,有很多函数都没有,比如我们进入opencv2/highgui查看highgui.hpp头文件(如下图),可以看到里面甚至没有内容
    ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第4张图片
  3. 最重要的是,cv_bridge的cmake文件(里面写了这个包需要链接的一些库)中默认调用的是ros自带的opencv3.3.1-dev,而且经过之前报错的实践可以知道cv_bridge调用opencv版本优先级是高于我们写的CmakeList文件调用的opencv的。也就是说,只要我们用了cv_bridge,无论在CmakeList中指定的opencv库路径是哪里,它都会默认调用ros自带的opencv3.3.1-dev。而通过上面两点我们知道,ros自带opencv库是不完整的,所以会出现某些函数报“未定义的引用”的错。
  4. 那么怎么解决这个问题呢?最佳办法就是修改cv_bridge的cmake文件,让它默认调用我们指定的opencv库。修改如下:
    1.首先在终端中输入cd /opt/ros/kinetic/share/cv_bridge/cmake
    2.然后输入sudo gedit cv_bridgeConfig.cmake
    3.然后修改以下两处(图片借鉴于博客https://blog.csdn.net/bigdog_1027/article/details/79092263):
    ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第5张图片ROS中用cv_bridge和opencv时出现cv::xxx未定义的问题_第6张图片opencv库文件(均为动态库so文件)有很多,在这里我们只是添加了最常用的几种,如果之后有需要还可以再在这个文件中添加。
    5.最后保存文件,在CmakeList中添加cv_bridge依赖包,就可以用我们指定的opencv版本啦。

参考链接

1.cv_bridge的原理讲解:https://blog.csdn.net/Robogreen/article/details/50487382
2.cv_bridge的简单应用:https://blog.csdn.net/qq_28306361/article/details/85142192
3.opencv的安装和配置:https://blog.csdn.net/weixin_40522162/article/details/79921370
4.Cmakelist添加opencv库地址:https://blog.csdn.net/qq_37340588/article/details/107057987
5.cv_bridge默认的opencv3和CmakeList中指定的opencv2冲突的问题:https://blog.csdn.net/bigdog_1027/article/details/79092263

你可能感兴趣的:(ros中的opencv,c++,linux,opencv)