在机器人视觉和SLAM领域,很多经典算法都是基于特定版本的OpenCV开发的。比如港科大的FIESTA建图系统,就明确要求使用OpenCV 3.2.0版本。但Ubuntu 20.04默认安装的是OpenCV 4.x版本,这就导致了版本兼容性问题。
我去年在部署一个激光雷达与视觉融合项目时,就遇到过这样的困扰。系统自带的OpenCV 4.x与项目要求的3.2.0版本冲突,导致编译时各种奇怪的报错。更麻烦的是,ROS中的cv_bridge组件对OpenCV版本极其敏感,稍有不慎就会导致图像传输失败。
这种情况其实很常见。根据我的经验,大约60%的视觉算法项目都会遇到版本兼容性问题。特别是当你要复现一些经典论文的代码时,版本匹配就更加重要了。这也是为什么我们需要专门学习如何在现代系统中部署旧版OpenCV。
首先需要清理系统可能存在的OpenCV残留。我建议先执行以下命令检查现有OpenCV版本:
bash复制pkg-config --modversion opencv
如果显示有4.x版本,建议先卸载:
bash复制sudo apt-get purge libopencv*
接下来安装编译依赖。这里有个坑需要注意:Ubuntu 20.04的软件源中有些包已经改名了。我整理了一份完整的依赖列表:
bash复制sudo apt-get install build-essential cmake git libgtk2.0-dev \
pkg-config libavcodec-dev libavformat-dev libswscale-dev \
python3-dev python3-numpy libtbb2 libtbb-dev \
libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
特别注意libjasper-dev这个包,在20.04中已经不存在了。经过多次测试,我发现这个依赖其实不是必须的,可以安全跳过。
从GitHub下载OpenCV 3.2.0源码:
bash复制wget -O opencv-3.2.0.zip https://github.com/opencv/opencv/archive/3.2.0.zip
unzip opencv-3.2.0.zip
创建编译目录并配置CMake。这里有几个关键参数需要特别注意:
bash复制mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local/opencv320 \
-D OPENCV_GENERATE_PKGCONFIG=YES \
-D BUILD_EXAMPLES=OFF \
-D BUILD_DOCS=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D WITH_FFMPEG=ON \
-D WITH_GTK=ON \
-D ENABLE_PRECOMPILED_HEADERS=OFF ..
参数说明:
CMAKE_INSTALL_PREFIX:指定安装路径,方便后续管理OPENCV_GENERATE_PKGCONFIG:生成pkg-config文件,便于其他程序查找ENABLE_PRECOMPILED_HEADERS:关闭预编译头,避免兼容性问题开始编译(根据CPU核心数调整-j参数):
bash复制make -j$(nproc)
sudo make install
安装完成后需要配置环境变量,让系统能找到我们的OpenCV 3.2.0:
bash复制echo '/usr/local/opencv320/lib' | sudo tee /etc/ld.so.conf.d/opencv320.conf
sudo ldconfig
验证安装是否成功:
bash复制pkg-config --modversion opencv
# 应该输出3.2.0
Ubuntu 20.04默认安装的cv_bridge是针对OpenCV 4.x编译的,必须卸载:
bash复制sudo apt-get remove ros-noetic-cv-bridge
从ROS官方仓库下载对应版本的cv_bridge源码:
bash复制git clone -b noetic https://github.com/ros-perception/vision_opencv.git
关键步骤是修改CMakeLists.txt。找到vision_opencv/cv_bridge/CMakeLists.txt,做如下修改:
cmake复制set(OpenCV_DIR "/usr/local/opencv320/share/OpenCV")
然后开始编译:
bash复制mkdir build && cd build
cmake -D CMAKE_INSTALL_PREFIX=/usr/local/cv_bridge320 ..
make -j$(nproc)
sudo make install
创建一个测试程序验证cv_bridge是否能正常工作:
python复制#!/usr/bin/env python3
import cv_bridge
print("cv_bridge version:", cv_bridge.__version__)
如果输出正确版本号且没有报错,说明安装成功。
以港科大FIESTA项目为例,我们需要修改CMakeLists.txt来适配我们的环境。关键配置如下:
cmake复制# 设置OpenCV路径
set(OpenCV_DIR "/usr/local/opencv320/share/OpenCV")
find_package(OpenCV 3.2 REQUIRED)
# 设置cv_bridge路径
set(cv_bridge_DIR "/usr/local/cv_bridge320/share/cv_bridge/cmake")
find_package(cv_bridge REQUIRED)
# 包含目录
include_directories(
SYSTEM
${OpenCV_INCLUDE_DIRS}
${cv_bridge_INCLUDE_DIRS}
/usr/local/opencv320/include
)
# 链接库
target_link_libraries(your_target
${OpenCV_LIBS}
${cv_bridge_LIBRARIES}
)
版本冲突问题:
如果遇到"OpenCV version mismatch"错误,检查CMake输出的OpenCV版本信息:
bash复制cmake --find-package -DNAME=OpenCV -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=COMPILE
符号未定义错误:
通常是因为链接顺序不正确。确保cv_bridge在OpenCV之后链接。
运行时错误:
如果程序运行时崩溃,检查LD_LIBRARY_PATH:
bash复制export LD_LIBRARY_PATH=/usr/local/opencv320/lib:$LD_LIBRARY_PATH
如果需要同时保留多个OpenCV版本,可以使用ccmake工具:
bash复制sudo apt-get install cmake-curses-gui
ccmake .
在界面中调整以下参数:
在Jetson Xavier上部署时,我发现编译过程会消耗大量内存,容易导致系统卡死。解决方案是限制编译线程:
bash复制make -j4 # 而不是make -j$(nproc)
另一个常见问题是Python绑定。如果你需要Python接口,编译OpenCV时要额外注意:
bash复制cmake -D BUILD_opencv_python2=OFF \
-D BUILD_opencv_python3=ON \
-D PYTHON3_EXECUTABLE=$(which python3) ..
对于ROS项目,建议在catkin工作空间中单独编译cv_bridge:
bash复制catkin_make --pkg cv_bridge --cmake-args \
-DOpenCV_DIR=/usr/local/opencv320/share/OpenCV
最后提醒一点:所有路径最好使用绝对路径,避免在复杂项目中出现找不到库的情况。我在一个多相机系统中就遇到过因为路径问题导致的运行时崩溃,调试了整整两天才发现是相对路径的问题。