AI-For-Beginners 计算机视觉课程全景指南:OpenCV 预处理、CNN 到迁移学习与生成模型

原创2026-10-02 10:56:411,669 阅读
文章标签:教程人工智能机器学习深度学习计算机视觉NLP

AI-For-Beginners 计算机视觉课程全景指南:OpenCV 预处理、CNN 到迁移学习与生成模型

导读

本文围绕 AI-For-Beginners 课程中「4-ComputerVision」章节(即 translations/cs/lessons/4-ComputerVision/README.md 所对应的核心内容,英文原版见 lessons/4-ComputerVision/README.md)展开,系统梳理该章节覆盖的七大主题:OpenCV 图像处理入门、卷积神经网络(CNN)、预训练模型与迁移学习、自编码器、生成对抗网络(GAN)、目标检测与语义分割。读完本文,你将理解从「读取一张图片」到「训练生成模型」的完整计算机视觉技术脉络,掌握每个主题的核心原理、关键代码用法、对应 Notebook 实验路径以及典型应用场景,可作为逐课学习的导航地图。

AI-For-Beginners 计算机视觉章节内容概览涂鸦图

章节地图:一节课通往一个视觉任务

计算机视觉是让计算机获得对数字图像高层理解的一门学科。这里的「理解」含义宽泛,既包括在图片中寻找物体(目标检测)、理解正在发生的事件(事件检测)、用文字描述图片,也包括在三维空间中重建场景,以及与人像相关的年龄/情绪估计、人脸检测识别、三维姿态估计等特殊任务。其中最简单的任务之一是图像分类。

本节(4-ComputerVision)共包含 7 课,每一课对应一类核心技术:

课程 主题 仓库路径
06 计算机视觉与 OpenCV 入门 06-IntroCV/README.md
07 卷积神经网络 07-ConvNets/README.md
08 预训练网络与迁移学习 08-TransferLearning/README.md
09 自编码器 09-Autoencoders/README.md
10 生成对抗网络 10-GANs/README.md
11 目标检测 11-ObjectDetection/README.md
12 语义分割 12-Segmentation/README.md

下面逐课展开。

1. 计算机视觉与 OpenCV:进入图像世界的第一步

为什么需要 OpenCV

现代计算机视觉任务大多由神经网络解决,本节的后续课程会重点介绍专用网络——卷积神经网络。但在把图像送入神经网络之前,往往值得先用算法技术对图像做增强与预处理。课程列举了四个常用的 Python 图像处理库:

  • imageio:用于读写多种图像格式,还支持 ffmpeg,可把视频帧转换为图像;
  • Pillow(PIL):功能更强,支持变形、调色板调整等操作;
  • OpenCV:用 C++ 编写的强大图像处理库,已成为图像处理的 de facto 标准,提供便捷的 Python 接口;
  • dlib:C++ 库,实现多种机器学习算法,可用于人脸与面部关键点检测等挑战性任务。

图像加载与颜色空间

在 Python 中,图像可以方便地用 NumPy 数组表示:320×200 像素的灰度图存储在 200×320 数组中,同尺寸彩色图形状为 200×320×3(三个颜色通道)。加载图像:

import cv2
import matplotlib.pyplot as plt

im = cv2.imread('image.jpeg')
plt.imshow(im)

关键细节:OpenCV 传统上对彩色图使用 BGR(蓝-绿-红)编码,而 Python 生态中其他工具多用 RGB。要让图像显示正常,需要转换到 RGB 颜色空间:

im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

同一个 cvtColor 函数还能完成其他颜色空间变换,如转灰度或 HSV(色相-饱和度-明度)。课程配套的 OpenCV.ipynb 中还给出了用 OpenCV 逐帧加载视频的示例。

图像预处理操作

送入神经网络前常用的预处理包括:

  • 缩放:im = cv2.resize(im, (320,200), interpolation=cv2.INTER_LANCZOS)
  • 模糊:im = cv2.medianBlur(im, 3) 或 im = cv2.GaussianBlur(im, (3,3), 0)
  • 亮度与对比度:可通过 NumPy 数组操作实现;
  • 阈值化:调用 cv2.threshold / cv2.adaptiveThreshold,通常比直接调亮度/对比度更优;
  • 几何变换:
    • 仿射变换:已知图像中三个点的源/目标位置时,可组合旋转、缩放与倾斜,且保持平行线平行;
    • 透视变换:已知四个点的源/目标位置时适用。例如用手机斜拍一张矩形文档,可借此矫正为正视的矩形图;
  • 光流(optical flow):用于理解图像内部的运动。

