☰
Ubuntu 18.04源码编译OpenCV 4.5完全指南:从CMake配置到环境验证
2026/9/30 12:03:11 网站建设 项目流程

搞过几年计算机视觉开发的人,对 Ubuntu 18.04 + OpenCV 4.5 这个组合应该不陌生。Opencv4.5 在 2020 年底发布,是 4.x 系列里综合体验比较舒服的版本:DNN 模块已经足够成熟,SIFT 等算法不需要再单独打补丁,编译配置也相对干净。这篇文章想分享的,不是网上那种复制粘贴的三行命令,而是一份我在不同机器上反复验证过的完整流程,包含依赖选型、CMake 参数含义、编译踩坑记录和安装后的验证方法。不管你是要给自己的视觉项目搭环境,还是正在配置相机雷达联合标定工具链,照着做基本都能顺利落地。

先交代一下我的习惯:OpenCV 4.5 我从不建议直接用 apt 或 pip 的预编译包,除非你只是临时跑个 demo。真正要用于项目开发、需要自己编译算法模块、接摄像头驱动、做 CUDA 加速或者深度集成的场景,源码编译反而更省心。这篇文章面向的是 Ubuntu 18.04 上需要认真使用 OpenCV 的开发者,包括正在折腾自动驾驶标定工具的同学,我会从零开始把每一步都拆开讲清楚。

1. 安装思路:源码编译还是包管理器

1.1 为什么我坚持源码编译

很多朋友第一次装 OpenCV,最先尝试的是pip install opencv-python或sudo apt install libopencv-dev。这两种方式确实省事,但对真正做项目的人来说,坑在后面。

先看 pip 版本。pip 装的是 pre-built wheel,优点是快,缺点是看不到编译选项。比如你后面做视频处理,可能需要 FFmpeg 后端、GStreamer 后端,或者想用 OpenCV 的 contrib 模块里的 ArUco、SIFT,pip 默认包往往是裁剪过的。更麻烦的是,pip 版 OpenCV 的cv2模块和系统里的库文件可能来自不同构建,一旦项目需要混合编译 C++ 和 Python,版本错位问题会让人一头雾水。

再看 apt 版本。Ubuntu 18.04 软件源里的 OpenCV 是 3.2 版本,和 4.5 的 API 有差异不说,很多新特性根本用不了。而且 apt 版 OpenCV 在编译时未必开启了全部优化,比如WITH_TBB、WITH_OPENMP这些性能开关,默认可能没打开。

所以我的建议很明确:如果你要长期做视觉开发,一步到位源码编译。虽然第一次编译需要二三十分钟,但编译出来的 OpenCV 完全可控,什么模块开启、什么功能关闭、装到什么路径,全在你自己手里。后面项目出了诡异问题,排查起来心里也有底。

1.2 版本选择和 4.5 带来的变化

选 4.5 而不是最新的 4.x 或 5.x,核心原因通常是项目依赖链。很多老项目是基于 18.04 搭的,比如相机激光雷达联合标定工具链里的部分底层库,对 OpenCV 版本敏感。4.5 正好处在一个平衡点:API 稳定,Python 接口齐全,DNN 模块支持主流模型格式,contrib 里的 ArUco、Barcode、文本检测等模块也很成熟。

相比更早的 4.1、4.2,OpenCV 4.5 有几个我实际用下来感知最明显的变化:

  • SIFT、SURF 这些非自由算法不需要自己编译 xfeatures2d 补丁,contrib 模块直接集成,但需要在 CMake 里显式开启OPENCV_ENABLE_NONFREE=ON。
  • DNN 模块对 ONNX 模型的支持更完善,很多 PyTorch 导出的模型可以直接加载。
  • 对 18.04 自带的 GCC 7.5 编译器兼容性极好,编译过程比新版 OpenCV 少很多编译错误。
  • opencv.pc等 pkg-config 文件支持更友好,配置 C++ 项目非常方便。

如果你刚接触 OpenCV,或者被很多“新版本教程”绕晕了,直接从 4.5 上手是稳妥的选择。

2. 环境准备:先把系统基础打好

2.1 更新系统与安装编译工具链

拿到一台干净的 Ubuntu 18.04,第一件事不是急着下载 OpenCV 源码,而是把系统的编译环境补全。很多人编译失败,根本不是 OpenCV 的问题,而是缺少基础依赖。

打开终端,先把软件源更新到最新状态:

sudo apt update sudo apt upgrade -y

注意upgrade可能会改动内核包,如果是服务器环境建议谨慎,但一般开发机没什么问题。之后安装编译工具链:

