ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu 20.04下OpenCV 4.5.0与C++开发环境搭建指南

Ubuntu 20.04下OpenCV 4.5.0与C++开发环境搭建指南 1. 环境准备与系统基础配置1.1 为什么要先处理系统和软件源说实话在 Ubuntu 20.04 上搭建 OpenCV 4.5.0 和 C 环境很多人一上来就急着下载源码、敲 cmake结果编译到一半各种报错要么缺依赖、要么网络超时、要么版本冲突。我早期也踩过不少这种坑后来才明白一个道理环境搭建这件事九成的问题都出在准备工作没做到位。Ubuntu 20.04 默认的 apt 软件源在国内访问速度通常不太理想尤其是编译 OpenCV 需要安装大量的依赖包如果源的速度慢或者不稳定光是 apt install 这一步就能耗掉你大半个小时。所以在开始之前我建议先把软件源更换为国内镜像源比如清华、阿里或者中科大的源。这一步不复杂但收益非常明显。具体操作方式是备份原有的 sources.list 文件然后用新的镜像源内容替换。这里以清华源为例sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo sed -i s/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g /etc/apt/sources.list sudo sed -i s/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g /etc/apt/sources.list sudo apt update换完源之后apt update的速度会明显改善。这里有个细节Ubuntu 20.04 对应的代号是 focal如果你用的镜像源配置不对可能会出现“仓库没有 Release 文件”之类的报错这时候检查一下 sources.list 里的代号是否正确就行。1.2 安装编译工具链与核心依赖接下来是安装编译工具链。OpenCV 4.5.0 的源码编译需要 CMake、GCC、G 等工具这些可以通过 apt 直接安装sudo apt install -y build-essential cmake git pkg-configbuild-essential 这个包会一次性装好 gcc、g、make 等基础编译工具是 Ubuntu 上做 C/C 开发绕不开的组件。cmake 用于生成编译配置pkg-config 用于管理库的编译参数。这些都是最基础的工具但很多人容易漏掉 pkg-config导致后续在编译 OpenCV 程序时找不到库文件路径报出一堆奇怪的链接错误。然后是图形和图像处理相关的依赖库。OpenCV 的很多功能模块依赖外部库比如处理 PNG、JPEG 图片需要 libpng、libjpeg读取摄像头视频流需要 libavcodec、libavformatGUI 显示需要 GTK 或者 Qt。建议一次性把常用的依赖都装齐sudo apt install -y libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt install -y libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev sudo apt install -y libatlas-base-dev gfortran python3-dev python3-numpy这一堆依赖里libgtk-3-dev 是用来支持 OpenCV 的 highgui 模块显示窗口的libavcodec-dev、libavformat-dev、libswscale-dev 是视频编解码的核心库libv4l-dev 则是摄像头采集的底层支持。如果你后续要用到摄像头这些一个都不能少。注意很多人编译 OpenCV 时报错“No package gtk-3.0 found”就是因为在 CMake 配置之前没有安装 libgtk-3-dev。这类问题最好的解决办法就是提前把依赖装齐别等到报错再回头补。另外如果你需要在 Python 中调用 OpenCV就需要安装 python3-dev 和 python3-numpy。虽然这篇文章主要讲 C 环境但 OpenCV 编译时检测到 Python 开发环境会自动生成对应的 Python 绑定属于锦上添花的操作。2. OpenCV 4.5.0 源码编译与安装2.1 源码下载与目录规划依赖装好之后就可以开始下载 OpenCV 4.5.0 的源码了。这里我不建议直接去 GitHub 页面手动下载 zip 包一方面解压麻烦另一方面后续更新和查看版本信息都比较别扭。用 git clone 的方式会更干净cd ~ mkdir -p opencv_build cd opencv_build git clone --branch 4.5.0 --depth 1 https://github.com/opencv/opencv.git这里使用了--branch 4.5.0指定分支--depth 1做浅克隆只拉取最新的一次提交可以大大减少下载时间。如果你在中国大陆GitHub 的访问速度可能不太稳定可以考虑在 clone 时使用代理镜像或者直接用 release 页面的压缩包下载链接配合下载工具。如果后续要用到 SIFT、SURF 这些非免费模块还需要额外克隆 opencv_contrib 仓库并在 CMake 配置时指定 contrib 模块路径。对于大部分初学者来说主线版本的 OpenCV 已经足够用了不建议一开始就引入 contrib等有明确需求时再加也不迟。目录规划方面我习惯把源码和编译目录分开。OpenCV 官方推荐的构建方式是在源码目录外单独建一个 build 目录这样做的好处是后续重新编译时可以直接删除 build 目录不会污染源码。我自己的习惯是cd opencv_build/opencv mkdir -p build cd build这样最终的编译产物都会集中在 build 目录里路径清晰方便后续排查问题。2.2 CMake 配置参数详解进入了 build 目录之后核心的一步就是执行 CMake 配置命令。很多教程直接复制一大段命令跑完就完事但完全不解释每个参数的含义导致读者遇到问题根本不知道从哪里改起。我这里把参数拆开讲一讲。先看一条最常用的完整配置命令cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D WITH_TBBON \ -D WITH_V4LON \ -D WITH_QTOFF \ -D WITH_GTKON \ -D OPENCV_GENERATE_PKGCONFIGON \ -D OPENCV_ENABLE_NONFREEON \ -D BUILD_EXAMPLESOFF \ -D BUILD_opencv_python3ON \ -D PYTHON_EXECUTABLE$(which python3) \ -D WITH_OPENGLON ..逐个看关键参数CMAKE_BUILD_TYPERELEASE编译发布版本编译器会做优化运行效率更高。如果只是为了调试可以改成 DEBUG但日常使用建议 RELEASE。CMAKE_INSTALL_PREFIX/usr/local指定安装路径。/usr/local 是 Linux 下第三方软件的标准安装目录头文件装在 /usr/local/include库文件装在 /usr/local/lib默认路径下让后面的编译更容易找到 OpenCV。WITH_TBBONTBB 是 Intel 的并行计算库开启后可以提升 OpenCV 在多核 CPU 上的运行效率。前提是你已经安装了 libtbb-dev如果没有安装CMake 配置时不会报错会自动禁用。WITH_V4LON开启 Video4Linux 支持摄像头采集必备。WITH_QTOFF / WITH_GTKONhighgui 模块需要一个 GUI 工具包来显示图像窗口。GTK 和 Qt 选一个即可GTK 在 Ubuntu 上兼容性更好装上之后显示窗口不会出问题。如果两个都装了CMake 会默认优先使用 Qt但 Qt 在纯命令行的 Ubuntu 服务器上经常缺少依赖所以我个人建议直接用 GTK。OPENCV_GENERATE_PKGCONFIGON这是 OpenCV 4.5.0 比较重要的一个参数。OpenCV 4 从某个版本开始不再默认生成 opencv.pc 文件导致使用 pkg-config 方式编译 C 程序时找不到库路径。加上这个参数后编译安装完成会自动生成 opencv4.pc省去手动配置的麻烦。OPENCV_ENABLE_NONFREEON开启非免费模块会包含 SIFT、SURF 等专利算法。这个参数是可选的如果只是做基础图像处理不涉及特征提取可以不开。BUILD_EXAMPLESOFF不编译 OpenCV 自带的示例程序节省大量编译时间。示例代码在源码的 samples 目录里可以直接查看没必要编译成可执行文件。BUILD_opencv_python3ON和PYTHON_EXECUTABLE$(which python3)这两个参数配合使用让 OpenCV 同时生成 Python 3 的接口库。如果你确定只用 C可以不加但加上也不影响 C 的使用反而多一条路。提示如果你的服务器内存比较小比如 2GB 的云主机建议在 CMake 配置时加上-D BUILD_TESTINGOFF同时在后续的 make 编译阶段限制并行任务数避免编译时内存耗尽被系统 kill 掉。2.3 编译、安装与路径配置CMake 配置成功之后输出信息的最后会列出一份完整的配置摘要包括检测到的库、启用的模块、安装路径等。建议花一分钟扫一眼确认第三方的库有没有被正确检测到比如 GTK、V4L 等。如果GUI: GTK显示为 NO那说明 libgtk-3-dev 没装好后续程序里调用imshow会直接崩溃。确认配置无误后开始编译。这一步我是强烈建议用多线程的OpenCV 源码体量不小单线程编译在普通机器上可能要一两个小时多线程能省不少时间make -j$(nproc)nproc命令会返回 CPU 的核心数make -j$(nproc)表示用全部核心并行编译。如果是在虚拟机里内存不是特别充足建议手动指定一个保守的数值比如make -j4。编译过程中会刷大量的日志如果你发现某个 .cpp 文件编译报错先不要慌记录下报错信息绝大多数情况都是依赖库缺少或者版本不匹配导致的排查思路我在后面专门讲。编译完成后就是安装sudo make install sudo ldconfigmake install会把头文件、库文件、CMake 配置文件安装到之前设置的路径下。ldconfig的作用是更新动态链接库缓存让系统能够找到新安装的库文件。漏掉ldconfig的话编译时链接库的阶段会报“cannot find -lopencv_core”之类的错误。安装完成之后验证一下是否成功pkg-config --modversion opencv4如果能够输出版本号 4.5.0说明安装没问题了。这里要注意OpenCV 4 的 pkg-config 名称是 opencv4不是 opencv。如果你习惯了旧版本的命令很容易在这一步搞混。3. C 开发环境搭建3.1 编译器与 CMake 版本检查OpenCV 装好之后接下来要准备 C 的开发环境。Ubuntu 20.04 自带的 GCC 版本是 9.xCMake 版本是 3.16.x对于 OpenCV 4.5.0 来说都够用。不过还是建议先确认一下版本g --version cmake --version如果 GCC 版本过低编译 OpenCV 程序时可能会报“不支持 C 11 标准”之类的错误。Ubuntu 20.04 的默认工具链不存在这个问题但如果你是从旧的 Ubuntu 版本升级上来的保险起见还是检查一下。开发 C 程序有两种常见方式直接用 g 命令行编译或者用 CMake 管理工程。命令行编译适合单文件的小测试比如g -stdc11 test.cpp $(pkg-config --cflags --libs opencv4) -o testpkg-config --cflags --libs opencv4会自动展开 OpenCV 头文件路径和库链接参数。这种方式简单粗暴但项目文件一多就不好维护了。正式的工程项目我建议用 CMake 组织。3.2 VS Code 配置 C/C 开发环境编辑器方面VS Code 是当前比较主流的选择插件生态丰富配置也灵活。在 Ubuntu 20.04 上装 VS Code 可以用微软官方源或者直接去官网下载 .deb 包安装。这里推荐用 deb 包因为可以顺便把微软的软件源注册好以后能直接用 apt upgrade 升级。打开 VS Code 之后首先安装 C/C 扩展插件。这个插件由微软官方维护提供 IntelliSense 智能提示、代码补全、调试功能。具体的配置点在.vscode/c_cpp_properties.json里核心的配置项是includePath也就是头文件搜索路径。你要把 OpenCV 的 include 目录加进去{ configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /usr/local/include/opencv4 ], defines: [], compilerPath: /usr/bin/g, cStandard: c11, cppStandard: c17, intelliSenseMode: gcc-x64 } ], version: 4 }很多人在 VS Code 里写 OpenCV 代码时发现头文件下面会有红色波浪线提示找不到 opencv2/opencv.hpp大多数原因就是 includePath 没配好。还有个容易忽略的点是如果你系统里装了多个版本的 OpenCVincludePath 里配了旧版本的路径IntelliSense 可能会给出错误的提示。建议固定使用 /usr/local/include/opencv4 这个路径和 CMake 的搜索路径保持一致。另外VS Code 的 C/C 插件的智能提示搜索路径是有优先级的includePath里配置的顺序会直接影响提示的准确性。把项目目录路径放在前面系统路径放在后面这样能够避免被其他的头文件干扰。3.3 用 CMake 组织工程CMake 是目前 C 工程最主流的构建系统OpenCV 官方也是用 CMake 编译的所以用 CMake 来构建自己的项目是最自然而然的选择。一个最简单的 CMakeLists.txt 长这样cmake_minimum_required(VERSION 3.10) project(HelloOpenCV) set(CMAKE_CXX_STANDARD 11) find_package(OpenCV REQUIRED) add_executable(hello main.cpp) target_link_libraries(hello ${OpenCV_LIBS})这里有三个关键点需要说明第一find_package(OpenCV REQUIRED)的核心原理是查找 OpenCV 安装时生成的OpenCVConfig.cmake文件。如果你在 CMake 配置时报错“Could not find OpenCV”大概率是因为这个文件不在默认搜索路径里。解决办法是在 CMake 命令中手动指定路径cmake -D OpenCV_DIR/usr/local/lib/cmake/opencv4 ..第二${OpenCV_LIBS}变量会被展开为一长串 OpenCV 库名称。理论上手动逐个链接也可以但用这个变量最省事。CMake 会帮你把所有必需的库全部链接上不用担心漏掉。第三CMakeLists.txt 里用find_package找到的 OpenCV 版本和路径可以通过下面的方式打印出来方便排查问题message(STATUS OpenCV version: ${OpenCV_VERSION}) message(STATUS OpenCV libraries: ${OpenCV_LIBS})编译运行mkdir build cd build cmake .. make ./hello整个过程清爽干净后续增加源文件只需要在 CMakeLists.txt 里加一行add_executable或者target_sources就行。4. 编写并运行第一个 OpenCV 程序4.1 读取并显示图片环境都搭建好之后我们来写第一个练手程序。目标很简单读取一张图片在窗口里显示出来然后保存一份灰度图副本。这个流程覆盖了 OpenCV 最核心的几个模块core数据结构、imgcodecs图片读写、imgproc图像处理、highgui界面显示。先写代码保存为 display.cpp#include opencv2/opencv.hpp #include iostream int main(int argc, char** argv) { if (argc ! 2) { std::cout Usage: ./display image_path std::endl; return -1; } cv::Mat image cv::imread(argv[1], cv::IMREAD_COLOR); if (image.empty()) { std::cerr Could not read the image: argv[1] std::endl; return -1; } std::cout Image width: image.cols , height: image.rows std::endl; cv::Mat gray; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); cv::imshow(Original Image, image); cv::imshow(Gray Image, gray); cv::imwrite(gray_output.jpg, gray); cv::waitKey(0); cv::destroyAllWindows(); return 0; }这段代码有几个细节值得注意第一image.empty()的判断非常关键。很多人第一次运行时图片路径写错了或者权限不足导致 imread 返回空矩阵但程序不报错直到后面 imshow 的时候才崩溃。提前判断 empty 能够让问题在早期暴露出来比后面排查崩溃要省事得多。第二cv::waitKey(0)的作用是等待用户按键输入参数 0 表示无限等待。没有这一行的话窗口可能会一闪而过甚至直接卡死。在高版本的 OpenCV 中因为 GTK 的事件循环机制waitKey是让窗口正常显示和响应的前提。第三cv::cvtColor中的cv::COLOR_BGR2GRAY是 OpenCV 的颜色空间转换标志。OpenCV 默认读图的通道顺序是 BGR 而不是 RGB这个概念在刚入门时很容易搞混我记得后来做项目的时候图像颜色偏蓝偏红基本都是这里出了问题。编译运行的方式按之前的 CMake 工程来把 main.cpp 换成 display.cpp在 build 目录里重新 cmake 和 make然后用一张测试图片执行./display /path/to/your/test.jpg如果一切顺利会弹出两个窗口一个彩色一个灰度。按任意键窗口关闭当前目录下会生成 gray_output.jpg。4.2 打开摄像头实时画面图片处理只是入门摄像头实时采集才是 OpenCV 在视觉项目里最常见的应用场景。这里写一个简单的程序打开默认摄像头实时显示画面并实时计算帧率。相关热词里提到 ubuntu 20.04 网络配置和摄像头正好可以拿这个例子串起来。先写代码保存为 webcam.cpp#include opencv2/opencv.hpp #include iostream #include chrono int main() { cv::VideoCapture cap(0); if (!cap.isOpened()) { std::cerr Error: Could not open camera. std::endl; return -1; } cv::Mat frame; auto start_time std::chrono::steady_clock::now(); int frame_count 0; while (true) { cap frame; if (frame.empty()) { break; } cv::imshow(Webcam, frame); frame_count; auto now std::chrono::steady_clock::now(); double elapsed std::chrono::durationdouble(now - start_time).count(); if (elapsed 1.0) { double fps frame_count / elapsed; std::cout FPS: fps std::endl; frame_count 0; start_time now; } if (cv::waitKey(30) 27) { // ESC key break; } } cap.release(); cv::destroyAllWindows(); return 0; }这段代码里最关键的是cv::VideoCapture cap(0)。参数 0 表示打开系统中第一个可用的摄像头设备对应 /dev/video0。如果电脑同时插了多个摄像头可以在 0、1、2 之间切换来尝试不同的设备。使用摄像头时请一定检查一下设备节点是否存在以及当前用户是否有访问权限ls -l /dev/video*有时候摄像头节点存在但当前用户不在 video 组里程序会报权限不足打不开设备。这时候把当前用户加入 video 组重新登录即可sudo usermod -aG video $USER另外在虚拟机中使用 USB 摄像头需要先在虚拟机的设置里把 USB 设备直通给虚拟机否则宿主机能看到设备VM 里却完全无感知。这个坑我在 VMware 里踩过很多次win 下没问题换到 Ubuntu 虚拟机就发现摄像头图标是灰的排查半天发现是 USB 直通没做。5. 常见问题与排查实录5.1 编译报错与路径问题速查表我在多个版本、多台机器上搭过 OpenCV 环境把遇到的典型问题按出错场景整理成了表格方便你对照排查。出错场景错误现象根本原因解决办法cmake 配置阶段Could not find OpenCVOpenCV_DIR 指向不对或者没安装手动指定 -D OpenCV_DIR/usr/local/lib/cmake/opencv4cmake 配置阶段No package gtk-3.0 found缺少 GTK 开发库sudo apt install -y libgtk-3-dev 后重新配置make 编译阶段fatal error: X11/Xlib.h: No such file or directory缺少 X11 开发头文件sudo apt install -y libx11-dev libxext-devmake 编译阶段undefined reference topng_set_chunk_malloc_maxlibpng 版本冲突更新 libpng-dev 后重新编译必要时先 make cleanmake 安装后pkg-config 找不到 opencv4编译时未开 OPENCV_GENERATE_PKGCONFIG重新 cmake 时加上 -D OPENCV_GENERATE_PKGCONFIGONg 链接阶段cannot find -lopencv_coreldconfig 未运行或库路径未注册sudo ldconfig或设置 LD_LIBRARY_PATH/usr/local/libg 链接阶段/usr/bin/ld: cannot find -lstdc未安装 build-essentialsudo apt install -y build-essential运行阶段error while loading shared libraries: libopencv_core.so.4.5动态链接库路径未配置检查 /etc/ld.so.conf 包含 /usr/local/lib然后 sudo ldconfig运行阶段Gtk-WARNING: cannot open display没有图形界面环境使用远程桌面或切换 tty或改用无 GUI 模式imwrite 代替 imshow运行阶段camera failed to open权限不足或设备不存在检查 /dev/video* 与用户组权限5.2 我总结的几个避坑经验结合这些年的实际经验我额外分享几条常规文档不会写但非常实用的经验。第一编译前确认磁盘空间充足。OpenCV 编译过程中build 目录会占用 4-6GB 的空间如果是树莓派或者小容量分区很容易在编译到一半时因磁盘写满而失败。编译之前用df -h瞄一眼剩余空间确保在 10GB 以上比较稳妥。第二尽量不要用 apt 安装系统自带的 libopencv-dev。Ubuntu 20.04 的官方软件源里其实有 OpenCV 4.2 版本命令行apt install libopencv-dev一条命令就能装好看起来很省事。但版本既然是 4.5.0说明你对版本有特定要求而且自己编译能够控制编译参数比如开启 TBB 优化、Nonfree 模块等。如果你在图省事装了系统自带版本后续 pkg-config 的模块名、头文件路径都会跟你编译出来的版本混在一起很难排查。要么全用 apt 版本要么全用源码编译版本别混用。第三make -j 的并行数不是越大越好。很多人看到推荐make -j$(nproc)觉得核心数越多越好。如果你的内存比较小并行编译时每个编译进程都会占用几百 MB 内存N 个进程同时跑内存很快就爆了最终 OOM 被系统杀掉反而更浪费时间。我的建议是内存 16GB 以上可以拉满8GB 用-j44GB 用-j2稳字当头。第四同一个终端会话里多跑几次 source 和 export不如直接修改系统配置文件。如果你在配置动态库路径时用了export LD_LIBRARY_PATH/usr/local/lib这条命令只在当前终端有效新开终端又没了。正确做法是写入配置文件echo export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc5.3 终极验证用 CMake 一步到位跑通项目前面所有的配置和排查最终都要落到“能跑起来一个真正的 C 工程”才算数。这里我提供一个最小的完整工程模板你复制过去改成自己的代码就能用my_opencv_project/ ├── CMakeLists.txt ├── main.cpp └── build/CMakeLists.txt 用我之前写的模板main.cpp 放一张图片读取的程序。然后cd my_opencv_project mkdir build cd build cmake -D CMAKE_BUILD_TYPERELEASE .. make -j4 ./my_opencv_project ../test.jpg这一步跑通了说明你的 Ubuntu 20.04 OpenCV 4.5.0 C 环境已经完全可用。从个人体会来看环境搭建最大的障碍其实不在 OpenCV 本身而在于 Linux 的依赖管理体系。库与库之间的版本要求、头文件与动态库的查找路径、编译时与运行时的环境差异这些才是真正耗时的地方。但只要理解了 apt、CMake、pkg-config、ldconfig 这几个关键环节的原理大部分问题都能快速定位。这套环境装好之后后面不管是做图像处理、视觉算法入门还是跑深度学习的推理前处理都能省下很多折腾的时间。
返回列表