三个实战案例

课程用 OpenCV.ipynb 演示了三个真实任务:

  1. 盲文书照片预处理:通过阈值化、特征检测、透视变换和 NumPy 操作,把单个盲文符号分离出来,供后续神经网络分类。
  2. 用帧差检测视频中的运动:相机固定时,相邻帧应高度相似。帧以数组表示,直接对相邻两帧做数组相减即可得到像素差——静态场景差值低,画面出现明显运动时差值变大。
  3. 用光流检测运动:光流让我们理解视频帧中单个像素如何移动。稠密光流为每个像素计算运动向量场;稀疏光流则先取图像中的显著特征(如边缘),再逐帧构建其运动轨迹。

本课结论是:运动检测、指尖检测这类相对复杂的任务,有时可以纯粹靠计算机视觉算法解决,因此掌握基础 CV 技术与 OpenCV 的能力边界非常有价值。配套实验(lab/README.md)要求拍摄一段带简单手势的视频,用光流提取上/下/左/右运动。

2. 卷积神经网络:让特征被自动学习

从模式到卷积核

此前课程已证明,单层感知机就能以不错的准确率识别 MNIST 手写数字。但 MNIST 太「特殊」——所有数字都居中,任务被简化了。真实场景要求无论物体在图像中的什么位置都能识别。计算机视觉区别于普通分类的关键在于:我们是在扫描图像、寻找特定模式及其组合。例如找猫时,先找可能构成胡须的水平线,再判断胡须的特定组合是否构成猫。重要的是模式的相对位置与存在与否,而非其精确坐标。

提取模式靠卷积滤波器。图像是 2D 矩阵(或带颜色深度的 3D 张量);应用滤波器即取较小的卷积核矩阵,对原图中每个像素与邻域点计算加权平均——就像一个小窗口滑过整幅图像,按卷积核权重对像素求平均。例如把 3×3 的垂直边缘滤波器和水平边缘滤波器作用于 MNIST 数字,会突出图像中的垂直/水平边缘位置,因而这两个滤波器可用来「寻找」边缘;同理可设计不同滤波器寻找其他低层模式(如 Leung-Malik 滤波器组)。

CNN 的核心思想正是:不仅手工设计滤波器,还设计网络结构让滤波器被自动训练学习;并且同样的方法可以作用于高层特征——CNN 的特征提取建立在特征的层级结构上:从低层像素组合,到高层图片部件组合。这正是 07-ConvNets 一课的要点。

CNN 层级特征提取示意图

金字塔架构与 VGG-16

用于图像处理的大多数 CNN 遵循金字塔架构:作用于原始图像的第一个卷积层通常只有相对较少的滤波器(8–16 个),对应不同的像素组合(如水平/垂直线条);下一层在降低空间维度的同时增加滤波器数量,对应更多简单特征的组合。越靠近最终分类器,图像空间维度越小、滤波器数量越多。

典型例子是 VGG-16——它在 2014 年 ImageNet Top-5 分类中达到 92.7% 准确率。课程还提供了一篇 CNN_Architectures.md 专题文章,介绍最著名的 CNN 架构。

配套实验

通过两个 Notebook 动手验证可训练滤波器与卷积网络:

3. 预训练网络与迁移学习:站在 ImageNet 肩膀上

迁移学习的基本思想

训练 CNN 耗时且需要海量数据,而大量时间其实花在学习低层滤波器上。自然的问题:能否把在某个数据集上训练好的网络,改造后用在新图像分类任务上,而不必完整重训?这个思路称为迁移学习——把知识从一个网络模型迁移到另一个。做法是以预训练模型为起点(通常在 ImageNet 等大规模图像集上训练),这类模型已经擅长从通用图像中提取各种特征,很多时候只需在提取出的特征之上构建一个分类器,就能得到不错的结果。

预训练模型当作特征提取器

卷积网络由多层组成,每层负责从图像中提取某种特征:从低层像素组合(水平/垂直线条),到高层特征组合(如「火焰」的形态)。在足够大、足够多样化的通用图像集上训练后,网络就能学会提取这些通用特征。

