linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)

在工程中,我们由于OpenCV的版本依赖问题,我们往往需要编译多个OpenCV的库。但是在我们使用ROS的时候,会默认在交叉编译文件夹/usr/lib/aarch64-linux-gnu/ (我的是arm架构所以中间为aarch64-linux-gnu,x86的机器则为/usr/lib/x86-64-linux-gnu/)文件夹下生成opencv的库,拿melodic版本为例自动生成的库版本为3.2.0,noetic则为4.2.0。
此时如果我一个设备需要的OpenCV版本为3.3,则可能会与之产生冲突并引发,conflict报错或者warn。并且由于对应版本的CV_bridge指定为该路径(/usr/lib/aarch64-linux-gnu/)下的OpenCV库,此时会引发严重问题,出现诸如这样的报错:

libopencv_imgcodecs.so.3.2, needed by /opt/ros/melodic/lib/libcv_bridge.so, may conflict with libope

【linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)】以及某些未定义的引用。上面的是一个由于cv_bridge引发的错误。
我们知道,当设备安装多个版本的OpenCV时,我们需要在cmakelists中指定你的OpenCV的路径
set(OpenCV_DIR xxxxxxxxx)

后再通过find等操作来完成版本的选择,或者通过
find(OpenCV xx REQUIRED)

xx为指定版本,如果这样能解决问题则完毕。
但是同样也存在报错在交叉编译部分的报错,我们明明选定了固定版本的OpenCV却仍然报错,在link中仍然看到了链接到了交叉编译的文件夹下的库。这时候我们去检查cmakelists.txt,发现在生成动态库的时候,链接的库只有两个$(catkin_LIBRARIES)以及${OpenCV_LIBRARIES}
linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)
文章图片

那么是哪个地方出现问题了呢,因为报错是产生在OpenCV的是OpenCV出的问题么,其实不然?我们将两个变量的内容打印出来检查一下:
message(STATUS "include path: ${OpenCV_INCLUDE_DIRS}") message(STATUS "LIBRARIES: ${OpenCV_LIBRARIES}") message(STATUS "catkin_LIBRARIES: ${catkin_LIBRARIES}")

可以看到:

这部分OpenCV3.2的库是由$(catkin_LIBRARIES)的内容带来的,那么我们将这部分opencv的库剔除即可。
此时使用:
file(GLOB_RECURSE OLD_OPENCV "/usr/lib/aarch64-linux-gnu/libopencv*") list(REMOVE_ITEM catkin_LIBRARIES ${OLD_OPENCV})

这是两个cmakelists的操作,简单介绍一下:参考链接
linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)
文章图片

linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)
文章图片

在链接库之前加上以上两句将把ros自带的的opencv库排除在外。我们可以输出验证一下:

发现确实没有了。如果仅有这类问题,直接编译即可通过。
如果报错含有文中开始提到的cv_bridge问题,则需要对cv_bridge进行修改:
在/opt/ros/melodic/share/cv_bridge/cmake路径下sudo 使用gedit或者vim打开 cv_bridgeConfig.cmake
打开后我们发现,cv_bridge正是由于版本配合,指向为ROS自带的OpenCV版本,此时我们只需要修订以下两处(下图为已修订后的):
linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)
文章图片

#原1: if(NOT "include; /usr/include; /usr/include/opencv4 " STREQUAL " ") #根据你所需的OpenCV路经改为: if(NOT "include; /usr/include; /usr/local/include/opencv" STREQUAL " ")#原2: set(libraries "cv_bridge; /usr/lib/aarch64-linux-gnu/libopencv_core.so.3.2.0; /usr/lib/aarch64-linux-gnu/libopencv_imgproc.so.3.2.0; /usr/lib/aarch64-linux-gnu/libopencv_imgcodecs.so.3.2.0") #根据你所需的OpenCV库的路经改为: set(libraries "cv_bridge; /usr/local/lib/libopencv_core.so.3.3.1; /usr/local/lib/libopencv_imgproc.so.3.3.1; /usr/local/lib/libopencv_imgcodecs.so.3.3.1")

再次编译即可通过。
------------------------------------------------------------------------------------------------------------------------
总结:
1.当使用多个版本OpenCV时首先指定版本看是否能解决问题;
2.当没有cv_bridge的报错时,提示冲突,检查$(catkin_LIBRARIES)的内容,并将ROS自带的OpenCV库排除在外;
3.当存在cv_bridge的报错时,提示冲突,修改/opt/ros/melodic/share/cv_bridge/cmake的cv_bridgeConfig.cmake文件。

后记:
当我们有多版本OpenCV时,我们需要明确需求,需要用多少版本去编译,以上$(catkin_LIBRARIES)的交叉编译库的指向很有可能来自于cv_bridge的指向,我们需要先明确是否会链接这种会二次调用的pkg:例如我需要使用opencv3.3.1来编译这个工程,且此工程中含有(catkin component)cv_bridge,故而仅需要指定OpenCV版本并调整cv_bridge的.cmake文件即可,不需要去除$(catkin_LIBRARIES)的内容!!! linux|ROS中catkin_make的OpenCV冲突的解决(踩坑小记,报错分析)
文章图片


    推荐阅读