资讯动态

AI for Beginners 第 6 课:计算机视觉入门 —— 用 OpenCV 做图像预处理、帧差运动检测与光流分析

发布时间:2026/10/9 1:46:31 来源:尧图企业网站定制
教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载导读计算机视觉Computer Vision是让计算机对数字图像获得“高层理解”的技术领域是 AI for Beginners 课程中“第 4 周计算机视觉”的第一课第 6 课。本文围绕课程配套文档 Introduction to Computer Vision 展开先讲清楚计算机视觉的任务谱系与四大 Python 图像库的定位再结合仓库中可运行的 OpenCV.ipynb 演示三个完整实战案例——盲文Braille图像预处理切分、基于帧差frame difference的视频运动检测、基于密集光流dense optical flow的运动方向分析最后介绍配套实验室作业用光流提取手势的上下左右方向。读完后你将能独立使用 OpenCV 完成图像加载、色彩空间转换、阈值化、透视变换与光流计算等经典算法流程。计算机视觉的任务谱系按照课程文档的定义计算机视觉的目标是让计算机对数字图像获得高层理解。由于“理解”可以包含多种含义这一领域的任务范围相当宽图像分类image classification最简单的任务判断整张图属于哪一类目标检测object detection在图中找到具体对象的位置事件检测event detection理解画面中正在发生什么图像描述用自然语言描述一张图片3D 场景重建从图像重建三维场景针对人形的专项任务年龄与情绪估计、人脸检测与识别、3D 姿态估计等。课程指出计算机视觉通常被视为 AI 的一个分支如今绝大多数视觉任务都靠神经网络解决——课程接下来的 卷积神经网络CNN一课 就会专门讲解视觉领域专用的网络结构。但本节的重点是另一半在把图像交给神经网络之前往往先用算法化的技术即“经典计算机视觉”对图像做增强和预处理。这正是 OpenCV 用武之地。四大 Python 图像处理库的定位课程文档给出了选型参考四者各有侧重库语言/实现定位与典型用途imageioPython读写各种图像格式支持 ffmpeg适合把视频帧转成图像PillowPILPython功能更强一些支持变形morphing、调色板调整等图像操作OpenCVC 内核 Python 接口事实上的图像处理标准库de facto standard算法丰富dlibC Python 接口实现多种机器学习算法适合人脸与面部关键点检测等较难任务本节聚焦 OpenCV。仓库中 第 5 周NLP的 PyTorch 需求文件 中固定了opencv-python4.5.1.48、numpy1.22.0、Pillow12.2.0、matplotlib这些版本组合可以作为本课实验环境的安装参考。OpenCV 基础图像即 NumPy 数组加载图像与色彩空间OpenCV 的核心思想是图像在 Python 中就是一个 NumPy 数组。以 320x200 像素为例灰度图存放在200x320的二维数组中彩色图为200x320x3的三维数组第三个维度对应 3 个颜色通道。加载与显示图像的最小代码与 OpenCV.ipynb 的加载流程一致仓库配套素材为盲文照片 data/braille.jpegimport cv2 import matplotlib.pyplot as plt im cv2.imread(data/braille.jpeg) # 返回 NumPy 数组 print(im.shape) # (高, 宽, 3) plt.imshow(im)这里有一个新手最容易踩的坑OpenCV 出于历史原因使用 BGR蓝-绿-红通道顺序而 matplotlib 等其他 Python 工具使用更常见的 RGB。直接用plt.imshow显示 OpenCV 读入的彩色图颜色会发“青”。修正方式有两种——在 NumPy 数组层面交换维度或调用 OpenCV 的cvtColorim cv2.cvtColor(im, cv2.COLOR_BGR2RGB)同一个cvtColor函数还能完成其他色彩空间变换例如转灰度cv2.COLOR_BGR2GRAY或转到 HSV色相-饱和度-明度空间。在 OpenCV.ipynb 中由于对盲文样本不关心颜色第一步就是bw_im cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # 转灰度shape 变为 (高, 宽)OpenCV 同样可以逐帧加载视频cv2.VideoCapture 循环vid.read()OpenCV.ipynb 中就演示了对 data/motionvideo.mp4 的逐帧读取。图像预处理工具箱在把图像喂给神经网络之前通常要做若干预处理步骤。课程文档列出的 OpenCV 能力清单如下每项都给出可直接使用的调用形式缩放Resizeim cv2.resize(im, (320,200), interpolationcv2.INTER_LANCZOS)模糊Blur中值模糊im cv2.medianBlur(im,3)高斯模糊im cv2.GaussianBlur(im, (3,3), 0)亮度/对比度调整通过 NumPy 数组运算实现课程文档引用了 StackOverflow 上的经典做法阈值化Thresholding调用cv2.threshold/cv2.adaptiveThreshold课程认为这通常优于直接调亮度对比度几何变换仿射变换Affine transformation当你知道图中三个点的源/目标位置时可组合旋转、缩放与错切其特点是保持平行线平行透视变换Perspective transformation当你知道四个点的源/目标位置时可用典型场景是用手机斜拍一张矩形文档、然后把文档“拉正”成矩形光流Optical flow理解图像内部像素的运动。实战案例一盲文照片的预处理与字符切分OpenCV.ipynb 的第一个完整案例是从一张盲文书籍照片出发纯靠传统计算机视觉手段把一个个盲文符号切分出来供后续神经网络分类。这正是课程反复强调的理念——如果视觉技术能让神经网络的工作变简单就应该做因为它可以用更少的训练数据解决问题。第一步多级阈值化增强盲文点阵在照片中光照不均notebook 采用的是一组“模糊 自适应阈值 Otsu 全局阈值”交替执行的增强流水线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)这里同时出现了课程文档提到的两类阈值函数cv2.adaptiveThreshold按局部均值自适应决定阈值适合光照不均的图和cv2.threshold(..., cv2.THRESH_OTSU)Otsu 算法自动选取全局最优阈值。两轮“模糊—阈值”交替可以显著压掉噪声。第二步用 ORB 提取特征点定位点阵要处理盲文需要先“提取”每个凸点即把图像变成一组点坐标。notebook 使用 ORB 特征检测SIFT、SURF、ORB 一类的特征提取技术orb cv2.ORB_create(5000) f, d orb.detectAndCompute(im, None) pts [x.pt for x in f] # 所有特征点坐标第三步透视变换把倾斜的文本“拉正”从所有特征点的 min/max 坐标可以算出整段文本的包围盒。由于照片拍摄角度问题文本可能是倾斜的因此对包围盒四角外加 5 像素偏移off5做透视变换映射到一个尺寸等比例的矩形目标区域off 5 src_pts np.array([(min_x-off, min_y-off), (min_x-off, max_yoff), (max_xoff, min_y-off), (max_xoff, max_yoff)]) 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))这正是课程文档中“透视变换”要点的落地已知四个源点和目标点位置用findHomography求单应矩阵再warpPerspective完成变换。第四步网格切片得到单个符号对齐之后切分就变得简单了——按固定的字符格高 36、宽 24 像素遍历跳过全空的格子逐块yieldchar_h 36 char_w 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:ychar_h, x:xchar_w]) 0: yield img[y:ychar_h, x:xchar_w] x char_w y char_h切分结果与流水线各阶段效果如下图所示左为预处理后的二值图右为切出的单个盲文符号形态上已经接近可直接送进分类网络的样本。实战案例二帧差法视频运动检测第二个案例解决一个非常高频的工程问题监控摄像头前是否发生了变化有变化时再用神经网络去理解画面远比逐帧跑网络便宜。核心思想课程文档与 notebook 中一致如果摄像头是固定的连续两帧应该非常相似。帧就是数组直接把相邻两帧做数组减法就能得到逐像素差异——静态场景差异很小一旦出现明显运动差值就会显著升高。读帧、转灰度、计算差异范数vid cv2.VideoCapture(data/motionvideo.mp4) c 0 frames [] while vid.isOpened(): ret, frame vid.read() if not ret: break frames.append(frame) c 1 vid.release() print(fTotal frames: {c}) # 运动检测不关心颜色全部转灰度后做帧差 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]) # 每帧变化的“幅度”diff_amps曲线直观反映了画面中“活动的量”用滑动平均 阈值定位“事件”区间为了生成“事件发生时抓拍中间帧”的报告需要找到事件的起止帧。notebook 用滑动平均np.convolve实现平滑曲线、设定阈值 13000再用np.where找出超过阈值的帧最后提取一段长度大于 30 帧的连续区间def moving_average(x, w): return np.convolve(x, np.ones(w), valid) / w threshold 13000 active_frames np.where(diff_amps threshold)[0] def subsequence(seq, min_length30): ss [] for i, x in enumerate(seq[:-1]): ss.append(x) if x 1 ! seq[i1]: if len(ss) min_length: return ss ss.clear() sub subsequence(active_frames) # 展示事件中间的帧 plt.imshow(cv2.cvtColor(frames[(sub[0]sub[-1])//2], cv2.COLOR_BGR2RGB))注意 notebook 特意演示了同一个帧在不转 RGB 与转 RGB 之后的显示差异再次印证了开头讲的 BGR/RGB 通道顺序问题。实战案例三密集光流分析运动方向帧差只能告诉你“变化有多大”却不能告诉你什么在动、往哪里动。这就需要光流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:])] flows[0].shape # (高, 宽, 2)两个通道分别是 x、y 方向分量每帧光流的形状与画面相同、带 2 个通道恰好对应运动向量在 x、y 方向的分量。用 HSV 颜色编码可视化向量场二维向量场不好直接画notebook 用了一个巧妙的技巧把光流转到极坐标得到每个像素的“方向 强度”然后构造 HSV 图像——色相H表示方向明度V表示强度饱和度固定 255def flow_to_hsv(flow): hsvImg np.zeros((flow.shape[0], flow.shape[1], 3), dtypenp.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)得到的彩色帧中不同颜色直接对应不同运动方向——在 notebook 的示例中偏绿表示向左移动蓝色表示向右移动。从源码逻辑看光流还有一个实用推论如果一帧内几乎所有像素都朝大致同一方向移动说明是相机本身在移动此时可以对画面做运动补偿。实验室作业用手势光流判断上/下/左/右课程的配套作业见 lab/README.md给定一段手掌在静止背景前左右上下移动的素材 palm-movement.mp4截图如下你的目标是用光流判断视频的哪些片段分别包含上、下、左、右运动进阶目标是用肤色检测实际追踪手掌/手指。MovementDetection.ipynb 给出了分步提示按课上方法读取视频帧计算密集光流并转到极坐标对每帧光流构建方向直方图统计有多少向量落在各个角度 bin 中——建议先把幅度低于阈值的向量清零以滤掉眼球、头部等细小抖动观察直方图后选取对应上/下/左/右的角度 bin并设一个阈值判定运动方向。这条作业路径恰好把本课三个概念串了起来视频读帧、密集光流、极坐标 直方图统计。小结与学习路径课程文档的结论是有些相对复杂的任务运动检测、指尖检测等可以完全用经典计算机视觉技术解决不需要神经网络。因此掌握这些基础技术以及 OpenCV 的能力边界非常有价值——它既能独立解决问题也能在需要神经网络时做高质量的前端预处理如盲文切分案例。在本课程的计算机视觉章节中本课时承上启下接下来会进入 卷积神经网络07-ConvNets学习真正用网络解决分类与检测问题的方法。想进一步加深光流理解可以运行 OpenCV.ipynb 中“Extract Motion using Optical Flow”一节的完整代码配合 data/motionvideo.mp4 观察光流 HSV 可视化效果再动手完成 MovementDetection.ipynb 的方向直方图作业。相关仓库文件索引本课讲解文档英文OpenCV 演示 notebook实验室作业说明 与 作业 notebook配套素材盲文原图、运动视频计算机视觉章节总览赞分享教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载相关推荐AI for Beginners 计算机视觉入门OpenCV 图像预处理、帧差法运动检测与光学流实战AI for Beginners 计算机视觉入门OpenCV 图像预处理、帧差法运动检测与光学流实战 本文基于 AI for Beginners 课程中计算教程人工智能机器学习深度学习计算机视觉入门与 OpenCV 实战图像预处理、运动检测与光流分析AI for Beginners 第 06 课计算机视觉入门与 OpenCV 实战图像预处理、运动检测与光流分析AI for Beginners 第 06 课 导读本文基于 AI for Begin教程人工智能机器学习深度学习AI-For-Beginners 第 06 课计算机视觉入门——用 OpenCV 完成图像加载、预处理、运动检测与光流分析AI For Beginners 第 06 课计算机视觉入门——用 OpenCV 完成图像加载、预处理、运动检测与光流分析 本文为 AI For Beginn教程人工智能机器学习深度学习上一篇Homebridge终极指南轻松将非HomeKit设备接入Apple智能家居生态下一篇Talos Linux自动化运维终极指南Ansible Playbook开发实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