Keras 与 PyTorch 都内置了轻松加载常见架构预训练权重的函数(多数基于 ImageNet)。课程推荐优先考虑的模型族:

  • VGG-16/VGG-19:相对简单的模型,准确率不错。作为迁移学习的首次尝试通常很合适;
  • ResNet:微软研究院 2015 年提出的模型族,层数更多,因此消耗更多资源;
  • MobileNet:体积更小的模型族,适合移动设备。资源紧张、可牺牲少量准确率时选用。

两个值得动手的实验

  • Cats vs. Dogs 分类:使用贴近真实场景的猫狗数据集,在对应 Notebook 中实践迁移学习:
  • 对抗猫可视化:预训练网络的「大脑」里存储着各种模式,包括「理想猫」(理想狗、理想斑马等)的概念。从随机图像出发,用梯度下降优化逐步调整图像,让网络判定它是猫,即可「可视化」这些概念。直接这样做会得到近似随机噪声的图像——因为让网络认为输入是猫的方式有很多种,其中一些在视觉上毫无意义。解决办法是在损失函数中加入变化损失(variation loss)——度量相邻像素的相似性,最小化它能令图像更平滑、去除噪声,从而显现更有视觉吸引力的模式。同样的思路还可以做对抗攻击:对一张被识别为狗的图像做微小扰动,直到网络把它分类为猫。复现代码见 AdversarialCat_TF.ipynb。

配套实验(lab/README.md)使用含 35 个猫狗品种的真实 Oxford-IIIT 宠物数据集,构建迁移学习分类器。进阶阅读可看 TrainingTricks.md 中更多训练技巧。

4. 自编码器:无监督地学习图像压缩表示

训练 CNN 的标注困境与自监督出路

训练 CNN 的一大难题是需要大量有标注数据:图像分类必须人工把图像归入不同类别。但我们完全可以只用原始(无标注)数据来训练 CNN 特征提取器——这称为自监督学习。自编码器的核心想法是:不提供标签,而是把训练图像同时作为网络输入与输出。网络由两部分组成:

  • 编码器网络:把输入图像转换到某个潜空间(latent space),通常是一个更小尺寸的向量;
  • 解码器网络:目标是重建原始图像。

由于我们训练自编码器尽可能保留原图信息以准确重建,网络会努力为输入图像寻找最好的**嵌入(embedding)**以捕获其含义。

自编码器的四大应用场景

重建原图本身看似无用,但自编码器在四个场景下尤其有价值:

  1. 降维:用于可视化或训练图像嵌入。自编码器通常优于 PCA,因为它考虑到了图像的空间性质与层级特征;
  2. 去噪:噪声携带大量无用信息,无法全部塞进较小的潜空间,于是网络只捕获图像的关键部分。训练时以原图为目标、以人为加噪的图作为输入;
  3. 超分辨率:以低分辨率图作为输入,目标重建高分辨率图;
  4. 生成模型:训练完成后,解码器部分可接收随机潜向量来生成新对象。

变分自编码器(VAE)

传统自编码器虽然压缩了维度,但其潜向量往往缺乏语义:以 MNIST 为例,很难说清哪个潜向量对应哪个数字,因为相近的潜向量未必对应同一数字。而训练生成模型时,最好能理解潜空间的结构——这引出了变分自编码器(VAE)。

VAE 是学习预测潜参数统计分布(即潜分布)的自编码器。比如我们希望潜向量服从某个均值 z_mean 与标准差 z_sigma 的正态分布(两者都是 d 维向量)。编码器学习预测这些参数,解码器则从该分布随机取一个向量来重建对象。流程可总结为:

  • 从输入向量预测 z_mean 和 z_log_sigma(预测的是标准差的对数而非标准差本身);
  • 从分布 N(z_mean, exp(z_log_sigma)) 中采样向量 sample;
  • 解码器用 sample 作为输入向量解码原图。

VAE 的损失函数由两部分构成:

  • 重建损失(Reconstruction loss):度量重建图像与目标的接近程度(如均方误差 MSE),与普通自编码器相同;
  • KL 损失:基于 Kullback-Leibler 散度,保证潜变量分布接近正态分布。

VAE 的一大优势是生成新图像相对容易——因为你知道该从哪个分布采样潜向量。课程展示了在 MNIST 上训练 2D 潜向量的 VAE 后,通过变化潜向量分量获得不同数字、以及 2D 可视化潜空间中数字逐渐融合的效果。动手实验见 AutoencodersTF.ipynb 与 AutoEncodersPyTorch.ipynb。