sudo apt install -y build-essential cmake git pkg-config

build-essential包含 GCC、G++、make,这是编译 C/C++ 代码的底子。cmake版本在 18.04 默认源里是 3.10.2,对 OpenCV 4.5 来说足够用。pkg-config后面检查安装是否正确时要用到。

提示:如果后面 CMake 报错说版本太低,可以考虑用 pip 安装新版 cmake,但我测试下来 Ubuntu 18.04 自带的 3.10.2 完全能编译 OpenCV 4.5,不需要多此一举。

2.2 图像、视频、GUI 依赖的安装细节

OpenCV 是个库,它要处理图像、视频和窗口显示,所以对应底层依赖一个都不能少。我第一次装的时候漏了libgtk-3-dev,结果编译出来cv2.imshow一调用就崩溃,排查了很久才发现是 GUI 后端没装全。

推荐按分组安装:

# 图片格式支持 sudo apt install -y libjpeg-dev libtiff5-dev libpng-dev # 视频处理和摄像头支持 sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev # GUI 显示(imshow等功能) sudo apt install -y libgtk-3-dev # 数值优化库(提升处理速度) sudo apt install -y libatlas-base-dev gfortran # 更多格式支持(jpeg2000, openexr等) sudo apt install -y libwebp-dev libopenexr-dev libgphoto2-dev

这里重点解释几个容易忽略的依赖。

libavcodec-dev、libavformat-dev、libswscale-dev对应 FFmpeg 的底层库,如果没装,OpenCV 的VideoCapture读视频文件能力会被大幅削弱,可能只能读 AVI,MP4 直接打不开。libv4l-dev是 V4L2 摄像头接口的支持库,不给它装上,USB 摄像头读取会各种花屏、打不开。

libgtk-3-dev用来提供 OpenCV 的 HighGUI 窗口显示能力。如果你不装,CMake 会退回使用 Qt 或者完全不启用 GUI,这样imshow、waitKey全废。做视觉调试的时候不能弹窗显示图像,效率会非常低。

libatlas-base-dev和gfortran属于数学优化库,OpenCV 上层大量矩阵运算可以借助 ATLAS 或 OpenBLAS 加速。装了以后图像处理速度会有可感知的提升。

2.3 Python 开发环境和 numpy

如果你计划使用 Python 调用 OpenCV,这一步很重要。

Ubuntu 18.04 默认带了 Python 3.6。OpenCV 4.5 对 Python 3.6 的兼容性没有问题,但建议先把 Python 开发头文件和 pip 工具装好:

sudo apt install -y python3-dev python3-pip python3-numpy

python3-dev提供 Python.h,编译 OpenCV 的 Python 绑定模块时必须要用到。python3-numpy用 apt 安装是因为系统级别的 numpy 比较稳定,能避免一些 pip 和系统环境混用的坑。

如果你有多个 Python 环境(比如 Anaconda),强烈建议在编译 OpenCV 之前确定好要用哪个 Python。因为 CMake 会自动检测系统里的 Python 解释器,如果环境变量VIRTUAL_ENV或CONDA_PREFIX存在,它会去绑定对应的 Python。这个绑定关系一旦定下来,OpenCV 的 Python 模块就只对这个 Python 环境生效。

注意:如果你的项目打算用 Anaconda 里的 Python,请在 CMake 配置之前先conda activate切换好环境。我就因为忘记切换,编译出的 cv2 装到了系统 Python 里,conda 环境怎么 import 都报错。

3. 源码下载与 CMake 配置

3.1 版本对应关系:OpenCV 与 Contrib 包缺一不可

OpenCV 4.5 发布后,opencv_contrib 仓库会同步发布相同版本的模块包。contrib 里包含了大量扩展模块,比如 ArUco 标记检测、SFM、文本识别、人脸识别等。官方主仓库默认不会编译这些模块,只有通过OPENCV_EXTRA_MODULES_PATH指定路径才能把它们加进来。

下载源码时,最稳妥的做法是用 Git 切到对应 tag:

cd ~ git clone https://github.com/opencv/opencv.git cd opencv git checkout 4.5.0 cd ~ git clone https://github.com/opencv/opencv_contrib.git cd opencv_contrib git checkout 4.5.0

两个仓库必须切到同一个版本 tag。如果一个是 4.5.0,另一个是 4.5.1,CMake 配置阶段极有可能因为模块接口不匹配而报错。我这里以 4.5.0 为例,如果你希望用 4.5.1、4.5.2,改成对应 tag 即可。

