ARTICLE DETAIL

资讯详情

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

004、WindowsLinux开发环境搭建:Anaconda、pip与源码编译

004、WindowsLinux开发环境搭建:Anaconda、pip与源码编译 004、WindowsLinux开发环境搭建Anaconda、pip与源码编译写这篇笔记的时候我电脑上还挂着三个终端窗口一个在跑Windows下的OpenCV源码编译另一个刚把Ubuntu 20.04的conda环境装到一半。为什么同时折腾两套因为昨晚有读者私信说按网上一篇教程在Linux下用pip装完OpenCVimport的时候直接段错误我一看他发来的命令pip install opencv-python干净利落但问题出在他用的是ARM开发板官方wheel根本就不是给这个平台准备的pip倒是给装了一跑就崩。这行命令本身没错错在环境不匹配。所以今天这篇我不打算把Anaconda、pip、源码编译并列起来讲成三种方案它们从来就不是同一层级的东西——conda管环境pip管包源码编译是最后的兜底手段也是你真正理解OpenCV内部结构的唯一路径。你得清楚什么时候用哪个以及为什么。先说你大概率会遇到的第一个坑。Windows下你兴冲冲装上Anaconda然后pip install opencv-python一切顺利import cv2也成功了但一调用cv2.VideoCapture(0)摄像头打不开。你去查发现OpenCV官方预编译包用的是MSVC编译的而你系统里的Python可能是MinGW或者其他编译器链出来的运行时库冲突接口对不上。这种问题在conda环境里特别容易发生因为conda的Python和系统Python可能不是同一套东西。解决的办法有两种一是用conda自带的opencv包而不是pip的conda install opencv它会自动帮你匹配编译器和运行时二是强迫自己统一使用某个编译链别混着来。我个人的习惯是既然用了Anaconda就彻底用conda管理环境pip只在conda里装一些conda没有的纯Python包。哪怕是pip也要在conda激活的环境里执行别用系统Python的pip去装东西进conda那样会污染环境。再说Linux下更微妙的一件事。很多教程让你pip install opencv-python-headless说这个版本不带GUI依赖适合服务器。这话没错但“headless”只是不依赖GTK/Qt这些图形库它仍然是从源码编译好的二进制wheel。问题来了如果你系统的libGL.so.1版本不兼容import cv2会直接报错说找不到libGL.so.1或者更恶心的找到了但版本不对。我遇到过一台干净的CentOS 7装完headless版本后import时提示libGL.so.1: cannot open shared object file因为系统里连mesa-libGL都没装。这时候你当然可以yum install mesa-libGL但更根本的问题是你根本不知道这个wheel需要哪些系统库。官方wheel是在很多Linux发行版上做了兼容性测试的但没法覆盖所有环境。所以如果你是CentOS/RHEL这类较老的发行版我建议要么用conda装要么就走源码编译不然你会在系统依赖的泥潭里折腾半天。源码编译这块值得认真写。Windows下编译OpenCV你得先装CMake、Visual Studio2019或2022社区版够用、Python的开发头文件。这里有个容易错的地方CMake配置时如果你不指定Python版本它会自己找一个有时候找到的不是你conda环境里的那个导致编译出来的cv2模块装进你的环境后import报错说找不到Python.h或者链接库不匹配。我教你一个办法在CMake GUI里明确把PYTHON_EXECUTABLE指向你conda环境的python.exe然后PYTHON_INCLUDE_DIR指向这个环境下的include目录PYTHON_LIBRARY指向对应的pythonXX.lib。这三项必须指向同一个Python解释器别让CMake自动探测不然大概率会错。另外我记得第一次编译时忘记勾选BUILD_opencv_world结果生成了几十个DLL配置环境变量时还得一个个加烦死了。你勾上这个选项所有模块会合成一个opencv_world.dll省心很多。还有个坑如果你用的VS版本和CMake生成的版本不一致编译到一半会蹦出各种莫名奇妙的错误干脆重来。这些坑我都踩过说多了都是泪。Linux下源码编译相对平滑但也不是没坑。在Ubuntu上你需要先装一堆依赖libgtk2.0-dev、libavcodec-dev、libavformat-dev、libswscale-dev、libv4l-dev、libxvidcore-dev、libx264-dev如果你要GPU加速还得装CUDA和cuDNN。这里最奇葩的是如果你不装GTK相关包OpenCV只能编译出不带GUI支持的版本cv2.imshow会报错。你可能会说那就装呗。问题在于这些dev包的版本和你系统里的运行时库版本如果对不上或者你换了软件源会产生依赖冲突。有一次我在Ubuntu 22.04上编译因为之前装了一个第三方源的libgtk-3-dev导致整个依赖树乱了最后把OpenCV源码里关于GTK的检测全部绕过用-DWITH_GTKOFF -DWITH_QTON强行转向Qt才算编译过。不同发行版甚至同一个发行版的不同版本依赖名称和版本都不同网上教程没法全覆盖。我的经验是编译前先执行sudo apt build-dep opencv这条命令会拉取所有OpenCV所需的构建依赖如果是Ubuntu/Debian系基本上一次搞定。其他发行版你得自己用包管理器解决。说到pip和conda的深层区别值得用实战案例讲透。conda不仅是包管理器它还能管理Python解释器版本、非Python库比如HDF5、MKL、CUDA runtime。pip只能管Python包而且很多包是预编译的二进制wheel这些wheel依赖系统库可移植性差。比如你pip install opencv-python它会捆绑一个特定版本的FFmpeg和H.264编码器但你无法控制这些捆绑库的版本。而conda的opencv包你可以用conda install opencv -c conda-forge它会自动帮你解决依赖比如libgcc、libstdc、numpy等这些依赖是conda管理的不会污染系统。这就是为什么在服务器上我部署目标检测模型时几乎总是用conda创建环境然后用conda install opencv除非这个包在conda-forge里没有我才会用pip。但要注意conda和pip混用有一个著名的问题conda装的是将pip视为辅助pip装的东西不会参与conda的依赖解析。所以你应该在创建环境后先用conda安装所有能装的大件比如numpy、matplotlib、opencv然后剩下的纯Python库用pip装而且不要pip install -U去升级一个conda已经管理的包否则依赖关系会悄悄坏掉你根本察觉不到。再提供一个我常用的环境创建命令模板conda create -n yolo python3.8然后激活接着conda install numpy scipy matplotlib opencv pillow最后pip install torch torchvision torchaudio——如果不开GPUCPU版直接用pip的官方index就行。这里有个小细节为什么Python版本指定3.8而不是最新的3.11因为很多深度学习框架的预编译wheel在较新Python上可能还没跟上或者你的CUDA版本不兼容。别为了求新Python版本太新坑的是你自己。我见过一个同事装Python 3.12结果一堆库没有对应wheel被迫每装一个包就编译一次那叫一个惨。一般来说项目文档里建议什么Python版本你就用什么。如果没有文档就用当前最稳定的3.10或3.11至于3.12多等半年再说。把源码编译的CMAKE参数再说细一点。在Linux下常用命令是cmake -D CMAKE_BUILD_TYPERELEASE \ -D CMAKE_INSTALL_PREFIX/usr/local \ -D OPENCV_EXTRA_MODULES_PATH../../opencv_contrib/modules \ -D PYTHON_EXECUTABLE$(which python) \ -D BUILD_opencv_python3ON \ -D BUILD_opencv_python2OFF \ -D WITH_V4LON \ -D WITH_LIBV4LON \ -D WITH_GTKON \ -D WITH_OPENGLON你注意那个OPENCV_EXTRA_MODULES_PATH指向的是contrib模块里面有SIFT、SURF这些专利算法默认不包含。如果你要做特征点匹配这个必须加。不加的话你到时候用cv2.SIFT_create()直接给你报错说不是OpenCV的模块。这事儿我碰到过不止一次很多人跑来问为什么SIFT不能用都是编译时没带contrib。还有那个BUILD_opencv_python3ON必须显式打开否则默认可能只编译C库不生成cv2的Python接口。不要相信默认值。我每次编译都要检查CMake输出日志看到Python 3: YES和Python 3 (Interpreter): /path/to/python才放心。这里还有个小技巧编译前先make -j$(nproc)但如果你内存不大比如8G以下的机器-j4就够了不然直接OOM。在Windows上编译OpenCV的步骤其实类似。用CMake GUI配置源代码目录选OpenCV源码构建目录新建一个build文件夹。然后点Configure选Visual Studio对应的版本平台选x64。等第一次配置完成后把OPENCV_ENABLE_NONFREE这个选项打开因为contrib里的很多算法被标为non-free默认是关的。如果你用的是contrib目录记得把OPENCV_EXTRA_MODULES_PATH指向它。再次Configure然后Generate再用Visual Studio打开生成的.sln选择Release模式右键“ALL_BUILD”生成。这个过程很长你可以去泡杯茶。生成完了接下来是INSTALL项目生成然后到build/install目录下把bin目录加入系统PATH。最后还要把生成的cv2.pyd文件复制到你的Python环境的Lib/site-packages里或者用CMake安装目录中的Python绑定路径。这个细节网上很多教程没说清总以为编译完就能用。实际上你得手动复制cv2.pyd或者设置PYTHONPATH否则import cv2时找不到模块。每次编译版本升级都要记得覆盖旧的pyd文件不然你用的还是老版本。关于环境变量多说一句。Windows下如果你同时装了系统Python和AnacondaPATH里谁在前你命令行敲python时就是谁。很多人装完Anaconda又在PATH里把系统Python放在前面结果进入conda环境后pip装的包跑到系统Python去了然后import时报错说模块不存在。你用where python看一下十有八九是路径不对。正确做法是Anaconda的路径放前面激活环境后which python应该指向你conda环境内的python。Linux下也一样用which python确认一下。如果不对先conda deactivate再激活或者手动修改PATH。这个问题我在给人排查时发现频率最高几乎占了所有安装问题的一半。再谈一个容易被忽略但实打实影响性能的环节OpenCV的构建类型。RELEASE和DEBUG两种。RELEASE会启用编译器优化比如-O3运行速度明显快。DEBUG模式适合调试时用因为会包含调试符号但速度慢。如果你只是做目标检测的开发和部署直接选RELEASE。有的人图方便直接在Windows上从源码编译了一个DEBUG版本结果跑推理时比预编译包慢三倍还找不准原因。这事儿我也干过当时我还以为是编译器问题后来想起CMake里那个CMAKE_BUILD_TYPE才意识到是DEBUG。在Windows上CMake如果没指定默认生成的是Debug配置你得在Visual Studio里手动把解决方案配置改成Release。或者用CMake命令行加-DCMAKE_BUILD_TYPERelease但在VS生成器中这个设置不生效你得在VS工具栏那里切换。别笑这种坑最耽误时间。还有一个Python环境里常见的冲突OpenCV的cv2和numpy版本不匹配。老版本的OpenCV用了一些numpy的私有接口新numpy改了接口后老cv2就报错。比如cannot import name multiarray from numpy.core。这个错误我在升级numpy到1.24后频繁遇到因为numpy移除了multiarray的公开路径。解决方法是降低numpy版本或者更推荐升级OpenCV到4.6以上。所以每当你安装新包导致numpy自动升级时一定要留意cv2是否还能用。我通常会在环境里固定numpy版本写进requirements.txt里比如numpy1.23.5防止别人重复部署时踩坑。写到这里我回想自己当年从Windows跳到Linux又从预编译包跳到源码编译走了很多弯路。有段时间我特别迷信“一键安装”结果在AI应用里环境问题往往比模型问题更致命。后来我整理出一套自己的流程先确认目标平台查官方文档支持哪些预编译包能用conda就用conda因为conda的二进制兼容性好conda没有的用pip装但装完立即验证import如果平台架构特殊比如ARM、树莓派直接源码编译不要幻想能找到现成的wheel。至于源码编译其实没有想象中那么可怕它只是把OpenCV的C源码编译成库然后生成Python接口。你只要记住几个关键参数比如Python路径、contrib模块路径、GUI框架选择其他就交给CMake。编译失败是常事但大多数错误都是同一个原因环境依赖不全或者路径配置不对。你耐心看日志一行行分析总能解决。最后我个人的一点经验性建议供各位参考不要在环境搭好之后觉得自己一劳永逸。买个新电脑、重装系统、更新Python、升级numpy都可能让原本稳定运行的OpenCV瞬间崩掉。养成写环境配置文档的习惯把自己当前环境的版本、安装命令、踩过的坑记录下来。以后换机器或者帮同事排错你会感谢当年的自己。至于本篇文章题目里说的“Anaconda、pip与源码编译”我建议你按这个优先级选如果只是学习或快速验证用Anaconda配合conda安装如果在服务器上且不需要GUI用conda-forge的opencv-headless如果是特殊平台或需要contrib模块就源码编译。不要一上来就编译浪费时间也不要永远依赖pip迟早要出问题。环境问题是个良心活今天偷的懒后面都会变成加班还回来。咱做工程师的还是踏实点好。
返回列表