cv_bridge会使用自定义版本的opecv,当我们想使用自己的opencv版本时可能会发生冲突。比如:我用opencv 3.2写的程序,而对方电脑的cv::bridge一直调用的opencv 4.1,然后为了执行我的程序就在对方电脑上安装了opencv 3.2,当ros节点中既使用opencv又引入cv_bridge时,程序报错说没有定义imread函数。
好多博文提到这种方法,也就是在写ros节点的时候不使用cv_bridge,就不会导致二者冲突了。这种方法虽然也可以编译过去,但是很多时候没有cv_bridge就无法完成我们程序的功能了。
这是很多博文提倡的做法,将cv_bridge所使用的opencv也切换为我们的opencv版本,这样就不会导致一个程序使用两个opencv而冲突了。这种做法的缺点是,为了运行自己的程序修改了cv;:bridge的opencv版本,这样可能会导致其他使用cv_bridge的程序无法正常运行。具体做法为修改cv::bridge的配置文件:
参考博文:https://blog.csdn.net/bigdog_1027/article/details/79092263(以下内容是复制过来的,没有测试过,不是本博文的核心,就不修改了)
首先打开终端并进入cv_bridge配置文件所在目录,并用gedit指令打开该配置文件
$ cd /opt/ros/kinetic/share/cv_bridge/cmake/
$ sudo gedit cv_bridgeConfig.cmake
然后按ctrl+f,输入关键词include找到以下内容并按图中的方式进行修改。
将默认的OpenCV头文件目录替换后,再按ctrl+f并输入关键词libraries可以找到下图的区域,我们将其库文件也进行替换。
修改cv_bridge的配置文件结束后,我们只需要在工程的CMakeLists.txt文件中的find_package加入cv_bridge就能够使用自己安装的OpenCV版本。不需要再像(1)方法中那样手动指定路径,而且这样做的好处就是能够使用cv_bridge。因为该包在OpenCV图像与ROS图像之间的转换中会经常用到。
因为我是要在别人电脑上运行自己的程序,不能影响电脑上其他程序的运行,所以不能采用2.2的方法。解决方案就是编译一个新的cv::bridge_1包实现cv::bridge的功能,cv_bridge_1使用opencv3.2,然后我的程序使用cv_bridge_1,这样的话我的程序很好地与电脑其他环境相互隔离开了。具体的:
从官网下载cv_bridge的对应版本的源代码,拷贝cv_bridge安装包到工作空间下: https://github.com/ros-perception/vision_opencv
修改名称:将功能包文件名改为cv::bridge_1
修改cv::bridge_1/CMakeLists.txt中的工程名称,
project(cv_bridge) 改为 project(cv_bridge_1)
修改cv::bridge_1/package.xml,
<name>cv_bridge</name> 改为 <name>cv_bridge_1</name>
配置cv::bridge_1/CMakeLists.txt,使其使用指定的opencv,例如我的是
set(OpenCV_DIR /usr/local/opencv3.2/share/Opencv)
find_package(Opencv 3.2.0 EXAT
...
)
与之前类似,将CMakeList中find_package(Opencv )之前需要指定opencv的路径
set(OpenCV_DIR /usr/local/opencv3.2/share/Opencv)
然后将CMakeList和package.xml中的cv_bridge修改为cv_bridge_1
具体使用时应引入头文件
#include
期间可能会出现其他一些小问题,根据报错自行百度解决即可。
总之,解决cv_bridge与opencv版本冲突有三种解决方案,第一种方案为程序不使用cv_bridge,不能解决根本问题;第二种方案为,修改cv_bridge的配置,令cv_bridge调用我们的opencv,就不会出现一个程序使用两个opencv而冲突的问题 ,其会改变原有软件环境依赖,可能会导致其他使用cv_bridge的程序出现错误,但是其操作比较简单,是很多博文介绍的方法;第三种方法为,重新定义和使用一个与cv_bridge功能相同的ros功能包,令其使用我们的opencv版本,这样既避免了opencv版本冲突,又不会影响现有的环境,缺点是操作比较麻烦。