如果你所在的网络环境访问 GitHub 太慢,可以下载压缩包,但注意 opencv 和 opencv_contrib 的压缩包版本号也要严格一致。下载完成后放在同一个父目录下,方便后面 CMake 引用路径。

3.2 CMake 参数逐个解释,避免“知其然不知其所以然”

进入源码目录,创建 build 目录:

cd ~/opencv mkdir build && cd build

然后执行 CMake 配置命令。下面是我实测稳定可靠的一组参数:

cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D WITH_TBB=ON \ -D WITH_V4L=ON \ -D WITH_QT=OFF \ -D WITH_GTK=ON \ -D WITH_OPENGL=ON \ -D WITH_OPENMP=ON \ -D OPENCV_ENABLE_NONFREE=ON \ -D OPENCV_GENERATE_PKGCONFIG=YES \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \ -D BUILD_EXAMPLES=OFF \ -D BUILD_TESTS=OFF \ ..

逐个解释一下关键参数:

  • CMAKE_BUILD_TYPE=RELEASE:编译优化等级,发布版能跑满 CPU 性能。debug 版会在运行时输出大量调试信息,通常没必要。
  • CMAKE_INSTALL_PREFIX=/usr/local:安装路径。默认就是 /usr/local,头文件放/usr/local/include,动态库放/usr/local/lib。自己指定也可以,但后续要额外配置 PKG_CONFIG_PATH。
  • WITH_TBB=ON:启用 Threading Building Blocks,Intel 的并行计算库,从 4.5 开始推荐开启,很多算法能自动利用多核并行。
  • WITH_V4L=ON:启用 Video for Linux 摄像头支持。
  • WITH_GTK=ON:使用 GTK 作为 GUI 后端。如果你的机器环境里 GTK 编译依赖没装全,这里会检测失败并退回其他后端,日志里会显示GUI: GTK+ : NO,这时候回去补装依赖。
  • WITH_QT=OFF:如果不需要 Qt 界面集成,建议关掉,避免两个 GUI 后端互相干扰。
  • WITH_OPENMP=ON:OpenMP 并行支持,配合多核 CPU,很多矩阵操作的性能提升明显。
  • OPENCV_ENABLE_NONFREE=ON:这个非常关键。不开启它,SIFT 和 SURF 即便在 contrib 模块里也无法使用。项目里要跑特征点匹配的同学,这个参数一定别忘。
  • OPENCV_GENERATE_PKGCONFIG=YES:4.5 系列编译后默认会生成opencv4.pc文件,方便 pkg-config 使用。
  • OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules:指向 contrib 模块路径。
  • BUILD_EXAMPLES=OFF、BUILD_TESTS=OFF:关闭示例和测试,大幅缩短编译时间。

CMake 执行完成后,仔细看输出信息。重点确认三处:

  1. Python 3: YES,对应版本是否是你要用的 Python。
  2. GUI: GTK+ : YES,GUI 后端是否生效。
  3. FFMPEG: YES,视频后端是否生效。

如果这三处有 NO 或版本不对,先不要急着继续,回到上一步补依赖再重新执行 cmake。

3.3 执行编译:线程数和内存管理

CMake 配置完成后,正式编译:

make -j$(nproc)

nproc会返回 CPU 核心数。不过这里有个经验值:如果你的物理内存低于 8GB,建议不要用全部核心,make -j4更稳妥。因为 OpenCV 编译过程中,编译单个.cpp文件可能吃掉 1-2GB 内存,同时开太多线程会导致内存耗尽、直接 OOM Kill。

我之前在一台 4 核 8GB 的笔记本上用过-j4,一切正常。换到 2 核 4GB 的老机器上同样用-j4,编译到一半卡死,后来降成-j2才顺利跑完。

编译过程可能需要十到二十分钟。可以去做点别的,但时不时看一眼终端,确认没有报错。如果编译中断,重新执行相同命令即可,CMake 会在中断点继续,不会从头开始。

编译完成后,安装:

sudo make install

安装过程通常很快,就是把编译好的动态库和头文件拷贝到/usr/local对应目录。

4. 环境变量与安装验证

4.1 动态库路径配置

安装完成后,Linux 系统默认不一定能找到/usr/local/lib下的 OpenCV 动态库。如果直接编译测试程序,可能会遇到cannot find -lopencv_world或者运行时error while loading shared libraries。

解决方法是把库路径加入动态链接器配置。先创建一个配置文件:

sudo sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf'

然后更新动态链接库缓存:

sudo ldconfig

ldconfig是必须执行的,不执行的话配置不会生效。执行完后,可以检查一下库是否能被找到:

ldconfig -p | grep opencv

正常情况下能看到一堆 libopencv_core、libopencv_imgproc 等动态库路径。

