1. 为什么 Ubuntu 20.04 上装 OpenCV 值得单独写一篇Ubuntu 20.04 LTS 是个很特殊的存在。它发布于 2020 年 4 月标准支持到 2025 年而 ESM 扩展支持能撑到 2030 年。这意味着直到今天仍有大量服务器、工控机、边缘计算盒子跑在这个版本上。而 OpenCV 作为计算机视觉领域事实上的标准库从简单的图像裁剪到复杂的 SIFT 特征匹配、DNN 推理几乎每个视觉项目都绕不开它。但问题在于Ubuntu 20.04 自带的 OpenCV 版本是 4.2.0这个版本有几个让人头疼的限制缺少部分 contrib 模块、CUDA 支持需要自己编译、某些新算子比如cv::dnn::Net::forward对 ONNX 新算子的支持不完整。更麻烦的是Python 生态里opencv-python和opencv-contrib-python的 wheel 包虽然方便但在需要调用底层 C 接口、需要 GPU 加速、或者需要和 ROS 集成时就完全不够用了。我见过太多人在这一步卡住有人pip install opencv-python之后发现cv2.cuda模块不存在有人apt install libopencv-dev之后发现版本太老编译自己项目时链接报错还有人源码编译到一半卡在ippicv下载超时上一卡就是半小时。这些坑我都踩过所以这篇内容不打算只给你一条命令而是把三条主流路线——apt 安装、pip 安装、源码编译——各自的适用场景、完整步骤、以及最容易翻车的地方全部讲清楚。这篇文章适合谁看如果你是刚接触 Ubuntu 的视觉方向学生想快速把环境跑起来做课程项目那 apt 或 pip 路线就够了如果你是要做产品级部署、需要 CUDA 加速或者自定义模块那源码编译那部分你得仔细看如果你已经在编译过程中报错了可以直接跳到第 4 节的排错部分。全文基于 Ubuntu 20.04.6 LTS 实测Python 3.8 环境GCC 9.4.0。2. 三条安装路线的适用边界与选型逻辑在动手之前先想清楚你要 OpenCV 干什么。这个判断直接决定了你该走哪条路选错了后面全是返工。2.1 apt 路线最省事但版本锁死在 4.2.0sudo apt install libopencv-dev python3-opencv这条命令两分钟就能跑完装出来的版本是 4.2.0。它的优点是稳定、依赖自动处理、和系统库兼容性好。如果你只是用 Python 做做图像读取、边缘检测、模板匹配这类基础操作4.2.0 完全够用。但它的局限也很明显没有 CUDA 支持没有 contrib 模块SIFT 在 4.2.0 里虽然进了主仓库但像cv::ximgproc、cv::face这些还是没有Python 绑定是系统 Python 的如果你用 conda 或者 venv 虚拟环境还得手动把/usr/lib/python3/dist-packages/cv2链接过去很容易出问题。提示apt 装的 OpenCV 头文件在/usr/include/opencv4库文件在/usr/lib/x86_64-linux-gnu用 CMake 的find_package(OpenCV)时如果找不到检查一下OpenCV_DIR是否指向/usr/lib/x86_64-linux-gnu/cmake/opencv4。2.2 pip 路线Python 用户的首选但要注意 wheel 的坑pip install opencv-python装的是预编译 wheel版本通常是最新的 4.8.x 或 4.9.x。它自带 FFmpeg、自带 contrib如果你装的是opencv-contrib-python安装速度快不污染系统环境。但 wheel 包有几个隐藏问题第一它编译时用的 CUDA 版本和你机器上的驱动不一定匹配所以cv2.cuda.getCudaEnabledDeviceCount()大概率返回 0第二它自带的 FFmpeg 是静态链接的某些编码格式比如 H.265可能不支持第三如果你同时装了opencv-python和opencv-contrib-python会出现模块冲突cv2导入时行为不确定。2.3 源码编译最灵活也最容易翻车源码编译能让你精确控制版本、开启 CUDA、开启 contrib、指定 Python 解释器、优化编译选项。但它的代价是编译时间长4 核机器大概 40 分钟到 1 小时依赖多cmake、gcc、g、python3-dev、numpy、libgtk、libavcodec 等一大堆而且网络问题会导致ippicv、face_landmark_model这些第三方文件下载失败。我个人的选型建议是这样的使用场景推荐路线理由课程作业、快速验证算法pip5 分钟搞定版本新需要和 ROS 集成aptROS 的 cv_bridge 依赖系统 OpenCV需要 CUDA 加速源码编译wheel 不带 CUDA需要自定义 contrib 模块源码编译可以只编译需要的模块生产环境部署源码编译 静态库可控性最强3. 源码编译 OpenCV 的完整实操链路这一节是重点。我以 OpenCV 4.5.5 contrib 4.5.5 为例这个版本在 Ubuntu 20.04 上兼容性最好CUDA 支持也成熟。如果你要更新的版本步骤一样把版本号换掉即可。3.1 依赖安装别漏掉这几个容易忽略的包先更新源然后装基础编译工具sudo apt update sudo apt install -y build-essential cmake git pkg-config接着装图像和视频编解码相关的库这几个是imshow、VideoCapture能正常工作的前提sudo apt install -y libjpeg-dev libtiff-dev libpng-dev sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt install -y libxvidcore-dev libx264-dev然后是 GUI 相关的Ubuntu 20.04 默认是 GTK3sudo apt install -y libgtk-3-dev libcanberra-gtk-module libcanberra-gtk3-modulePython 绑定需要sudo apt install -y python3-dev python3-numpy python3-pip如果你要编译 contrib 里的cv::ximgproc或者cv::face还需要sudo apt install -y libatlas-base-dev gfortran libeigen3-dev注意libcanberra-gtk-module这个包很多人会漏掉结果cv2.imshow报Gtk-WARNING: cannot open display或者窗口一闪而过。装完记得export GTK_MODULEScanberra-gtk-module。3.2 源码下载用 git clone 还是下 zip官方仓库在 GitHub 上但国内直接 clone 经常断。我的做法是用--depth 1只拉最新一次提交减少数据量cd ~ git clone --depth 1 --branch 4.5.5 https://github.com/opencv/opencv.git git clone --depth 1 --branch 4.5.5 https://github.com/opencv/opencv_contrib.git如果 git 实在拉不下来就去 Release 页面下Source code (tar.gz)然后本地解压。注意 contrib 的版本号必须和主仓库完全一致4.5.5 对 4.5.5不能混。3.3 CMake 配置每个参数背后的意图这是最关键的一步。先建 build 目录cd ~/opencv mkdir build cd build然后执行 cmake。下面这条命令我拆开讲每个参数cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH~/opencv_contrib/modules \ -D WITH_CUDAON \ -D WITH_CUDNNON \ -D OPENCV_DNN_CUDAON \ -D CUDA_ARCH_BIN7.5 \ -D WITH_GTKON \ -D WITH_FFMPEGON \ -D WITH_TBBON \ -D WITH_OPENMPON \ -D BUILD_EXAMPLESOFF \ -D BUILD_opencv_python3ON \ -D PYTHON3_EXECUTABLE/usr/bin/python3 \ -D PYTHON3_INCLUDE_DIR/usr/include/python3.8 \ -D PYTHON3_NUMPY_INCLUDE_DIRS/usr/lib/python3/dist-packages/numpy/core/include \ -D PYTHON3_PACKAGES_PATH/usr/lib/python3/dist-packages \ ..CMAKE_BUILD_TYPERELEASE开启 -O3 优化比 Debug 快很多。CMAKE_INSTALL_PREFIX/usr/local是默认安装路径头文件会进/usr/local/include/opencv4库文件进/usr/local/lib。OPENCV_EXTRA_MODULES_PATH指向 contrib 的 modules 目录不写这个就没有 contrib 模块。WITH_CUDAON和CUDA_ARCH_BIN7.5是配套的。7.5 对应 Turing 架构比如 RTX 2060、GTX 1660如果你用的是 30 系显卡Ampere改成 8.6如果是 40 系Ada改成 8.9。写错了编译能过但运行时会报no kernel image is available。WITH_FFMPEGON让 OpenCV 能读写 mp4、avi 等格式。WITH_TBBON和WITH_OPENMPON开启多线程加速对cv::resize、cv::GaussianBlur这类操作有明显提升。Python 路径那几个参数如果你用 conda 环境PYTHON3_EXECUTABLE要指向 conda 的 pythonPYTHON3_PACKAGES_PATH指向 conda 的 site-packages。写错了会导致编译出来的cv2.so装到系统 Python 里你的虚拟环境里 import 不到。cmake 跑完后仔细看输出里的Python 3部分确认Interpreter、Libraries、numpy、install path四项都正确。如果有NO说明路径不对要重新配。3.4 编译与安装make -j 的并行度怎么定配置成功后开始编译make -j$(nproc)$(nproc)是 CPU 核心数。但这里有个经验如果你的内存小于 8GB-j开满核心数会导致 OOM内存溢出编译到一半被 kill。我一般用-j$(($(nproc)/2))比如 8 核就用-j4稳一点。编译过程中最常卡住的是ippicv下载。OpenCV 会在 cmake 阶段尝试从第三方地址下载ippicv_2020_lnx_intel64_20191018_general.tgz国内网络经常超时。解决办法是提前手动下载放到~/opencv/.cache/ippicv/目录下文件名保持原样。同理还有face_landmark_model.dat放到~/opencv/.cache/data/下。编译完成后安装sudo make install sudo ldconfigldconfig是刷新动态链接库缓存不执行的话运行程序会报error while loading shared libraries: libopencv_core.so.4.5。3.5 验证安装别只看 import 成功验证分三步。第一步Python 里import cv2 print(cv2.__version__) print(cv2.cuda.getCudaEnabledDeviceCount())如果版本号是 4.5.5CUDA 设备数大于 0说明基本 OK。第二步检查 contrib 模块print(hasattr(cv2, ximgproc)) print(hasattr(cv2, face))第三步写个最小 C 程序用 CMake 编译确认头文件和库都能找到cmake_minimum_required(VERSION 3.10) project(test_opencv) find_package(OpenCV REQUIRED) add_executable(test main.cpp) target_link_libraries(test ${OpenCV_LIBS})#include opencv2/opencv.hpp int main() { cv::Mat img cv::Mat::zeros(100, 100, CV_8UC3); cv::imwrite(test.jpg, img); return 0; }能编译通过并生成 test.jpg才算真正装好了。4. 编译过程中最常翻车的五个点与排查链路这一节我按“现象 → 原因 → 解决”的结构写都是我自己踩过的。4.1 ippicv 下载超时导致 cmake 中断现象cmake 输出停在ICV: Downloading ippicv_2020_lnx_intel64_20191018_general.tgz...然后等很久报Timeout或Hash mismatch。原因OpenCV 的 cmake 脚本会从第三方地址拉这个文件国内网络不稳定。解决手动下载。文件在 OpenCV 的 GitHub Release 附件里能找到下载后放到~/opencv/.cache/ippicv/文件名必须是ippicv_2020_lnx_intel64_20191018_general.tgz。如果目录不存在就手动建。放好后重新跑 cmake它会检测到本地文件直接跳过下载。4.2 Python 绑定装到了系统 Python 而不是虚拟环境现象在 conda 环境里import cv2报ModuleNotFoundError但系统 Python 里能 import。原因cmake 时PYTHON3_EXECUTABLE指向了/usr/bin/python3而不是 conda 的 python。解决重新 cmake把PYTHON3_EXECUTABLE改成$(which python3)的实际路径PYTHON3_PACKAGES_PATH改成python3 -c import site; print(site.getsitepackages()[0])的输出。然后重新 make install。注意不用重新 makecmake 后直接make install就行因为 Python 绑定是最后链接阶段生成的。4.3 CUDA 架构不匹配导致运行时崩溃现象编译一切正常但运行cv2.cuda.GpuMat()时报CUDA error: no kernel image is available for execution on the device。原因CUDA_ARCH_BIN写错了编译出的 PTX 代码和你的显卡架构不匹配。解决查你的显卡架构。nvidia-smi看显卡型号然后对照RTX 20 系是 7.5RTX 30 系是 8.6RTX 40 系是 8.9Tesla T4 是 7.5A100 是 8.0。改对后重新 cmake make。如果不想每次查可以写多个架构用分号隔开比如-D CUDA_ARCH_BIN7.5;8.6但编译时间会翻倍。4.4 imshow 报 GTK 错误或窗口不显示现象cv2.imshow报Gtk-WARNING: cannot open display或者窗口一闪就没了。原因缺少 GTK 模块或者DISPLAY环境变量没设。解决先确认libgtk-3-dev和libcanberra-gtk3-module装了。然后export GTK_MODULEScanberra-gtk-module。如果是 SSH 远程需要 X11 转发ssh -X登录并且本地要有 X Server。实在不行就用cv2.imwrite保存图片看结果别死磕 imshow。4.5 和 apt 装的 OpenCV 冲突现象编译装完后Python 里 import 的 cv2 还是 4.2.0或者 C 链接时报undefined reference。原因系统里同时存在/usr/lib/python3/dist-packages/cv2apt 装的和/usr/local/lib/python3.8/dist-packages/cv2源码装的Python 优先加载了前者。解决把 apt 装的卸掉sudo apt remove python3-opencv libopencv-dev然后sudo ldconfig。如果不想卸就在 Python 里手动调整sys.path把/usr/local/lib/python3.8/dist-packages放到最前面。C 的话在 CMakeLists 里显式指定set(OpenCV_DIR /usr/local/lib/cmake/opencv4)。5. 装完之后怎么用几个提升效率的配置装好只是第一步用起来顺手还得做几件事。5.1 配置 pkg-config 让编译命令更短源码安装后/usr/local/lib/pkgconfig/opencv4.pc应该存在。确认PKG_CONFIG_PATH包含这个目录export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH然后编译单个 C 文件就可以这样g test.cpp -o test $(pkg-config --cflags --libs opencv4)比手写一堆-I和-l方便多了。5.2 在 CMake 项目里正确 find_package很多人的 CMakeLists 写find_package(OpenCV REQUIRED)后报找不到。原因是/usr/local/lib/cmake/opencv4不在默认搜索路径。加一行set(OpenCV_DIR /usr/local/lib/cmake/opencv4) find_package(OpenCV REQUIRED)如果还不行检查OpenCVConfig.cmake是否真的在那个目录下。源码安装有时会把它放到/usr/local/share/opencv4那就改路径。5.3 多版本共存时的切换技巧如果你机器上既有 apt 的 4.2.0又有源码的 4.5.5可以用环境变量切换。写两个脚本# use_system_opencv.sh export OpenCV_DIR/usr/lib/x86_64-linux-gnu/cmake/opencv4 export LD_LIBRARY_PATH/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH # use_custom_opencv.sh export OpenCV_DIR/usr/local/lib/cmake/opencv4 export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH用的时候source一下就行。Python 那边同理通过sys.path控制。5.4 验证 CUDA 加速是否真的生效别只看getCudaEnabledDeviceCount()返回非零就以为成了。写个实际测试import cv2 import numpy as np import time img np.random.randint(0, 255, (4000, 4000, 3), dtypenp.uint8) gpu_img cv2.cuda_GpuMat() gpu_img.upload(img) # CPU t1 time.time() for _ in range(10): cv2.GaussianBlur(img, (31, 31), 0) print(CPU:, time.time() - t1) # GPU t2 time.time() for _ in range(10): gpu_blur cv2.cuda.createGaussianFilter(cv2.CV_8UC3, cv2.CV_8UC3, (31, 31), 0) result gpu_blur.apply(gpu_img) print(GPU:, time.time() - t2)如果 GPU 比 CPU 还慢说明数据传输开销大于计算收益小图别用 GPU。大图4000x4000 以上才能看出优势。6. 我个人的几条实操心得最后分享几个文档里不会写、但实际用起来很关键的点。第一编译前先sudo apt update sudo apt upgrade把系统包更新到最新。Ubuntu 20.04 早期的 GCC 9.3 有 bug编译 OpenCV 4.5.x 时会在modules/dnn里报内部错误升级到 9.4 就好了。第二make的时候用make -j$(nproc) 21 | tee build.log把日志存下来。编译报错时终端滚屏太快根本看不清哪一行出错有日志文件就能慢慢查。第三如果你只是用 Python其实没必要源码编译。pip install opencv-contrib-python4.5.5.64这个 wheel 版本和源码 4.5.5 功能几乎一样省下 40 分钟编译时间。只有需要 CUDA 或者 C 接口时才值得编译。第四编译 contrib 时如果某个模块报错比如cv::cudacodec依赖 NVCUVID 头文件可以在 cmake 里用-D BUILD_opencv_cudacodecOFF单独关掉不用整个重来。第五装完后把~/opencv和~/opencv_contrib目录留着别删。以后想加模块或者换版本重新 cmake 就行不用重新下载。但build目录可以删占空间大重新 cmake 会重建。这套流程我在三台不同配置的机器上跑过一台 8 核 16G 无显卡的服务器一台 6 核 32G 带 RTX 2060 的工作站一台 4 核 8G 的迷你主机。配置参数基本一致只有CUDA_ARCH_BIN和-j并行度按机器调整。只要依赖装全、路径配对一次过的概率很高。真正花时间的不是编译本身而是排查那些因为网络、路径、版本不匹配导致的意外。把上面第 4 节的五个坑提前避开能省下至少两个小时。