自编码器的三条性质

  • 数据特定:只对训练过的图像类型效果好。例如在花卉上训练的超分网络对肖像效果不佳,因为网络是靠从训练数据中学到的特征细节来补出高分辨率;
  • 有损:重建图像与原图不完全相同,损失的性质由训练时的损失函数决定;
  • 可工作于无标注数据。

5. 生成对抗网络:让两个网络互相博弈

架构:生成器 vs 判别器

上节提到 VAE 是生成模型的好例子,但如果想生成真正有意义、分辨率合理的内容(比如一幅画),VAE 训练往往难以收敛。为此需要专门面向生成模型的另一种架构——生成对抗网络(GAN)。核心想法是让两个神经网络互相博弈训练:

  • 生成器(Generator):接收随机向量,输出图像;
  • 判别器(Discriminator):接收图像,判断它是真实图像(来自训练集)还是生成器伪造的,本质是一个图像分类器。

判别器的架构与普通图像分类网络无异:最简单时可以是全连接分类器,但更常见的是卷积网络(基于 CNN 的 GAN 称为 DCGAN)。典型结构为:若干卷积+池化层(空间尺寸递减)、一个或多个全连接层得到「特征向量」、最后是二分类器。

生成器稍显复杂,可视为反向的判别器:从潜向量(替代特征向量)出发,用全连接层转换到所需尺寸/形状,随后是反卷积+上采样——与自编码器的解码器部分相似。因为卷积层本质是扫过图像的线性滤波器,反卷积与卷积基本类似,可用相同的层逻辑实现。

两阶段训练

GAN 之所以称为「对抗」,在于生成器与判别器之间持续的竞争。训练分两个阶段:

  1. 训练判别器:较直接。用生成器生成一批图像并标记为 0(伪造图),从数据集取一批图像标记为 1(真实图),计算判别器损失并反向传播;
  2. 训练生成器:稍复杂,因为我们不知道生成器的期望输出。把「生成器+判别器」的整个 GAN 网络接起来,喂入随机向量,期望输出为 1(对应真实图)。此时冻结判别器参数(不希望它在本步被训练),再做反向传播。

理想情况下,生成器与判别器的损失都不应显著下降,而是来回振荡,对应两个网络交替提升。GAN 训练尤其困难,课程明确列出了几类典型问题:

  • 模式坍缩(Mode Collapse):生成器学会只产生一张能骗过判别器的成功图像,而非多样的图像;
  • 对超参数敏感:常见现象是 GAN 完全不收敛,突然降低学习率后才收敛;
  • 生成器与判别器的平衡:很多情况下判别器损失会很快降到零,导致生成器无法继续训练。对策是给两者设置不同学习率,或在损失过低时跳过判别器训练;
  • 高分辨率训练:与自编码器问题相似,卷积网络重建太多层会产生伪影。通常用**渐进式生长(progressive growing)**解决——先在低分辨率图像上训练前几层,再逐步「解封」或新增层。

动手实验见 GANTF.ipynb 与 GANPyTorch.ipynb。

风格迁移

GAN 是生成艺术图像的好方法,另一项有趣的技术是风格迁移:取一张内容图像,用风格图像的滤镜重新绘制成不同风格。其工作方式是:

  • 从随机噪声图出发(也可从内容图出发,但理解上随机噪声更容易);
  • 目标:生成一张既接近内容图像又接近风格图像的图,由两个损失函数决定:
    • 内容损失:基于 CNN 在若干层从当前图像与内容图像提取的特征计算;
    • 风格损失:用 Gram 矩阵在当前图像与风格图像之间巧妙计算;
  • 另引入变化损失平滑图像、去除噪声(计算相邻像素的平均距离);
  • 主优化循环用梯度下降(或其他优化算法)调整当前图像,使三者加权和的总损失最小化。

完整示例见 StyleTransfer.ipynb。

6. 目标检测:从「是什么」到「在哪里」

从分类到定位

前面学的图像分类模型输入图像、输出类别结果(如 MNIST 中的数字类别)。但很多时候我们不仅想知道图片中有物体,还要确定它们的精确位置——这正是目标检测。最朴素的思路是:把图片切成若干块,对每块做图像分类,激活足够高的块即认为包含目标物体。但这只能给出非常不精确的边界框。要精确定位,需要运行某种回归来预测边界框坐标,为此需要专门的标注数据集。