接下来配置 pkg-config。OpenCV 4.5 编译时设置了OPENCV_GENERATE_PKGCONFIG=YES,所以系统里会有opencv4.pc文件。为了让 pkg-config 能发现它,设置环境变量:

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

如果你希望每次打开终端都生效,把它写入~/.bashrc:

echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc source ~/.bashrc

然后验证 pkg-config 是否能正确返回 OpenCV 版本:

pkg-config --modversion opencv4

如果输出4.5.0,说明环境配置成功。

4.2 C++ 测试程序验证安装

光看版本号还不够,最好写一个完整的测试程序,确认头文件、链接库和运行都没问题。

创建一个test.cpp:

#include <opencv2/opencv.hpp> #include <iostream> int main() { cv::Mat image(480, 640, CV_8UC3, cv::Scalar(0, 0, 255)); std::cout << "OpenCV version: " << CV_VERSION << std::endl; std::cout << "Image size: " << image.cols << " x " << image.rows << std::endl; cv::Mat gray; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); std::cout << "Grayscale size: " << gray.cols << " x " << gray.rows << std::endl; return 0; }

编译命令:

g++ test.cpp -o test $(pkg-config --cflags --libs opencv4)

如果编译通过并且运行输出OpenCV version: 4.5.0,说明 C++ 环境完全正常。

很多教程无视 pkg-config,直接写一大串-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui,也能编译,但容易漏库。用 pkg-config 是从项目配置角度最不容易出错的方案。

4.3 Python 接口验证

如果你编译时检测到了 Python 3,安装完成后,Python 环境里会生成cv2模块。验证方法很直接:

import cv2 print(cv2.__version__) print(cv2.getBuildInformation())

输出的版本号是4.5.0就代表成功。getBuildInformation()里能看到完整的编译参数,比如 FFMPEG、GTK、TBB 是否生效。

这里有一个容易疑惑的问题:你可能会发现cv2.__file__指向的是/usr/local/lib/python3.6/dist-packages/cv2/python-3.6/cv2.cpython-36m-x86_64-linux-gnu.so,这是源码编译默认安装路径。如果你之前 pip 安装过 opencv-python,它会在site-packages下留下一个cv2,这时候 import 的到底是哪个?简单说,谁在PYTHONPATH里或者谁排在 sys.path 前面,就加载谁。建议源码编译完,把 pip 版的 opencv-python 卸载干净:

pip3 uninstall opencv-python opencv-contrib-python

避免后面调试项目时出现版本错乱。

5. 常见问题与排查实录

5.1 编译中途容易遇到的经典报错

编译 OpenCV 很少有一帆风顺的,下面几个是我遇到最多的情况。

第一个是boostdesc_bgm.i等文件缺失的报错。这个问题在使用 contrib 模块时非常常见。本质是 contrib 仓库里部分算法的原始训练数据文件没有被正常打包。解决方法可以从网上找对应的.i文件,放到opencv_contrib/modules/xfeatures2d/src/目录下,再重新编译。如果是新版本,这个情况稍好一些,但 4.5 时代确实还有人遇到。

第二个是内存不足导致编译进程被杀。错误信息通常是virtual memory exhausted或者直接被系统 OOM 杀死。我在 2GB 内存的机器上试过,确实必现。解决办法是增加临时 swap:

sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

编译完可以视情况关闭 swap,这能有效防止 g++ 在编译高内存消耗的模块时崩溃。

第三个是Qt5WebKitWidgets之类缺失导致WITH_QT=ON时报错。如果你不需要 Qt,直接像我前面参数那样设WITH_QT=OFF就好了。不要盲目追求“功能全开”,稳定才是第一位。

5.2 头文件和动态库找不到

编译测试程序时如果报fatal error: opencv2/opencv.hpp: No such file or directory,要么是安装不完整,要么是头文件路径没被找到。

首先看一下/usr/local/include下是否有opencv4/opencv2目录。OpenCV 4.x 的头文件默认放在/usr/local/include/opencv4/opencv2下。如果存在,说明安装没问题,是编译命令没指定-I路径。换成 pkg-config 模式编译就不会有这个困扰。

运行时如果报error while loading shared libraries: libopencv_core.so.4.5: cannot open shared object file,那是动态库路径没生效。回到 4.1 节,确认/etc/ld.so.conf.d/opencv.conf是否已添加/usr/local/lib,并且执行过ldconfig。

提示:如果改完配置还不行,可以临时用export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH验证,但这个变量只对当前终端有效,不建议作为长期方案。

5.3 Python 环境多版本冲突

