- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
计算机视觉(Computer Vision)是让计算机获得对数字图像"高层次理解"的人工智能分支,而 OpenCV 则是该领域事实标准的图像处理库。本文以 AI-For-Beginners 课程第 6 课(计算机视觉与 OpenCV 入门)的德文翻译版为骨架,结合仓库中可运行的 OpenCV.ipynb 实验笔记本与 MovementDetection.ipynb 实验,完整讲解图像加载、色彩空间转换、预处理、盲文符号分离、帧差法运动检测与光流分析,让读者具备"用纯计算机视觉技术替神经网络减负"的实战能力。
什么是计算机视觉:从任务谱系到课程定位
计算机视觉是一个目标宽泛的学科:它要让计算机对数字图像产生高层次理解,而"理解"本身包含多种含义:
- 对象检测(Object Detection):在图像中找到某个物体;
- 事件检测(Event Detection):理解画面中正在发生什么;
- 图像描述:把一幅图用文字描述出来;
- 三维场景重建:从图像反推立体场景;
- 还有与人像相关的专项任务:年龄与情绪估计、人脸检测与身份识别、3D 姿态估计等。
在这些任务中,最简单的一类就是图像分类(Image Classification)。课程 第 4 部分计算机视觉总览 依次覆盖了本课(IntroCV/OpenCV)、卷积神经网络、迁移学习、自编码器、GAN、对象检测与语义分割,本课正是整个计算机视觉章节的起点。
如今大多数计算机视觉任务都靠神经网络解决。但课程给出了一个容易被忽视的关键观点:在把图像交给神经网络之前,很多情况下先用算法技术增强/预处理图像是划算的。高质量预处理能让后续神经网络用更少的数据、更简单的模型完成任务(这一点在 OpenCV.ipynb 的结尾也有明确论述)。这也是本课聚焦 OpenCV 的根本原因。
图像处理 Python 库全景:imageio、Pillow、OpenCV、dlib
课程文档开篇即对比了四款 Python 生态中最常用的图像处理库,选型建议如下:
| 库 | 定位与能力 | 典型用途 |
|---|---|---|
| imageio | 读写多种图像格式,支持调用 ffmpeg | 将视频帧批量转换为图像 |
| Pillow(PIL) | 比 imageio 更强大,支持变形(morphing)、调色板调整等操作 | 基础图像读写与简单像素级操作 |
| OpenCV | 用 C++ 编写的高性能图像处理库,已成为事实标准,提供便捷的 Python 接口 | 复杂图像处理、几何变换、光流、特征点提取 |
| dlib | C++ 编写的机器学习库,内含多项 CV 算法,有 Python 接口 | 人脸检测与面部关键点(facial landmark)识别等进阶任务 |
其中 OpenCV 因算法覆盖面广、性能高而被视为"事实标准"。在仓库根目录的 environment.yml 中,OpenCV 通过conda-forge::opencv渠道安装;requirements.txt 中则固定了imageio==2.35.0、pillow==12.2.0等配套版本,读者可直接据此搭建与本课程一致的实验环境。
OpenCV:加载图像与理解色彩空间
用 NumPy 数组理解图像
OpenCV 读入的图像本质上是 NumPy 数组。例如一张 320×200 像素的灰度图,对应形状为200×320的二维数组;同尺寸彩色图则对应形状为200×320×3的三维数组(3 个通道分别对应颜色分量)。加载并显示一张图像的入门代码如下(摘自 OpenCV.ipynb):
import cv2 import matplotlib.pyplot as plt im = cv2.imread('image.jpeg') plt.imshow(im)BGR 与 RGB:OpenCV 的历史遗留
一个必须掌握的细节:OpenCV 传统上使用 BGR(蓝-绿-红)编码存储彩色图像,而 matplotlib 等大多数 Python 工具采用 RGB(红-绿-蓝)。直接plt.imshow一张 OpenCV 读入的彩色图,颜色会明显失真。解决办法有两种:手动交换 NumPy 数组的通道维度,或调用 OpenCV 转换函数:
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)同一cvtColor函数还能完成其他色彩空间变换,例如转灰度cv2.COLOR_BGR2GRAY、转 HSV(色调-饱和度-明度)色彩空间。实验笔记本中特别提醒:大多数情况下应在加载图像后立即转成 RGB,避免后续展示与调试时踩坑。此外,OpenCV 还可以用cv2.VideoCapture逐帧加载视频,OpenCV.ipynb 的"帧差法运动检测"一节即演示了完整流程。
输入神经网络前的图像预处理
将图像交给神经网络之前,通常需要一串预处理步骤。课程文档与笔记本共同给出的 OpenCV 能力清单如下:
- 尺寸调整:
im = cv2.resize(im, (320, 200), interpolation=cv2.INTER_LANCZOS)interpolation参数控制插值算法(如INTER_LANCZOS适合高质量缩放)。 - 模糊去噪:
im = cv2.medianBlur(im, 3) # 中值模糊,ksize 取奇数 im = cv2.GaussianBlur(im, (3, 3), 0) # 高斯模糊,第三参数为 σ - 亮度与对比度调整:可通过 NumPy 数组运算直接完成(例如像素值整体加减/乘除)。
- 阈值化(Thresholding):调用
cv2.threshold/cv2.adaptiveThreshold。课程特别指出,在许多场景下阈值化比调节亮度/对比度更可取,因为它能干净地把前景与背景分离。 - 几何变换:
- 仿射变换(Affine):当你已知图像中 3 个点的源与目标位置,需要同时组合旋转、缩放与倾斜时使用;仿射变换保持平行线仍平行。
- 透视变换(Perspective):当你已知 4 个点的源与目标位置时使用。典型场景:用手机斜着拍了一张矩形文档,想矫正成端正的矩形文档图。
- 光流(Optical Flow):用于理解图像内部的运动,分为稠密光流与稀疏光流(详见下文实战三)。
实战一:盲文照片预处理——阈值化 + 特征点 + 透视变换 + 切片
课程文档给出的第一个端到端案例是对一张盲文书照片做预处理,把单个盲文符号分离出来,便于后续交给神经网络分类。案例使用的原始图与处理结果如下:
| 原始盲文照片 | 预处理后 | 分离出的盲文符号 |
|---|---|---|
图片来自 OpenCV.ipynb
这个案例完整展示了"纯图像处理"如何为神经网络铺路,OpenCV.ipynb 中的实现细节如下:
第一步:灰度化与阈值化管线。颜色对盲文识别无用,先用cvtColor转灰度,再组合多种处理手段增强图像:
im = cv2.blur(bw_im, (3, 3)) im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 4) im = cv2.medianBlur(im, 3) _, im = cv2.threshold(im, 0, 255, cv2.THRESH_OTSU) im = cv2.GaussianBlur(im, (3, 3), 0) _, im = cv2.threshold(im, 0, 255, cv2.THRESH_OTSU)这里adaptiveThreshold用邻域均值自适应确定阈值(块大小 5、常量 C=4),THRESH_OTSU则自动计算全局最优阈值,两次 Otsu 与模糊交替使用以压制噪声。
第二步:ORB 特征点提取,把图像变成坐标集合。对后续的符号切割而言,更实用的做法是用特征提取(SIFT/SURF/ORB 之一,这里用 ORB)把"点"从图像里抽出来:
orb = cv2.ORB_create(5000) # 最多提取 5000 个特征点 f, d = orb.detectAndCompute(im, None) pts = [x.pt for x in f] # 特征点坐标随后可用cv2.circle把这些点画在空白画布上,直观校验提取结果。
第三步:用特征点坐标求整体包围盒。通过特征点坐标的 min/max 得到整段盲文文本的边界框:
min_x, min_y, max_x, max_y = [int(f([z[i] for z in pts])) for f in (min, max) for i in (0, 1)]第四步:透视变换矫正旋转。盲文照片可能存在轻微旋转,用文本的 4 个角点构造单应矩阵并矫正为规则矩形:
off = 5 src_pts = np.array([(min_x - off, min_y - off), (min_x - off, max_y + off), (max_x + off, min_y - off), (max_x + off, max_y + off)]) w = int(max_x - min_x + off * 2) h = int(max_y - min_y + off * 2) dst_pts = np.array([(0, 0), (0, h), (w, 0), (w, h)]) ho, m = cv2.findHomography(src_pts, dst_pts) trim = cv2.warpPerspective(im, ho, (w, h))第五步:按固定窗口切片。矫正后按盲文字符的典型尺寸滑动切割,跳过空白行,得到单个符号:
char_h, char_w = 36, 24 def slice(img): dy, dx = img.shape y = 0 while y + char_h < dy: x = 0 while x + char_w < dx: if np.max(img[y:y + char_h, x:x + char_w]) > 0: # 跳过空窗 yield img[y:y + char_h, x:x + char_w] x += char_w y += char_h整个流程表明:许多任务可以不借助任何"智能"而纯粹用图像处理完成。既然能用 CV 技术降低神经网络的负担,就应该优先做——这能显著减少训练数据需求。
实战二:帧差法运动检测——从数组相减到事件定位
运动检测是监控类场景的高频需求:先知道"画面有动静",再决定是否调用神经网络理解内容,成本更低。课程文档点明了核心思想:如果摄像头固定,连续帧应该高度相似;帧本质是数组,两帧相减得到的像素差在静止时很小,画面有明显运动时显著变大。
OpenCV.ipynb 给出了完整可运行的实现链路:
vid = cv2.VideoCapture('data/motionvideo.mp4') frames = [] while vid.isOpened(): ret, frame = vid.read() if not ret: break frames.append(frame) vid.release()随后把所有帧转灰度,逐对相减并计算差值的范数,得到"活动强度曲线":
bwframes = [cv2.cvtColor(x, cv2.COLOR_BGR2GRAY) for x in frames] diffs = [(p2 - p1) for p1, p2 in zip(bwframes[:-1], bwframes[1:])] diff_amps = np.array([np.linalg.norm(x) for x in diffs]) plt.plot(diff_amps)再用滑动平均平滑噪声曲线,并设定阈值定位"事件"(threshold = 13000,与仓库数据配套):
def moving_average(x, w): return np.convolve(x, np.ones(w), 'valid') / w threshold = 13000 active_frames = np.where(diff_amps > threshold)[0]为了在事件中挑一张有代表性的画面,还实现了"连续帧序列提取"(长度超过 30 帧才算有效事件),最终展示事件中间帧。若直接显示会发现颜色不对——这正是 BGR/RGB 问题,补上cv2.cvtColor(..., cv2.COLOR_BGR2RGB)即可。帧差可视化效果如下:
图片来自 OpenCV.ipynb
实战三:光流分析——理解"什么在动、往哪动"
帧差法只能告诉你"变化量有多大",无法回答"是什么在动、向哪个方向动"。课程文档引入了光流(Optical Flow):逐像素追踪视频帧间的运动。它有两种形态:
- 稠密光流(Dense Optical Flow):为每个像素计算运动矢量场;
- 稀疏光流(Sparse Optical Flow):只选取显著特征(如边缘)并追踪其在帧间的轨迹。
OpenCV.ipynb 使用 Farneback 算法计算稠密光流:
flows = [cv2.calcOpticalFlowFarneback(f1, f2, None, 0.5, 3, 15, 3, 5, 1.2, 0) for f1, f2 in zip(bwframes[:-1], bwframes[1:])]每个流场形状与帧相同、带 2 个通道(分别对应 x、y 分量)。为了可视化二维流场,笔记本使用了一个巧妙技巧:把光流矢量转成极坐标(方向 + 强度),再用HSV 色彩空间渲染——H(色调)表示方向、V(明度)表示强度、S 固定为 255:
def flow_to_hsv(flow): hsvImg = np.zeros((flow.shape[0], flow.shape[1], 3), dtype=np.uint8) mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1]) hsvImg[..., 0] = 0.5 * ang * 180 / np.pi hsvImg[..., 1] = 255 hsvImg[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX) return cv2.cvtColor(hsvImg, cv2.COLOR_HSV2BGR)在生成的彩色流场图中,绿色系代表向左移动、蓝色系代表向右移动(具体色相映射取决于角度编码)。这种全局方向信息非常有价值:例如当画面中几乎所有像素都朝同一方向运动时,可推断是摄像头自身在移动,进而做运动补偿。光流可视化效果如下:
图片来自 OpenCV.ipynb
动手环节:OpenCV Notebook 与手势方向识别 Lab
课程为每个单元配套了可运行的实验笔记本。本课的主笔记本是 OpenCV.ipynb,它把上文三个实战按可执行代码 + 图文说明的格式完整串联起来,并定义了display_images辅助函数用于并排展示多张图。
配套的动手实验是 Lab:用光流识别手势方向:视频 palm-movement.mp4 中,一个人在稳定背景上让手掌分别向左/右/上/下移动。任务流程在 MovementDetection.ipynb 中给出:
- 按讲义方法逐帧读取视频;
- 计算稠密光流帧并转为极坐标;
- 对每个光流帧统计方向直方图——直方图统计各方向区间内的矢量数量,即可把不同运动方向区分开;
- 建议先把幅值低于阈值的光流矢量清零,过滤掉眨眼、头部晃动等微小运动;
- 观察直方图后,选取对应上/下/左/右的直方图区间且超过一定阈值的帧,判定运动方向。
作为延伸目标,可以进一步用肤色(skin tone)跟踪手掌/手指的精细运动。完成该实验,你就真正掌握了"用光流判断视频运动方向"的完整链路。
运行环境与依赖
本课所有代码都基于 Python 与 OpenCV,建议按仓库根目录的 environment.yml 创建 conda 环境(其中已包含conda-forge::opencv、ipython、python等),或参考 requirements.txt 中的固定版本(含imageio==2.35.0、pillow==12.2.0等)。除cv2外,笔记本还用到了numpy与matplotlib(含pyplot),实验目录内的视频文件(data/motionvideo.mp4、lab/palm-movement.mp4)已随仓库提供,无需额外下载数据即可复现全部结果。
总结、挑战与延伸学习
本课的收尾结论很实用:诸如运动检测、指尖检测这类看起来复杂的问题,有时可以完全由纯计算机视觉解决。因此,了解 CV 基础技术与 OpenCV 的能力边界,是任何 AI 从业者的基本功。课程还布置了挑战任务:调研以"积木化方式让非专业人士通过机器人完成 CV 任务"的开源项目(如 AI Show 中介绍的 Cortic Tigers 方案),思考如何降低初学者进入该领域的学习门槛。课后的延伸阅读主题集中在光流的进阶用法;需要更系统地学习 OpenCV 时,也可以从本课笔记出发逐步深入。
一句话总结本课方法论:先让 OpenCV 这类传统 CV 技术把图像整理干净、把运动线索提炼出来,再让神经网络去解决真正"智能"的部分——这是工程上最省数据、最稳定、也最被低估的 AI 落地姿势。
- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
相关推荐
计算机视觉入门实战:AI-For-Beginners 课程第 6 课 OpenCV 图像处理与运动检测指南
计算机视觉入门实战:AI For Beginners 课程第 6 课 OpenCV 图像处理与运动检测指南 计算机视觉是让计算机"看懂"数字图像的技术分支,而本
教程人工智能机器学习深度学习AI for Beginners 课程实战:用 OpenCV 入门计算机视觉——图像预处理、视频运动检测与光学流
AI for Beginners 课程实战:用 OpenCV 入门计算机视觉——图像预处理、视频运动检测与光学流 导读 计算机视觉(Computer Visio
教程人工智能机器学习深度学习计算机视觉入门与 OpenCV 实战:图像预处理、运动检测与光流分析(AI for Beginners 第 06 课)
计算机视觉入门与 OpenCV 实战:图像预处理、运动检测与光流分析(AI for Beginners 第 06 课) 导读:本文基于 AI for Begin
教程人工智能机器学习深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考