常用数据集与评估指标

课程推荐了两个公开数据集:

  • PASCAL VOC:20 个类别;
  • COCO(Common Objects in Context):80 个类别,含边界框与分割掩码。

评估上,分类任务容易度量正确率,而检测任务既要度量类别正确性,也要度量边界框定位精度:

  • Intersection over Union(IoU):度量两个框(或任意两块区域)的重叠程度——交叠面积除以并集面积。两个完全相同的区域 IoU=1,完全不相交则 IoU=0,其余介于 0 与 1 之间。通常只考虑 IoU 超过某阈值的边界框;
  • Average Precision(AP):对某个类别 C,考察 Precision-Recall 曲线(随检测阈值 0→1 变化),其曲线下面积即为 AP。更精确地说,Recall 轴通常分成 10 份,Precision 在这些点上取平均:AP = (1/11) Σ Precision(Recall = i/10);
  • AP 与 IoU 的关系:只考虑 IoU 高于某阈值的检测。PASCAL VOC 通常取 IoU 阈值 0.5,而 COCO 对多个 IoU 阈值分别测 AP;
  • Mean Average Precision(mAP):目标检测的主指标,即 AP 在所有类别(有时也对多个 IoU 阈值)上的平均。

两大类检测算法

课程把目标检测算法分为两大类:

  1. 区域提议网络(Region Proposal Networks):R-CNN、Fast R-CNN、Faster R-CNN。核心思路是生成**感兴趣区域(ROI)**并对它们跑 CNN、寻找最大激活。这类似朴素方法,但 ROI 的生成更聪明;主要缺点是慢——因为需要对图像做多次 CNN 分类器传递。R-CNN 用 Selective Search 生成 ROI 的层级结构,经 CNN 特征提取器和 SVM 分类器判定类别,再用线性回归确定边界框坐标;
  2. 单次(One-pass)方法:YOLO、SSD、RetinaNet。这类架构把类别与 ROI 的预测放在一次前向传递中完成。

7. 语义分割:逐像素的分类

目标检测用边界框定位物体,但对某些任务我们需要更精确的物体定位——这就是分割。分割可视为像素分类:对图像的每一个像素预测其类别(背景也是类别之一)。两类主流算法:

  • 语义分割:只告诉像素类别,不区分同类中的不同物体;
  • 实例分割:把类别进一步细分为不同实例——对实例分割而言这些羊是不同对象,而对语义分割所有羊都属于同一个类。

编码器-解码器结构与专用损失

各种分割网络架构虽多,但结构相同,某种意义上类似前面学过的自编码器——不过目标不是解构原图,而是解构一个掩码(mask)。分割网络由两部分组成:

  • 编码器:从输入图像提取特征;
  • 解码器:把特征变换为掩码图像——尺寸与原图相同,通道数对应类别数。

损失函数的选择有讲究:经典自编码器度量两图相似度可用 MSE;但分割中目标掩码的每个像素代表类别编号(沿第三维做 one-hot 编码),因此要使用分类专用的损失——交叉熵损失,并对所有像素取平均;若掩码是二值的,则用二值交叉熵损失(BCE)。

实战:医学影像中的痣分割

本课把分割落到真实场景:训练网络在医学图像上识别人体痣(色素痣)。数据来源是 PH² 皮肤镜图像数据库——含 200 张、三个类别(典型痣、非典型痣、黑色素瘤)的图像,每张图带对应的勾勒痣轮廓的掩码。目标是从背景中分割出任何痣。动手实验见:

学习路径与配套资源

本章节的学习节奏是「一课一原理、一课一 Notebook」。每个子课程 README 均包含课前测验、课程正文、课后测验、挑战任务与自修材料;所有实验都提供 PyTorch 与 TensorFlow 双版本 Notebook,便于对照学习。各课作业(lab)从光流手势方向提取、迁移学习宠物分类到用自己的图像重训 GAN,层层递进,覆盖从经典图像处理到前沿生成式视觉的全链路能力。

建议按 06→12 的编号顺序推进:先建立图像操作手感,再理解卷积特征学习,接着用迁移学习解决标注数据稀缺问题,随后以自编码器进入无监督表示学习,以 GAN 进入生成式建模,最后掌握检测与分割这两类工业级视觉任务。每完成一课,都可以回到本节开头的概览图对照自己的知识地图,确认自己已经走到哪一步。

登录后查看全文
AI-For-Beginners