系统同时存在多个 Python 时,CMake 可能绑定到错误的 Python 版本。我在一台装有 Anaconda 的机器上,明明用系统 python3,但 CMake 自动检测到了 conda 里的 Python 3.8,结果编译出的 cv2 只能在 conda 环境里 import。

解决方案很粗暴:CMake 时手动指定 Python 解释器、库和 include 路径:

cmake -D PYTHON_DEFAULT_EXECUTABLE=$(which python3) \ -D PYTHON3_EXECUTABLE=$(which python3) \ -D PYTHON3_INCLUDE_DIR=$(python3 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \ -D PYTHON3_LIBRARY=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")/libpython3.6m.so \ ...

配置完成后,在 CMake 输出里明确核对 Python 版本和路径是否一致,再继续编译。

5.4 FFmpeg、GTK 等扩展功能未生效

编译完成后,如果你用cv2.VideoCapture读不了 MP4,或者cv2.imshow弹不出窗口,大概率是编译时 FFmpeg 或 GTK 没有被检测到。

在 CMake 配置输出里搜索FFMPEG和GTK,看到NO就要回头补依赖。常见原因是 apt 安装依赖之前你已经执行过 cmake,导致缓存里残留了旧的检测结果。这时候需要把 build 目录缓存清掉重新配置:

rm -rf build mkdir build && cd build cmake ...

开发中最容易忽略的点就是“依赖装晚了”,然后一直沿用旧的 cache,排查半天以为代码有问题,其实重新 cmake 就解决了。

6. 实际使用中的几点建议

6.1 多项目共存时如何隔离 OpenCV 版本

编译完成不代表万事大吉。OpenCV 4.5 装到/usr/local后,全局生效。如果后面某个项目需要 OpenCV 3.x,安装到/usr/local会把 4.5 覆盖掉,比较麻烦。

我的做法是给不同版本指定不同的安装前缀。比如 4.5 装到/usr/local/opencv4.5:

cmake -D CMAKE_INSTALL_PREFIX=/usr/local/opencv4.5 ...

编译项目时,通过-I/usr/local/opencv4.5/include/opencv4和-L/usr/local/opencv4.5/lib指定路径,或者临时设置PKG_CONFIG_PATH指向对应的 pkgconfig 目录。这样不同项目各用各的 OpenCV,互不干扰。

用 CMake 管理 C++ 项目的同学,还可以在CMakeLists.txt里这样写:

set(OpenCV_DIR "/usr/local/opencv4.5/lib/cmake/opencv4") find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) target_link_libraries(your_target ${OpenCV_LIBS})

6.2 编译优化参数还能加什么

如果你的机器有 NVIDIA 显卡,并且计划跑深度学习推理,可以考虑在 CMake 时加入 CUDA 支持:

-D WITH_CUDA=ON \ -D WITH_CUDNN=ON \ -D OPENCV_DNN_CUDA=ON \ -D CUDA_ARCH_BIN=7.5

CUDA_ARCH_BIN要按显卡的算力填写,比如 RTX 2070 Super 是 7.5,RTX 3080 是 8.6。填错的话虽然能编译,但运行时可能无法调用 GPU 设备。

有 NVIDIA 显卡还能启用WITH_CUBLAS和WITH_CUFFT,对图像处理和矩阵运算有帮助。

如果机器上没有 NVIDIA 平台,千万别开 CUDA 相关参数,否则 CMake 检测阶段直接报错或者编译出来的库运行不稳定。

6.3 安装完成后备份编译产物

最后分享一个我自己的习惯。编译好的 OpenCV 4.5,我会把/usr/local/lib下的 libopencv 相关 so 文件、/usr/local/include/opencv4头文件和lib/cmake/opencv4目录一起打包留底:

tar -czf opencv4.5_ubuntu18.04_backup.tar.gz \ /usr/local/lib/libopencv* \ /usr/local/include/opencv4 \ /usr/local/lib/cmake/opencv4

等哪一天系统重装、或者另一台同版本机器要复用,直接把备份释放回去,再补一个ldconfig就能重新用,不用再花二三十分钟重新编译。这个方法在团队协作维护多台开发机时特别实用。

我自己在几年的开发里,用这套流程装过的机器包括笔记本、台式机、工控机和服务器,除了极少数硬件特殊的情况,基本都是一遍过。Ubuntu 18.04 的生命周期虽然逐步进入尾声,但大量存量项目依然跑在这个系统上,OpenCV 4.5 作为它们的视觉底层,仍然会存在很长时间。希望这篇记录能在你安装配置的时候帮你省点时间,少踩点我当年踩过的坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询