在工程中,我们由于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

以及某些未定义的引用。上面的是一个由于cv_bridge引发的错误。

我们知道,当设备安装多个版本的OpenCV时,我们需要在cmakelists中指定你的OpenCV的路径

set(OpenCV_DIR xxxxxxxxx)

后再通过find等操作来完成版本的选择,或者通过

find(OpenCV xx REQUIRED)

xx为指定版本,如果这样能解决问题则完毕。

但是同样也存在报错在交叉编译部分的报错,我们明明选定了固定版本的OpenCV却仍然报错,在link中仍然看到了链接到了交叉编译的文件夹下的库。这时候我们去检查cmakelists.txt,发现在生成动态库的时候,链接的库只有两个$(catkin_LIBRARIES)以及${OpenCV_LIBRARIES}

 那么是哪个地方出现问题了呢,因为报错是产生在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的操作,简单介绍一下:参考链接

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

 发现确实没有了。如果仅有这类问题,直接编译即可通过。

如果报错含有文中开始提到的cv_bridge问题,则需要对cv_bridge进行修改:

在/opt/ros/melodic/share/cv_bridge/cmake路径下sudo 使用gedit或者vim打开 cv_bridgeConfig.cmake

打开后我们发现,cv_bridge正是由于版本配合,指向为ROS自带的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/cmakecv_bridgeConfig.cmake文件。

后记:

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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