ARTICLE DETAIL

资讯详情

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

Ubuntu下源码编译OpenCV 4.5.0完整流程与环境配置

Ubuntu下源码编译OpenCV 4.5.0完整流程与环境配置 1. 为什么我不用apt install libopencv-dev非要源码编译先说一个很现实的问题Ubuntu 20.04的apt源里其实自带OpenCV一个sudo apt install libopencv-dev就能搞定很多人一看这么省事就直接装了。但我建议你别这么干至少在你打算认真用C做视觉开发的前提下源码编译是更值得走的一条路。apt源里的OpenCV版本是4.2.0跟我们要搭建的4.5.0差了三个小版本。听起来差距不大但OpenCV从4.2到4.5之间改了很多API行为尤其是DNN模块、相机标定相关的接口有过调整网上很多新教程和开源项目都基于4.4以上版本写的。你用4.2去编译别人的项目经常会出现函数签名对不上、找不到头文件这类问题排查起来非常浪费时间。更重要的是apt安装的OpenCV是不带opencv_contrib扩展模块的而contrib里有SIFT、SURF这些经典特征点算法还有aruco、xfeatures2d、text这些实用模块。如果你后面做AR、做物体识别、做特征匹配这些模块基本是绕不开的。虽然可以单独装libopencv-contrib-dev但我实测下来apt源里的contrib跟主库版本匹配有时候会有问题不如源码编译一次搞定版本自己把控想开哪个模块就开哪个。还有一点源码编译可以自己控制优化选项。比如你想开TBB多线程加速、想开Eigen矩阵库、想把OpenCL的离线缓存打开这些在apt包里都是默认配置没得选。源码编译的好处就是CMake配置完全由你掌控编译出来的是“为你这台机器定制”的库性能上通常会更好一点。当然源码编译也有代价最大的代价就是时间和磁盘空间。完整编译一次4.5.0大概需要30到60分钟取决于你的CPU核心数和内存大小安装完占用的空间大约1.5GB到2GB。如果你的项目只是简单调个接口、跑个demo那apt安装确实更省事但如果你确定要在OpenCV上做一段时间开发那今天这篇完整流程就非常有参考价值了。我当前使用的系统环境是Ubuntu 20.04.6 LTS内核版本5.15GCC版本9.3.0CMake版本3.16.3这些是Ubuntu 20.04默认软件源里的版本。OpenCV 4.5.0是2020年10月发布的版本跟这套工具链的兼容性非常稳定实测编译过程中没有遇到任何编译器版本相关的问题。2. 编译前的依赖准备缺了这些库后面全是坑很多人编译OpenCV失败不是CMake配置写错了而是系统里缺依赖库。OpenCV的源码编译虽然会自己下载一些第三方库但大部分底层的图像编解码、视频处理、GUI支持库都是依赖系统自带的。缺了某个库CMake配置阶段通常不会报错顶多是在输出的表格里显示某个模块为NO但等到你真正运行时才发现功能缺失这才是最头疼的。2.1 基础工具链build-essential和cmake第一个要装的是编译工具链这个没什么好说的GCC和G是编译OpenCV源码的基础CMake是构建系统的核心。sudo apt update sudo apt install -y build-essential cmake git pkg-config这里我特别提一下pkg-config很多人容易忽略它。OpenCV编译完成后我们需要通过pkg-config来让编译器自动找到OpenCV的头文件和库文件路径。如果没有安装pkg-config后面的环境配置会非常麻烦而且在CMake中find_package(OpenCV)的查找过程也会受到影响。2.2 图像编解码库JPEG、PNG、TIFFOpenCV处理图像文件时需要依赖系统的编解码库。虽然OpenCV内部自带了一些基础的编解码实现但为了最佳兼容性和性能官方推荐安装系统的开发库。sudo apt install -y libjpeg-dev libpng-dev libtiff-dev这里有个细节值得说一下libjpeg-dev和libpng-dev是几乎所有图像处理项目的基础但libtiff-dev经常被忽略。如果你的项目需要处理卫星影像、医学图像这种高深度图像格式TIFF支持是必须的。我当初第一次编译OpenCV时就没装TIFF库结果CMake配置阶段输出显示TIFF: NO我也没当回事直到后来用cv::imread读一张.tif格式的16位深度图像读出来全是黑的排查了好久才发现是因为没装TIFF支持。2.3 视频处理库FFmpeg全家桶视频读写是OpenCV的核心功能之一尤其是在做视频分析、摄像头采集这类项目时。OpenCV通过FFmpeg来实现视频文件的解码和编码所以FFmpeg相关的开发库必须装齐。sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev我建议把这几个库一起装掉不要只装libavcodec-dev和libavformat-dev。特别说一下libx264-dev如果缺了它OpenCV的VideoWriter在写MP4格式视频时会提示找不到对应的编码器运行时会直接抛异常。而且H.264编码是目前最通用的视频编码格式不装的话视频处理功能等于废了一半。另外libv4l-dev是Video4Linux的开发库这个库关系到OpenCV能否通过V4L2接口访问USB摄像头。如果你之后要做树莓派或者Linux工控机上的摄像头采集这个库是必须的。2.4 GUI与显示依赖GTK和CanberraOpenCV的highgui模块负责窗口显示、鼠标键盘事件处理它有两种后端可以选择GTK和Qt。Ubuntu桌面版默认使用GTK所以我这里选择的是GTK3。sudo apt install -y libgtk-3-dev libcanberra-gtk-module这里有一个我踩过的坑只装libgtk-3-dev不装libcanberra-gtk-module编译能通过cv::imshow显示窗口也没问题但是运行时会提示Gtk-WARNING **: 无法找到主题引擎窗口打开后还会伴随着一个警告声音。虽然不影响功能但每次都刷这个警告真的很烦人。libcanberra-gtk-module就是用来解决这个声音和主题问题的。CMake配置阶段会检测GTK版本如果检测到GTK3在输出表格中会显示GUI: GTK 3.x。如果你在配置输出里看到的是GTK: NO那编译出来的OpenCV虽然能用但无法显示图像窗口这个问题后面会讲怎么排查。2.5 数学与线性代数库ATLAS、LAPACK、EigenOpenCV在很多算法中需要用到矩阵运算虽然它自己实现了部分线性代数功能但调用系统优化过的BLAS/LAPACK库可以获得更好的性能。sudo apt install -y libatlas-base-dev liblapacke-dev libeigen3-dev这里libatlas-base-dev是ATLAS的BLAS实现liblapacke-dev提供了LAPACK的C接口这两个主要用于优化矩阵运算性能。libeigen3-dev是Eigen模板库OpenCV在calibrateCamera、findFundamentalMat等几何计算中会用到Eigen来进行矩阵运算。2.6 Python开发库可选建议装虽然我们主打C环境但OpenCV编译时如果检测到Python3的开发环境会自动生成Python绑定。这其实是个额外福利同一个编译版本既能给C用也能给Python用两边版本完全一致不会出现Python环境和C环境OpenCV版本不一致导致的行为差异。sudo apt install -y python3-dev python3-numpy python3-pip如果你确定自己完全不需要Python接口可以在后面CMake配置时用-D BUILD_opencv_python3OFF来关闭但如果你想留个后路建议保留这个功能。我自己的习惯是保留的因为有时候快速验证一个算法效果用Python写demo比C快得多。依赖库装完之后我建议先重启一下终端或者重新登录确保环境变量生效避免后面编译时出现奇怪的问题。3. 源码下载与CMake配置几个关键参数的意义依赖库准备好之后就是下载OpenCV源码和配置CMake了。这个阶段决定了你的OpenCV最终长出什么样所以每一步都值得认真对待。3.1 下载主库和contrib扩展库OpenCV的源码托管在GitHub上我使用的是官方4.5.0稳定版。直接clone或者下载tag包都行我习惯用git clone方便以后切分支。cd ~ mkdir -p opencv_build cd opencv_build git clone -b 4.5.0 --depth 1 https://github.com/opencv/opencv.git git clone -b 4.5.0 --depth 1 https://github.com/opencv/opencv_contrib.git如果你没有安装git或者直接用浏览器下载zip包也可以但记得主库和contrib的版本必须保持一致4.5.0的主库对应4.5.0的contrib。版本不对应会出现模块加载失败或编译错误这个问题在GitHub的issue区经常有人遇到本质上就是版本不匹配导致的。两个源码目录要放在同一级目录下比如都放在~/opencv_build里。这样后面CMake配置时OPENCV_EXTRA_MODULES_PATH的参数路径就很直观。3.2 CMake配置先看参数再看命令在跑CMake命令之前我先解释一下几个关键参数的作用这样你后面自己调整时也知道该改什么。cd opencv mkdir -p build cd build cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH~/opencv_build/opencv_contrib/modules \ -D OPENCV_GENERATE_PKGCONFIGON \ -D BUILD_TESTSOFF \ -D BUILD_PERF_TESTSOFF \ -D BUILD_EXAMPLESOFF \ -D WITH_TBBON \ -D WITH_EIGENON \ -D WITH_V4LON \ -D OPENCV_ENABLE_NONFREEON \ ..逐个说一下这些参数的含义CMAKE_BUILD_TYPERELEASE编译Release版本编译器会开启O3优化运行性能最好。OpenCV没有Debug版本调试的硬需求正式开发都用Release。CMAKE_INSTALL_PREFIX/usr/local指定安装路径默认就是/usr/local头文件装到/usr/local/include库文件装到/usr/local/lib。OPENCV_EXTRA_MODULES_PATH指定contrib模块的路径这个就是刚才下载的扩展模块目录。OPENCV_GENERATE_PKGCONFIGON这个参数非常关键。OpenCV 4.x版本默认不再生成opencv4.pc文件但是C开发中我们经常需要用pkg-config来获取编译参数。如果不把这个选项打开后面用pkg-config --cflags --libs opencv4时会提示找不到文件还得手动配置环境变量非常麻烦。BUILD_TESTSOFF和BUILD_PERF_TESTSOFF关闭测试模块和性能测试模块。这两个模块编译非常耗时而且对开发没有直接用处强烈建议关掉。我做过对比开和不开的编译时间能差15到20分钟。WITH_TBBON启用Intel TBB多线程库OpenCV的并行计算框架会使用TBB来加速在多核CPU上效果明显。这个依赖需要额外安装不过Ubuntu仓库里有现成的包。sudo apt install -y libtbb-devWITH_EIGENON启用Eigen矩阵库主要在几何计算和相机标定模块中使用刚才依赖阶段已经安装过了。WITH_V4LON启动V4L2接口支持访问USB摄像头必开。OPENCV_ENABLE_NONFREEON这个参数比较特殊SIFT、SURF这些算法因为专利原因被归为non-free模块默认是编译不了的。如果你需要使用这些特征点算法必须把这个参数打开。配置完成后CMake会在终端输出一份非常详细的配置报告里面包含所有模块的启停状态。我建议你花半分钟扫一遍关键项确认一下GUI: GTK 3.x、Video I/O: FFMPEG、TIFF: YES这些都已启用。如果某个模块显示NO说明对应的系统依赖库没装好此时不要急着编译先把依赖补齐再重新CMake不然编译完了功能还是缺失的。另外提一个细节CMake配置阶段会联网下载一些依赖文件比如ippicv这种Intel预编译的二进制包。如果你的网络状况不好下载可能会很慢甚至失败。如果卡在下载阶段可以多试几次或者手动下载放到指定缓存目录这一步对国内网络环境是一个常见的卡点。4. make编译的体能考验内存管理、swap与时长预判CMake配置完成后输出了一堆编译指令真正的考验才刚开始。你用make命令编译OpenCV考验的不仅是CPU性能还包括内存够不够用。4.1 选择合适的并行编译参数make支持-j参数来指定并行编译的任务数最直接的做法是把它设成CPU核心数make -j$(nproc)这个命令会自动获取你的CPU逻辑核心数然后用这个数量并行编译。比如8核16线程的CPUnproc返回16make就会同时跑16个编译任务。但这里有个非常大的坑并行编译任务开的越多内存占用就越高。OpenCV每个编译任务大约需要1GB内存如果你的是8GB内存的机器开16个并行任务内存很容易被吃满然后触发系统OOM Killer编译进程会被直接杀掉。轻则某个.o文件编译失败重则整个构建系统崩溃你还得重新make。所以我的建议是内存16GB以上可以放心用make -j$(nproc)内存8GB建议用make -j4内存4GB的机器老老实实用make -j2。编译慢一点没问题总比编译到一半崩溃要强。有一个小技巧如果你想确认自己的机器有多少内存可以用free -h查看不要只看CPU核心数就盲目开并行。4.2 swap空间不足的问题如果你的机器内存确实很小比如4GB或8GB而你又想加快编译速度可以临时增加swap空间。这个做法我自己试过效果立竿见影。sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile这样临时创建4GB的swap空间相当于给编译过程增加了4GB的“内存额度”。编译完成后可以留着也可以执行sudo swapoff /swapfile sudo rm /swapfile删掉。但我还是要提醒一句增加swap只是治标不治本如果编译任务并行数太多系统在swap和物理内存之间频繁换页反而会拖慢编译速度。最稳妥的做法就是降低-j参数让每个编译任务稳定吃满内存即可。4.3 编译时间的预判与控制编译时间受CPU性能影响非常大。我在一台i7-9700K8核8线程、16GB内存的机器上make -j8编译OpenCV 4.5.0大概需要25到35分钟编译日志滚动得飞快。在笔记本的i5-8250U上make -j4大概需要50分钟左右风扇会一直高速运转。编译过程中会看到大量的[ XX%] Building CXX object modules/core/CMakeFiles/opencv_core.dir/src/xxx.cpp.o这类日志进度从0%到100%逐步推进。第一次编译到100%时那种感觉还是挺爽的但也不要太心急编译过程中偶尔卡在某个文件上几秒钟是正常现象尤其是一些模板实例化特别多的文件比如core模块里的matrix_decomp.cpp单文件编译时间可能超过一分钟。这里有个经验分享如果你中途发现CMake配置有问题不要等编译完直接CtrlC停掉删掉build目录重新配置就行。OpenCV的构建系统不支持改CMake参数后增量编译改了参数后很多源文件会被强制重新编译时间成本反而更高。4.4 编译完成后的安装编译进度到100%后执行安装命令sudo make installsudomake install正确写法是sudo make install中间有空格。这一步会把头文件复制到/usr/local/include/opencv4把编译好的.so库文件复制到/usr/local/lib同时会把opencv4.pc文件放到/usr/local/lib/pkgconfig目录下。安装过程一般一两分钟就完成了如果终端没有任何报错说明OpenCV已经成功装到系统里了。最后执行一下配置动态库让系统能找到刚刚安装的OpenCV共享库sudo ldconfigldconfig会更新系统的动态链接库缓存告诉系统新装到/usr/local/lib的.so文件可以被程序引用。这一步如果不做运行OpenCV程序时会提示error while loading shared libraries: libopencv_core.so.4.5: cannot open shared object file: No such file or directory。5. 环境配置的最后一公里pkg-config、库路径与OpenCV_DIR编译安装完成不等于环境搭好了还差最后一步让系统能够顺利找到OpenCV的头文件和库文件。这一步配置不好你写C代码时即便#include opencv2/opencv.hpp了编译器也不知道去哪儿找这些头文件。5.1 使用pkg-config验证安装如果你在CMake配置时像我一样开启了OPENCV_GENERATE_PKGCONFIGON那么安装后可以执行pkg-config --modversion opencv4如果返回4.5.0说明pkg-config已经能识别OpenCV了。再执行一下pkg-config --cflags --libs opencv4你会看到输出的编译参数类似这样-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_dnn -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core有了这些参数你后续编译C程序时就不需要手动指定一堆-I和-l参数了直接用pkg-config引用即可。5.2 手动配置PKG_CONFIG_PATH如果你在pkg-config --modversion opencv4时报错提示找不到opencv4.pc文件先确认一下这个文件是否存在ls /usr/local/lib/pkgconfig/opencv4.pc如果文件存在说明pkg-config默认没有搜索这个路径。此时需要手动添加环境变量export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH为了永久生效把这行加到~/.bashrc文件末尾然后source ~/.bashrc。5.3 配置OpenCV_DIR供CMake查找现在很多C项目使用CMake构建CMake通过find_package(OpenCV REQUIRED)来查找OpenCV查找时依赖的就是OpenCV_DIR这个变量它指向包含OpenCVConfig.cmake文件的目录。OpenCV安装后OpenCVConfig.cmake文件位于/usr/local/lib/cmake/opencv4目录下某些版本在/usr/local/share/OpenCV下。在CMakeLists.txt中我们通常这样写find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) add_executable(my_app main.cpp) target_link_libraries(my_app ${OpenCV_LIBS})如果CMake配置时报错找不到OpenCV可以在CMakeLists.txt中显式指定set(OpenCV_DIR /usr/local/lib/cmake/opencv4)或者运行时传参cmake -DOpenCV_DIR/usr/local/lib/cmake/opencv4 ..这里有个经验之谈不要试图手动设置OpenCV_INCLUDE_DIRS和OpenCV_LIBS直接依赖于find_package返回的变量即可。因为find_package(OpenCV)会自动检测头文件和库文件路径包括库文件之间的依赖关系手动指定容易漏掉链接库导致编译时各种undefined reference。6. 编写测试程序验证整个工具链环境搭建完成写个简单的程序验证一下是否运转正常。这一节我会给出一个相对完整的测试流程从单文件编译到CMake编译都覆盖到确保你的环境真的“能跑”。6.1 测试程序读取一张图片并显示先找一张图片放到测试目录里比如test.jpg然后写一个最简单的程序读取这张图片打印图像尺寸信息并用窗口显示出来。#include opencv2/opencv.hpp #include iostream int main(int argc, char** argv) { if (argc 2) { std::cerr Usage: ./display_image image_path std::endl; return -1; } cv::Mat image cv::imread(argv[1], cv::IMREAD_COLOR); if (image.empty()) { std::cerr Failed to load image: argv[1] std::endl; return -1; } std::cout Image loaded. Size: image.cols x image.rows , channels: image.channels() std::endl; cv::imshow(Display Image, image); cv::waitKey(0); cv::destroyAllWindows(); return 0; }这个程序虽然简单但涵盖了OpenCV中最核心的三个操作cv::Mat作为图像数据结构、cv::imread读图、cv::imshow显示窗口。如果这三步都能正常运行说明你的环境基本没有问题。6.2 直接用g编译不依赖任何构建工具直接用g编译最直观g display_image.cpp -o display_image $(pkg-config --cflags --libs opencv4)编译成功后运行./display_image test.jpg如果弹出一个窗口显示了图片控制台打印出图像尺寸说明你的OpenCV环境完全正常。这里有个编译注意事项$(pkg-config --cflags --libs opencv4)一定要放在源文件后面。很多刚学C的朋友习惯写成g $(pkg-config --cflags --libs opencv4) display_image.o -o app这会导致链接阶段找不到OpenCV的函数定义报一堆undefined reference的错误。GCC的链接顺序是从左到右扫描的库必须放在引用它的源文件或目标文件之后。6.3 用CMake写正式的构建脚本单文件用g编译没问题但如果项目文件多了还是老老实实用CMake。下面是一个最简的CMakeLists.txtcmake_minimum_required(VERSION 3.10) project(OpenCVTest) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(OpenCV REQUIRED) add_executable(display_image display_image.cpp) target_link_libraries(display_image ${OpenCV_LIBS})编译方式mkdir -p build cd build cmake .. make ./display_image ../test.jpg如果你的系统中OpenCV_DIR查找没问题这套流程应该是丝滑通过。如果报错找不到OpenCV就在CMakeLists.txt里加上set(OpenCV_DIR /usr/local/lib/cmake/opencv4)或者指定绝对路径再重新配置。6.4 验证扩展模块是否生效前面我们编译了contrib扩展模块现在验证一下SIFT特征点算法能不能用。写一个简单的测试程序#include opencv2/opencv.hpp #include opencv2/xfeatures2d.hpp #include iostream int main() { cv::Mat image cv::Mat::zeros(100, 100, CV_8UC1); auto sift cv::SIFT::create(); std::vectorcv::KeyPoint keypoints; sift-detect(image, keypoints); std::cout SIFT keypoints detected: keypoints.size() std::endl; return 0; }编译运行g test_sift.cpp -o test_sift $(pkg-config --cflags --libs opencv4) ./test_sift如果输出SIFT keypoints detected: 0说明SIFT模块正常加载。如果编译时报错找不到xfeatures2d.hpp说明contrib模块没有编译成功需要回到CMake配置阶段检查OPENCV_EXTRA_MODULES_PATH参数。7. 运行时常见报错与我的排查链路环境搭好、第一个程序跑通之后开发过程中大概率会遇到各种运行时报错。下面这几个是我在OpenCV C开发中经常遇到的也好几个是网上提问频率很高的问题。我把自己在实际排查过程中的思路写出来你遇到了可以照着查。7.1 error while loading shared libraries运行程序时提示error while loading shared libraries: libopencv_core.so.4.5: cannot open shared object file: No such file or directory这个报错的意思是系统在运行程序时找不到OpenCV的动态链接库。原因就是安装后没有执行sudo ldconfig或者OpenCV不是安装在系统默认搜索路径下。排查链路ldconfig -p | grep opencv如果输出为空说明系统缓存里没有OpenCV库。再检查库文件是否存在ls /usr/local/lib/libopencv_core.so*如果文件存在立刻执行sudo ldconfig再运行程序。如果还是报错确认/usr/local/lib是否在/etc/ld.so.conf.d/的搜索路径里必要时在/etc/ld.so.conf.d/下新建一个opencv.conf文件内容是/usr/local/lib然后重新sudo ldconfig。7.2 fatal error: opencv2/opencv.hpp: No such file or directory编译时提示找不到头文件说明编译器不知道OpenCV头文件在哪。排查链路ls /usr/local/include/opencv4/opencv2/opencv.hpp确认头文件存在后检查编译命令里的-I参数。如果用pkg-config重新执行pkg-config --cflags opencv4确认是否输出-I/usr/local/include/opencv4。如果pkg-config里没有极有可能是PKG_CONFIG_PATH没配好参考前面第三节的设置方式。还有一个容易被忽略的细节头文件路径是/usr/local/include/opencv4不是/usr/local/include。这意味着在代码中#include opencv2/opencv.hpp是正确的写法但编译参数必须加上-I/usr/local/include/opencv4。有些教程给你配的是-I/usr/local/include这种情况下编译器只能找到opencv2目录的上级路径还是报找不到头文件。7.3 undefined reference to cv::imread编译到了链接阶段报一堆undefined reference to cv::xxx错误。这个问题的核心是链接阶段少了库文件或者库文件顺序不对。先说顺序在g命令行中库文件参数-lopencv_core等必须放在源文件或.o文件之后。GCC的链接器是从左到右扫描的如果前面的目标文件引用了后面的库中的符号链接器才能找得到。再说库文件$(pkg-config --libs opencv4)输出的是一大串-lopencv_xxx如果输出为空说明pkg-config有问题回到上一步排查。7.4 imshow窗口正常打开但显示全黑或报GTK警告窗口正常弹出来了但显示的内容是黑的或者在终端刷一堆GTK警告。如果是GTK警告参考前面装libcanberra-gtk-module来解决。如果是显示全黑先检查一下cv::imread是不是返回了空图像。这段代码就很有代表性cv::Mat img cv::imread(test.png); if (img.empty()) { std::cerr Failed to load image std::endl; return -1; }为空的原因通常是图像路径不对或者图像格式缺少对应的编解码库。比如你没装libpng-dev那么读取PNG格式时颜色通道可能异常或者读取失败。用file test.png查看图片的真实格式再检查编译时CMake配置报告里PNG: YES/NO。有一个很常见的迷惑现象程序读取一张照片用cv::imshow显示出来窗口显示一切正常但保存成JPEG后用图片查看器打开发现旋转了90度。这是因为现代手机和相机拍摄的照片会带有EXIF方向信息OpenCV默认是不处理EXIF方向的。如果你想自动修正方向需要额外写代码解析EXIF或者用cv::rotate手动旋转。7.5 摄像头打不开或打开后一片黑用VideoCapture打开USB摄像头常见情况有两种cap.open(0)返回false且打不开或者能打开但读出的帧全黑。先看这个排查链路lsusb确认摄像头被系统识别后再看看/dev/video0是否存在ls /dev/video*如果/dev/video0存在但权限不够通常的表现是open失败。把你当前用户加入video组sudo usermod -a -G video $USER然后注销重新登录。如果权限没问题但还是打不开检查驱动支持。很多免驱UVC摄像头在Ubuntu下是即插即用的但也有一些老的摄像头需要专用驱动。这时可以先跑一下CheeseUbuntu自带的摄像头应用来测试摄像头本身是否可用如果Cheese能显示画面说明OpenCV层面的配置有问题重点检查CMake配置报告中的V4L/V4L2: YES/NO。全黑的问题通常出在摄像头没有正确曝光或者自动白平衡还没稳定可以尝试打开后用cap.set(cv::CAP_PROP_FRAME_WIDTH, 640)和cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480)设置一个较低的分辨率有些摄像头在高分辨率下会出现帧率过低导致读帧超时。8. 进阶建议版本管理、卸载清理和日常使用小技巧环境搭好之后长期开发过程中还有一些细节值得注意。这些内容官方文档不会写但实际开发中确实遇到的频率比较高。8.1 管理系统里同时存在的多个OpenCV版本如果你之前用apt装过OpenCV 4.2这次又用源码编译安装了4.5.0系统里会有两套OpenCV并存。apt版本的头文件在/usr/include/opencv4源码装的在/usr/local/include/opencv4库文件分别在/usr/lib/x86_64-linux-gnu/和/usr/local/lib。默认情况下编译器搜索头文件的顺序是/usr/local/include在前/usr/include在后所以源码编译的4.5.0会优先生效。ld链接器搜索库文件的顺序也类似/usr/local/lib优先于/usr/lib。所以大多数场景下你用的就是新编译的4.5.0。如果你想切换回apt版本编译时指定g main.cpp -I/usr/include/opencv4 -L/usr/lib/x86_64-linux-gnu -lopencv_core ...但不建议你这么折腾容易把自己搞懵。最稳妥的做法是确定要源码编译就彻底卸载apt版本。sudo apt remove libopencv-dev libopencv-contrib-dev如果你不确定系统中哪些包与OpenCV相关用dpkg -l | grep opencv查看把相关的全部移除。8.2 卸载源码安装的OpenCV如果需要清理源码编译安装的OpenCV进入之前配置时的build目录执行cd ~/opencv_build/opencv/build sudo make uninstall如果build目录已经不在了也可以手动删除安装的文件sudo rm -rf /usr/local/include/opencv4 sudo rm -rf /usr/local/lib/cmake/opencv4 sudo rm -rf /usr/local/lib/pkgconfig/opencv4.pc sudo rm -f /usr/local/lib/libopencv_* sudo ldconfig注意删除libopencv_*时要注意如果系统里还有其他软件依赖OpenCV删掉后它们也会运行不了。这个命令我建议你在确认无误后再执行。8.3 把OpenCV编译命令封装成脚本如果你需要在多台Ubuntu机器上搭建相同的环境每次手动敲几十条命令很烦。把整个过程写成一个shell脚本是个不错的选择也方便团队内部共享。大致骨架如下#!/bin/bash set -e echo [INFO] Installing dependencies... sudo apt update sudo apt install -y build-essential cmake git pkg-config \ libjpeg-dev libpng-dev libtiff-dev \ libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \ libxvidcore-dev libx264-dev \ libgtk-3-dev libcanberra-gtk-module \ libatlas-base-dev liblapacke-dev libeigen3-dev \ libtbb-dev python3-dev python3-numpy echo [INFO] Downloading OpenCV 4.5.0... mkdir -p ~/opencv_build cd ~/opencv_build git clone -b 4.5.0 --depth 1 https://github.com/opencv/opencv.git git clone -b 4.5.0 --depth 1 https://github.com/opencv/opencv_contrib.git echo [INFO] Configuring... cd opencv mkdir -p build cd build cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH~/opencv_build/opencv_contrib/modules \ -D OPENCV_GENERATE_PKGCONFIGON \ -D BUILD_TESTSOFF \ -D BUILD_PERF_TESTSOFF \ -D WITH_TBBON \ -D WITH_EIGENON \ -D WITH_V4LON \ -D OPENCV_ENABLE_NONFREEON \ .. echo [INFO] Building... make -j$(nproc) echo [INFO] Installing... sudo make install sudo ldconfig echo [INFO] Done. OpenCV 4.5.0 installed.脚本中使用set -e确保任何一步出错就立即停止避免后面的步骤基于错误状态继续执行最后可以省去很多由于“上次没装成功这次接着跑”导致的诡异问题。8.4 用VSCode提升C开发体验环境本身搭好了开发工具也值得花点时间配置。如果你习惯用Visual Studio Code装上C/C扩展插件后在c_cpp_properties.json里指定{ configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /usr/local/include/opencv4 ], defines: [], compilerPath: /usr/bin/g, cStandard: c11, cppStandard: c14, intelliSenseMode: linux-gcc-x64 } ], version: 4 }这样VSCode的智能提示就能正确识别#include opencv2/opencv.hpp代码补全和错误检查都可以正常使用了。这个配置我每次搭完环境都会顺手配上因为如果没有includePathVSCode里所有OpenCV相关代码都会标红波浪线写代码的时候非常干扰注意力。另外推荐在VSCode里配置一下CMake Tools插件配合上面给的CMakeLists.txt模板按F7就能直接编译F5调试比在终端里手工敲命令高效很多。最后再说一个小技巧OpenCV 4.5.0在Release模式下编译的程序二进制体积会比较大这是正常的因为cv::Mat这类模板类在很多地方会实例化出大量代码。如果最终部署时对体积敏感可以在CMake中加入-DCMAKE_BUILD_TYPEMinSizeRel或者使用strip命令裁剪符号表能显著减小可执行文件体积。不过对于学习和开发阶段这个优化可以等真正做产品时再考虑。
返回列表