1. 这个专栏到底在讲什么
OpenCV这四个字母,但凡碰过计算机视觉的人都不会陌生。但说实话,我见过太多人打开一个OpenCV专栏,翻了两篇就开始犯迷糊——有的文章上来就贴一段C++代码,连环境怎么装都不提;有的通篇在讲Mat类的底层内存布局,新手看完连一张图片都读不进来;还有的今天讲Python调库,明天突然跳到C++的指针操作,中间没有任何过渡。所以我决定在正式开更之前,先把整个专栏的定位、内容边界、学习路径和实操环境交代清楚,这就是这篇“观看须知”的由来。
这个专栏的核心目标很明确:帮你把OpenCV从“听说过”变成“用得顺手”。不管你是做图像处理、目标检测、视频分析,还是只想批量给自己的照片加水印、做拼接、调色调,OpenCV都是绕不开的基础工具。它不是一个高不可攀的学术框架,而是一套实打实的工程库,里面有超过2500个优化过的算法,覆盖从基础的像素读写到复杂的特征匹配、相机标定、光流追踪等几乎所有经典视觉任务。
适合谁来读?三类人。第一类是有一定编程基础但没接触过视觉库的开发者,比如你写过Python或者C++,但不知道图像在计算机里到底长什么样;第二类是用过OpenCV但只会复制粘贴代码的人,能跑通但说不清原理,换个场景就不知道怎么改参数;第三类是做深度学习但发现绕不开传统图像预处理的人,比如做目标检测时需要做图像增强、裁剪、色彩空间转换,这些活儿OpenCV干得比深度学习框架利索得多。
这个专栏不会做的事也要说清楚:不讲深度学习模型的训练和调参,不讲CUDA加速的底层优化,不讲OpenCV源码级的编译原理。这些内容各有专门的专栏去覆盖,我这里聚焦的是OpenCV本身的API使用、参数含义、常见组合和工程实践。你可以把它理解成一本“带注释的实战手册”,而不是一本“算法理论教材”。
专栏的更新节奏大致是每周两到三篇,每篇围绕一个具体的功能模块展开,从环境搭建、核心概念、API详解到完整可运行的代码示例,最后附上我实际踩过的坑和排查思路。代码统一用Python和C++双版本对照,Python为主,C++作为补充,因为Python的入门门槛低、调试方便,而C++在工程部署时更常见。你不需要两个都精通,选一个跟着走就行,另一个当作参考。
提示:如果你是完全零基础,连Python的列表和字典都不太熟,建议先花两三天补一下Python基础语法,不然看图像处理代码会比较吃力。不需要学到面向对象和装饰器,会写循环、条件判断、函数调用就够了。
2. 学习OpenCV之前必须搞清楚的几件事
2.1 图像在计算机里到底是什么
很多人学OpenCV卡在第一步,不是因为代码难,而是因为脑子里没有建立起“图像就是矩阵”这个认知。你打开一张手机拍的照片,看到的是风景、人物、颜色,但计算机看到的只是一个数字表格。以最常见的RGB彩色图为例,一张1920×1080的照片,在计算机内存里就是一个1080行、1920列、3个通道的三维数组。每个通道对应红、绿、蓝三个颜色的强度值,范围是0到255。0代表这个通道完全没有贡献,255代表满值。
为什么是0到255?因为一个字节是8位,能表示2的8次方也就是256个值。这个设计是历史沿袭下来的,早期显示硬件和图像格式都基于8位通道,后来虽然出现了16位、32位浮点的图像格式,但8位仍然是日常使用最广泛的。OpenCV默认读取的彩色图像就是8位三通道,顺序是BGR而不是RGB。这个顺序差异坑过无数人——你用OpenCV读一张图,然后用matplotlib显示,会发现颜色偏蓝,就是因为matplotlib按RGB解释,而OpenCV给的是BGR。
灰度图则是单通道的二维数组,每个像素只有一个值,代表亮度。从彩色转灰度有一个经典的加权公式:Gray = 0.299×R + 0.587×G + 0.114×B。为什么绿色权重最高?因为人眼对绿光最敏感,对蓝光最不敏感。这个公式不是随便定的,它来自人眼视锥细胞的响应特性。OpenCV的cvtColor函数用的就是这个加权方式,你不需要自己手算,但知道背后的逻辑有助于理解为什么不同转换方法得到的灰度图会有细微差异。
2.2 环境搭建的三种方案与选择逻辑
OpenCV的环境搭建有三种主流方式,各有适用场景,我逐一分析。
第一种是pip安装,命令就一行:pip install opencv-python。这是最省事的方式,适合快速上手和做原型验证。但要注意,opencv-python这个包只包含主模块,如果你需要SIFT、SURF这类专利算法(SIFT专利已过期,现在包含在主模块里了),或者需要contrib扩展模块里的额外功能,得装opencv-contrib-python。另外还有opencv-python-headless版本,去掉了GUI相关的功能,适合部署在服务器上没有显示器的场景。我个人的习惯是开发阶段装完整版,部署时换成headless版减小体积。
第二种是conda安装,命令是conda install -c conda-forge opencv。conda的好处是会自动处理底层依赖,比如FFmpeg、libjpeg这些库,在Windows上尤其省心。如果你用Anaconda做数据科学的工作,conda安装能和numpy、matplotlib等库的版本更好地协调。但conda的OpenCV版本更新往往比pip慢一些,新特性可能要等一段时间才能用上。
第三种是源码编译,这是最折腾但也最灵活的方式。你需要先装CMake、编译器、各种图像格式的开发库,然后下载OpenCV源码和contrib源码,用CMake生成构建文件,再编译安装。整个过程在性能好的机器上也要半小时到一小时。什么时候需要源码编译?当你需要开启特定的优化选项(比如CUDA加速、OpenCL支持)、需要裁剪掉不需要的模块来减小体积、或者需要在特定平台上做交叉编译时。普通学习者不建议走这条路,除非你确实遇到了pip和conda解决不了的问题。
注意:不管你用哪种方式,装完之后一定要验证。运行
import cv2; print(cv2.__version__)看版本号是否正常输出,再运行img = cv2.imread('test.jpg'); print(img.shape)看能否正确读取一张图片。很多人装完不验证,等到写代码时才发现读图返回None,回头排查环境问题更浪费时间。
2.3 Python还是C++:选择依据与对照策略
这个问题我被问过无数次。直接给结论:学习阶段用Python,工程部署阶段看情况。
Python的优势在于开发效率。同样的功能,Python代码量通常是C++的三分之一到五分之一,而且不需要管理内存、不需要编译、调试方便。OpenCV的Python接口底层就是C++实现,性能差距主要在Python的解释器开销上,对于大多数图像处理任务,这个开销可以接受。比如读一张图、做一次高斯模糊、保存结果,Python和C++的耗时差异在毫秒级别,人眼根本感觉不到。
C++的优势在于极致性能和部署灵活性。当你需要处理高帧率视频流(比如每秒几百帧的工业检测)、需要在嵌入式设备上运行、或者需要和已有的C++系统集成时,C++是更好的选择。另外,某些OpenCV的高级功能在Python接口中可能没有暴露出来,或者参数传递不如C++灵活。
我的建议是:专栏中的代码以Python为主,每篇涉及核心API时附上C++的对照写法。你不需要同时学两套,先把Python用熟,理解每个函数的输入输出和参数含义。等到需要做C++部署时,你会发现API的名字和参数逻辑几乎一样,只是语法形式不同,迁移成本很低。
3. 专栏内容模块与学习路径规划
3.1 基础模块:从读写图片到像素操作
基础模块是整个专栏的地基,覆盖OpenCV最常用的核心功能。这部分我会用大约六到八篇的篇幅讲透。
第一篇讲图像的读写与显示。cv2.imread的第二个参数决定了读取方式:IMREAD_COLOR读彩色图(默认),IMREAD_GRAYSCALE读灰度图,IMREAD_UNCHANGED保留alpha通道。很多人不知道的是,imread在读取失败时不会报错,而是返回None,如果你不检查就直接传给后续函数,会得到一个莫名其妙的错误。所以我的习惯是每次读图后加一行assert img is not None,把问题扼杀在源头。
第二篇讲像素访问与ROI操作。OpenCV的Python接口里,图像就是一个numpy数组,你可以用切片语法直接操作像素区域。比如img[100:200, 300:400]就是取第100到199行、第300到399列的区域。这个特性极其方便,做图像裁剪、区域替换、局部调色都靠它。但要注意,切片得到的是视图而不是副本,修改切片会影响原图,需要副本时要用.copy()。
第三篇讲色彩空间转换。除了BGR和灰度,OpenCV还支持HSV、LAB、YCrCb等色彩空间。HSV在颜色分割时特别有用,因为H通道直接对应色调,不受光照变化影响。比如你要提取画面中的红色物体,在RGB空间里红色分布在三个通道的高值区域,很难用一个简单的范围描述;但在HSV空间里,红色集中在H通道的0到10和170到180两个区间,用cv2.inRange就能轻松分割出来。
第四篇讲图像的几何变换。缩放用cv2.resize,旋转用cv2.getRotationMatrix2D配合cv2.warpAffine,透视变换用cv2.getPerspectiveTransform配合cv2.warpPerspective。这里的关键是理解变换矩阵的含义。以旋转为例,旋转矩阵是一个2×3的矩阵,前两列是旋转部分,第三列是平移部分。getRotationMatrix2D帮你根据旋转中心和角度自动生成这个矩阵,你不需要手算三角函数。
3.2 进阶模块:滤波、边缘检测与轮廓分析
进阶模块开始涉及真正的图像处理算法,这部分是OpenCV的核心价值所在。
滤波部分我会重点讲高斯滤波、中值滤波和双边滤波。高斯滤波适合去除高斯噪声,中值滤波对椒盐噪声效果最好,双边滤波能在保边的同时去噪但速度较慢。选择哪种滤波取决于你的噪声类型和对边缘保留的要求。参数方面,高斯滤波的核大小必须是奇数,标准差越大模糊效果越强。我通常会先用cv2.GaussianBlur试几个不同的核大小,观察效果后再定。
边缘检测部分讲Sobel、Laplacian和Canny。Canny是最常用的,因为它做了非极大值抑制和双阈值连接,得到的边缘细且连续。Canny的两个阈值很关键:高阈值用于确定强边缘,低阈值用于连接弱边缘。经验法则是高阈值取低阈值的两到三倍,具体数值要根据图像的对比度调整。我一般会先用cv2.Canny的默认值跑一遍,然后根据结果微调。
轮廓分析部分讲cv2.findContours和cv2.drawContours。findContours的返回值在不同OpenCV版本中有差异,3.x返回三个值(图像、轮廓、层级),4.x返回两个值(轮廓、层级)。这个变化坑过很多人,网上很多老代码在4.x上跑会报错。轮廓的层级关系用cv2.RETR_TREE获取,可以分析轮廓之间的包含关系,做形状嵌套分析时很有用。
3.3 实战模块:从人脸检测到视频分析
实战模块把前面学到的知识串起来,做几个完整的项目。
人脸检测用Haar级联分类器,虽然现在深度学习方案更流行,但Haar级联胜在轻量、快速、不需要GPU。cv2.CascadeClassifier加载预训练的XML文件,然后调用detectMultiScale检测。关键参数是scaleFactor和minNeighbors:前者控制每次图像缩放的比例,越小检测越慢但越不容易漏;后者控制检测框的保留阈值,越大误检越少但可能漏掉侧脸。我一般设scaleFactor=1.1、minNeighbors=5作为起点。
视频分析部分讲视频的读取、处理和保存。cv2.VideoCapture可以读摄像头也可以读视频文件,用cap.read()逐帧获取。处理完的帧用cv2.VideoWriter写入新视频,注意要指定正确的编码器和帧率,否则保存的视频可能无法播放。编码器用cv2.VideoWriter_fourcc(*'mp4v')在大多数平台上都能工作。
4. 实操环境配置与第一个可运行示例
4.1 从零搭建一个干净的OpenCV开发环境
我强烈建议用虚拟环境来管理OpenCV项目,避免不同项目之间的依赖冲突。以下是基于venv的完整步骤,适用于Windows、macOS和Linux。
第一步,创建项目目录并进入:
mkdir opencv-lab && cd opencv-lab第二步,创建虚拟环境:
python -m venv venv第三步,激活虚拟环境。Windows下用venv\Scripts\activate,macOS和Linux下用source venv/bin/activate。激活后命令行提示符前面会出现(venv)标识。
第四步,安装核心依赖:
pip install opencv-python opencv-contrib-python numpy matplotlib这里同时装了主模块和contrib模块,numpy是OpenCV的底层依赖会自动安装,matplotlib用于在notebook中显示图像。
第五步,验证安装:
import cv2 import numpy as np print(f"OpenCV版本: {cv2.__version__}") print(f"NumPy版本: {np.__version__}") # 创建一个纯色图像测试基本功能 test_img = np.zeros((100, 100, 3), dtype=np.uint8) test_img[:] = (0, 255, 0) # BGR绿色 cv2.imwrite('test_green.jpg', test_img) loaded = cv2.imread('test_green.jpg') print(f"图像形状: {loaded.shape}") print(f"像素值(BGR): {loaded[50, 50]}")如果输出显示版本号正常、图像形状为(100, 100, 3)、像素值为[0, 255, 0],说明环境完全就绪。
提示:如果你在Linux服务器上没有图形界面,把
opencv-python换成opencv-python-headless,避免安装GUI相关的系统库。另外,如果pip安装速度慢,可以临时指定国内镜像源加速,这是通用的Python包管理技巧,和OpenCV本身无关。
4.2 第一个完整示例:图像读取、处理与保存
这个示例把读取、灰度转换、边缘检测、保存四个步骤串起来,让你对OpenCV的工作流有一个完整的感知。
import cv2 import numpy as np # 1. 读取图像 img = cv2.imread('input.jpg') if img is None: raise FileNotFoundError("图像读取失败,请检查路径是否正确") print(f"原始图像尺寸: {img.shape}") # (高, 宽, 通道数) # 2. 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 3. 高斯滤波去噪 blurred = cv2.GaussianBlur(gray, (5, 5), 1.5) # 4. Canny边缘检测 edges = cv2.Canny(blurred, 50, 150) # 5. 保存结果 cv2.imwrite('edges_output.jpg', edges) # 6. 并排显示(需要GUI环境) combined = np.hstack([gray, edges]) cv2.imshow('Gray vs Edges', combined) cv2.waitKey(0) cv2.destroyAllWindows()这段代码有几个细节值得展开。GaussianBlur的核大小(5, 5)表示用5×5的邻域做加权平均,标准差1.5控制权重的衰减速度。标准差越大,离中心像素远的点权重越高,模糊效果越明显。Canny的50和150分别是低阈值和高阈值,低于50的梯度被丢弃,高于150的被认为是强边缘,介于两者之间的只有和强边缘相连时才保留。
为什么先滤波再边缘检测?因为Canny本身对噪声敏感,图像中的噪点会产生虚假边缘。高斯滤波平滑了噪声,让真正的边缘更突出。但滤波也会让边缘变模糊,所以核大小和标准差要适中,太大了边缘会糊成一片,太小了噪声去不干净。我一般从(5, 5)和1.5开始试,根据结果调整。
4.3 参数调整的实操记录与效果对比
我拿一张建筑照片做了几组对比实验,记录如下。
第一组:不滤波直接Canny,阈值50和150。结果:边缘很多但很碎,墙面纹理和窗户边框混在一起,噪点明显。
第二组:高斯滤波(3, 3)标准差1.0,再Canny。结果:噪点减少,但边缘仍然偏碎,细小的纹理还在。
第三组:高斯滤波(5, 5)标准差1.5,再Canny。结果:边缘变得干净,主要结构清晰,细节纹理被平滑掉,整体效果最好。
第四组:高斯滤波(7, 7)标准差2.0,再Canny。结果:边缘开始断裂,窗户的直角变得圆滑,过度平滑导致部分边缘丢失。
第五组:中值滤波(5)替代高斯,再Canny。结果:噪点去除效果不错,但边缘比高斯滤波的稍微粗一些,因为中值滤波不产生新的灰度值,只是取邻域中位数。
最终我选了第三组的参数作为默认配置。这个实验说明一个道理:滤波参数没有绝对的最优值,要根据图像内容和任务目标来调。如果你做的是精密测量,需要保留更多细节,就用小核;如果你做的是粗略的形状识别,大核更合适。
5. 常见问题与排查技巧实录
5.1 图像读取返回None的六种原因
这是新手遇到最多的报错,没有之一。cv2.imread返回None的原因我整理了六种,按出现频率排序。
第一种,路径写错了。这是最常见的,尤其是Windows下反斜杠和正斜杠混用的问题。Python字符串里反斜杠是转义字符,'C:\Users\test.jpg'中的\t会被解释成制表符。解决办法是用原始字符串r'C:\Users\test.jpg'或者统一用正斜杠'C:/Users/test.jpg'。
第二种,文件不存在。路径对了但文件名拼错了,或者文件被移动了。用os.path.exists先检查一下。
第三种,文件格式不支持。OpenCV支持常见的JPEG、PNG、BMP、TIFF等,但某些特殊格式比如RAW、PSD可能读不了。用cv2.haveImageReader可以检查某个文件是否能被读取。
第四种,文件损坏。下载不完整或者传输过程中损坏的图片,OpenCV读不了。用其他看图软件打开试试,如果也打不开就是文件本身的问题。
第五种,权限问题。Linux下如果文件没有读权限,OpenCV会静默返回None。用ls -l检查权限,必要时用chmod修改。
第六种,路径中有中文或特殊字符。某些OpenCV版本对非ASCII路径支持不好,尤其是Windows下。解决办法是把文件移到纯英文路径下,或者用cv2.imdecode配合np.fromfile读取。
注意:排查时不要靠猜,用
print(os.path.abspath(path))打印绝对路径,用print(os.path.exists(path))确认文件存在,用print(os.path.getsize(path))确认文件大小不为零。三步下来基本能定位问题。
5.2 颜色不对:BGR与RGB的世纪混淆
这个问题我在前面提过,但值得单独展开,因为它太常见了。OpenCV读图默认是BGR顺序,而大多数其他库(PIL、matplotlib、深度学习框架)用RGB。当你用OpenCV读图、用matplotlib显示时,红色和蓝色会对调。
解决办法有三种。第一种,读图后手动转换:img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)。第二种,用切片反转通道:img_rgb = img[:, :, ::-1],效果一样但写法更简洁。第三种,如果你只是用matplotlib显示,可以在显示前转换,不影响后续OpenCV处理。
我个人的习惯是:在OpenCV的处理流程中始终保持BGR,只在需要和其他库交互时才转换。这样避免在流程中间反复转换导致混乱。另外,保存图像时OpenCV也按BGR写入,所以如果你用OpenCV读、OpenCV写,颜色不会出问题;只有跨库操作时才需要注意。
5.3 视频写入失败或文件无法播放
cv2.VideoWriter的坑比imread还多。最常见的问题是保存的视频文件大小为0或者无法播放。
原因一,编码器不支持。cv2.VideoWriter_fourcc(*'mp4v')在大多数平台可用,但某些Linux发行版可能缺少对应的编码库。可以尝试'XVID'配合.avi后缀,或者'MJPG'。如果都不行,检查系统是否安装了FFmpeg。
原因二,帧尺寸不匹配。VideoWriter初始化时指定的帧尺寸必须和实际写入的帧尺寸完全一致,否则写入会静默失败。比如你用摄像头读到的帧是640×480,但初始化时写了1280×720,写入的帧会被丢弃。解决办法是用cap.get(cv2.CAP_PROP_FRAME_WIDTH)和cap.get(cv2.CAP_PROP_FRAME_HEIGHT)动态获取实际尺寸。
原因三,帧率设置不合理。帧率设得太高或太低都可能导致播放问题。一般设25或30,和源视频保持一致。如果源视频帧率是29.97,你设30,保存的视频时长会有微小偏差,但通常可以接受。
原因四,忘记释放。VideoWriter用完必须调用release(),否则文件头没有正确写入,文件无法播放。这个和文件写入的缓冲区刷新是一个道理。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| imread返回None | 路径错误 | 打印绝对路径检查 | 用原始字符串或正斜杠 |
| 颜色偏蓝 | BGR/RGB混淆 | 检查显示库的通道顺序 | cvtColor转换或切片反转 |
| 视频文件0字节 | 编码器不支持 | 尝试不同fourcc | 换XVID或MJPG |
| 视频无法播放 | 未调用release | 检查代码是否有release | 写入完成后必须release |
| Canny边缘太碎 | 噪声未滤除 | 先做高斯滤波 | 调整核大小和标准差 |
| 轮廓检测报错 | 版本差异 | 打印findContours返回值个数 | 4.x用两个变量接收 |
| 内存占用持续增长 | 未释放资源 | 检查循环中是否重复创建对象 | 复用对象或手动释放 |
| 处理速度慢 | 分辨率过高 | 打印图像尺寸 | 先缩放再处理 |
6. 效率提升与工程化建议
6.1 向量化操作替代循环
OpenCV配合NumPy的最大优势是向量化运算。很多新手会写双重循环遍历每个像素,这在Python里慢得令人发指。比如要把图像中所有大于200的像素设为255,用循环要几秒钟,用NumPy一行搞定:img[img > 200] = 255。
再比如计算图像的平均亮度,用np.mean(gray)比循环累加快几百倍。OpenCV的很多函数内部已经做了向量化优化,你只需要把数据准备好传进去就行。我见过有人用Python循环做卷积运算,一张1080p的图跑了半分钟,换成cv2.filter2D瞬间完成。
6.2 合理使用ROI减少计算量
如果你只关心图像中的某个区域,不要对整张图做处理再裁剪,而是先裁剪再处理。比如做人脸检测时,如果你已经知道人脸大致在画面中央,可以只对中央区域做检测,计算量能减少一半以上。
ROI的获取用切片:roi = img[y1:y2, x1:x2]。处理完的ROI可以直接赋值回原图:img[y1:y2, x1:x2] = processed_roi。这个操作是原地修改,不产生新的大数组,内存效率很高。
6.3 图像金字塔与多尺度处理
当图像尺寸很大时,直接处理会很慢。一个常用的策略是先缩小图像做粗定位,再在原图上做精细处理。比如模板匹配,先用0.5倍缩放找到大致位置,再在原图的对应区域做精确匹配。OpenCV的cv2.pyrDown和cv2.pyrUp提供了高斯金字塔的上下采样,cv2.resize则更灵活。
多尺度处理在人脸检测中很常见。detectMultiScale内部就是通过不断缩小图像来检测不同大小的人脸。理解了这个机制,你就能明白为什么scaleFactor越小检测越慢——因为缩放的次数更多了。
6.4 代码组织与复用
我建议把常用的图像处理操作封装成函数,比如read_image_safe、resize_keep_ratio、show_image等。这样主流程代码会很干净,也方便在不同项目间复用。
一个实用的技巧是用配置文件管理参数。把滤波核大小、Canny阈值、缩放比例这些容易变的参数写在一个字典或JSON文件里,调参时只改配置不改代码。这在做实验对比时特别方便,你可以保存多组配置,快速切换对比效果。
7. 学习资源与进阶方向
7.1 官方文档的正确打开方式
OpenCV的官方文档是最权威的参考,但很多人不会用。文档分为Doxygen生成的API参考和教程两部分。API参考适合查函数签名和参数含义,教程适合系统学习某个模块。我建议把API参考页面加入书签,写代码时随时查阅。
查文档时注意版本号。OpenCV 4.x和3.x有不少API变化,比如findContours的返回值、VideoWriter_fourcc的写法等。文档页面左上角可以切换版本,确保你查的是自己安装的版本。
7.2 从OpenCV到深度学习的衔接
OpenCV不是终点,而是起点。当你把传统图像处理用熟之后,自然会遇到它的局限性:Haar人脸检测对侧脸和遮挡效果差,传统特征匹配在纹理少的场景下失效,光流法在大位移时不准。这些问题深度学习方案解决得更好。
衔接的方式是用OpenCV做预处理和后处理,深度学习框架做核心推理。比如做目标检测,用OpenCV读视频帧、做尺寸归一化、做色彩空间转换,然后送入模型推理,输出的检测框再用OpenCV画到原图上。这个流程中OpenCV的角色是不可替代的,因为它的I/O和图像操作效率极高。
7.3 我个人的学习路径回顾
我当初学OpenCV走了不少弯路。最开始是照着网上的代码抄,能跑通但不知道每行在干什么。后来强迫自己每用一个新函数就去查文档,搞清楚每个参数的含义和取值范围,进步才快起来。
另一个有效的办法是给自己定小项目。比如“批量给照片加水印”、“做一个简单的颜色追踪器”、“把视频转成素描风格”。有了具体目标,学习就有了方向,遇到问题也知道该查什么。纯粹按部就班地看教程,很容易看到后面忘了前面。
最后一个建议是养成写笔记的习惯。每解决一个报错、每调通一组参数,就记下来。这些笔记在你下次遇到类似问题时能节省大量时间。我现在的笔记里积累了上百条OpenCV的实操记录,从环境配置到算法调参都有,比任何教程都贴合自己的实际需求。
这个专栏后续还会覆盖特征匹配、相机标定、光流追踪、背景减除等进阶内容,每一篇都会保持同样的风格:先讲清楚为什么,再讲怎么做,最后分享踩过的坑。你可以按顺序读,也可以挑自己需要的模块跳着看。遇到问题欢迎在评论区交流,我看到都会回复。