背景
由于在初学slam阶段,电脑上装了一堆开源的slam代码,每个代码的环境库都不一样,其中最重要的opencv库需要经常切换。在此期间,csdn上的很多帖子有坑,浪费了我非常多的时间,坑位总结如下:
- 通过.bashrc修改PKG_CONFIG_PATH和LD_LIBRARY_PATH只是修改了动态链接库,在编译程序的时候还是原来的版本。
- 通过.so文件直接替换,非常坑人,看起来版本都变了,但是在程序运行时还是会调用之前的链接库,这是因为package的.cmake文件中依然保存的是原来的.so路径
原因:根据项目的CMakeList里面的包,CMake会采用不同的调用策略
Package | Path |
---|---|
cv_bridge | /opt/ros/noetic/share/cv_bridge |
OpenCV | /usr/local/share/OpenCV |
如果,这两个文件夹里的OpenCV版本不同,那么就杯具了,程序会有莫名其妙的各种问题和Warning,而修改.bashrc的办法也只针对OpenCV而不是cv_bridge,导致版本不一致,所以这就是坑点。
OpenCV多版本安装
首先安装多版本的OpenCV,下载不同的OpenCV版本,一定注意,需要在执行cmake指令时规定install的路径!,如下所示替换相应的路径和版本
cmake .. -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local/opencv_4.7.0 \ #把opencv安装路径
-D OPENCV_EXTRA_MODULES_PATH=/home/${主机名}/opencv_contrib-4.7.0/modules \ #指向下载的opencv_contrib文件夹
-D OPENCV_GENERATE_PKGCONFIG=YES
演示的是opencv4.7.0版本,其他版本类似操作,只需要修改CMAKE_INSTALL_PREFIX和OPENCV_EXTRA_MODULES_PATH就行。
最后别忘了sudo make install
CMakeList的find_package()功能解析
find_package()这个函数的功能,是通过搜索一些路径,寻找到来实现的。搜索路径<package>Config.cmake
的优先级我暂时没有做测试,但是可以粗略的做一个表格
CMAKE_PREFIX_PATH
<package>_DIR
CMAKE_FRAMEWORK_PATH
PATH
在这些路径中,寻找以下的文件夹里有没有<package>
文件夹,再搜索<package>Config.cmake
文件
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/
所以,我们只需要保证CMAKE_PREFIX_PATH
路径中有这些包就行,就不会找不到包了,其次,再保证OpenCV的版本正确。
项目的CMakeList编写指南
在安装了不同版本的OpenCV之后,我们需要在每个项目的CMakeList中添加
set(OpenCV_DIR "/usr/local/opencv_4.7.0")
解释:
通过message(STATUS ${CMAKE_PREFIX_DIR})
可以知道,CMAKE_PREFIX_PATH的路径有:
- /usr/local/
- /opt/ros/noetic/
由上文的find_package()功能解析可以知道,CMAKE_PREFIX_PATH的优先级最高。
那么,我们需要确保这个OpenCV多版本的包在这两个路径下都找不到,这样我们自己设置OpenCV_DIR就能正确连接到合适的版本了。删掉这两个路径下OpenCV文件夹再进行修改CMakeList
ROS的cv_bridge安装
接下来,我们需要解决ros系统对opencv的调用问题,首先,要删掉原本的cv_bridge
sudo apt-get remove ros-noetic-cv-bridge
下载cv_bridge源码,注意在branch中选择版本
Github 链接
修改CMakeList,指定OpenCV package的路径。
set(OpenCV_DIR "/usr/local/opencv_4.7.0")
find_package(OpenCV REQUIRED)
再进行sudo make install
完成安装。
总体流程
讲了这么多,总结以下,确保能够运行多版本切换的流程是:
- 安装多版本的opencv
- 确保OpenCV多版本的包在
CMAKE_PREFIX_PATH
路径下找不到(删去必要的部分) - 在每个项目的CMakeList里面添加OpenCV_DIR
- 重新安装cv_bridge
- 完成更改
如果需要重新切换版本,需要重新安装cv_bridge
参考
- https://github.com/ros-perception/vision_opencv/tree/noetic
- https://zhuanlan.zhihu.com/p/50829542
- https://immortalqx.github.io/2021/07/06/opencv-notes-0/