2.1 图像处理基础与传统特征


2.1 图像处理基础与传统特征

本节摘要:计算机视觉的第一步是把图像变成数字。本节从图像的数值表示出发,讲卷积操作的数学本质——它就是滑动窗口的点积,再讲滤波、边缘检测、形态学这些传统图像处理,最后落到 HOG、SIFT 这些手工特征。这些方法在深度学习时代用得少了,但面试高频追问,且它们背后的思想(梯度、尺度、局部性)正是理解 CNN 特征的钥匙。理解了 SIFT 的尺度不变性,再看 CNN 的多尺度特征金字塔会豁然开朗。

学习目标

阅读完本节,你应当能够:

  1. 说清 RGB、HSV、灰度三种色彩空间的区别和各自适用场景
  2. 推演卷积操作如何滑动窗口计算,解释步长、填充对输出尺寸的影响
  3. 讲清高斯滤波、中值滤波去噪机理的差异,以及为什么中值滤波对椒盐噪声特别有效
  4. 解释 Sobel 和 Canny 边缘检测的原理,说清 Canny 的四个步骤
  5. 说清 HOG 特征的计算流程及其在行人检测里的应用
  6. 讲清 SIFT 的尺度不变性和旋转不变性是如何实现的
  7. 解释传统手工特征与 CNN 学习特征的优劣对比

为什么面试官还在考传统特征

很多刚接触 CV 的人有个误区:以为深度学习出现后,传统图像处理就没用了。这是个危险的认知,因为它让你跳过了"图像是什么"这个最基础的问题。

真实的痛点是这样的:深度学习模型是个黑盒,输入什么它就学什么,但模型不会告诉你"这张图太暗了""这块区域的梯度方向很乱"。当你需要做图像预处理(去噪、对齐、增强)、当你需要可解释的特征(医疗、工业检测的合规要求)、当你的数据量小到训不动深度模型——传统图像处理就是你唯一可靠的工具。面试官问 SIFT,不是要你背流程,而是考察你是否理解"特征是什么"这个本质。

所以本节的组织逻辑是:先把图像还原成数字矩阵,让你看到"一张猫的图片在计算机里就是 224×224×3 的整数",再讲卷积操作怎么对这种矩阵做局部运算,最后讲传统方法如何从这种矩阵里提取有意义的特征(边缘、角点、梯度方向直方图)。这些思想在 CNN 里被自动学习了,但理解手工提取的过程,能让你讲清 CNN 学到的特征"是什么意思"。

二、核心原理

2.1 图像的数值表示

一张彩色图像在计算机里是三维张量:高 × 宽 × 通道。最常见的是 RGB 三通道,每个像素每个通道用 0–255 的整数表示(8 位)或 0–1 的浮点数。灰度图是二维张量(高 × 宽),每个像素只有一个值表示亮度。

色彩空间 是描述颜色的不同坐标系统:

色彩空间 分量 适用场景
RGB 红、绿、蓝 显示器原生,但分量高度相关
HSV 色相、饱和度、明度 颜色分割、追踪(色相和亮度分离)
灰度 单通道亮度 计算量减半、边缘检测前置
LAB 亮度、a、b 感知均匀,颜色差异量化

💡 关键直觉:很多 CV 任务(边缘检测、HOG)只需要灰度图,因为颜色信息对"形状"的判断贡献有限。深度学习里第一层卷积自己学到了从 RGB 提特征的组合,但理解灰度图的处理,能让你讲清 CNN 第一层到底在学什么——它学到的就是各种方向的边缘和颜色斑块。

2.2 卷积操作:滑动窗口的点积

卷积是图像处理最基础的操作。它的本质是把一个小矩阵(卷积核)在图像上滑动,每个位置算一次点积,输出一个新的矩阵。

def conv2d(image, kernel, stride=1, padding=0): # 简化的二维卷积,假设单通道 if padding > 0: image = np.pad(image, padding) h, w = image.shape kh, kw = kernel.shape out_h = (h - kh) // stride + 1 out_w = (w - kw) // stride + 1 out = np.zeros((out_h, out_w)) for i in range(0, out_h): for j in range(0, out_w): region = image[i*stride:i*stride+kh, j*stride:j*stride+kw] out[i, j] = np.sum(region * kernel) return out

输出尺寸的公式要记住:\text{out} = \lfloor \frac{\text{in} - \text{kernel} + 2 \times \text{padding}}{\text{stride}} \rfloor + 1。面试白板常考这个。

池化 是另一种滑动窗口操作,但它不做点积,而是取最大值(最大池化)或平均值(平均池化)。池化的作用是降采样(减小尺寸)和提供一定的平移不变性(小幅平移不改变 max 的结果)。

2.3 滤波:图像去噪

图像传感器的噪声让原始图像总有颗粒感。滤波是用卷积或邻域操作平滑这些噪声。

滤波方法 原理 适用噪声 副作用
均值滤波 邻域平均 高斯噪声 模糊边缘
高斯滤波 加权平均(中心权重大) 高斯噪声 轻微模糊
中值滤波 邻域取中位数 椒盐噪声 边缘保留好
双边滤波 同时考虑空间和像素值距离 保边去噪 计算量大

⚠️ 常见坑:很多人以为高斯滤波万能,遇到椒盐噪声也用高斯,结果越滤越糟。椒盐噪声是极端离群点(纯黑或纯白像素),均值和高斯会被离群点带偏,只有中值滤波(取中位数,离群点直接被排除)能有效去除。选滤波方法要先看噪声类型。

2.4 边缘检测:梯度与极值

边缘是图像里亮度剧烈变化的地方。检测边缘的本质是求梯度——亮度变化最快的地方梯度最大。

Sobel 用两个 3×3 卷积核分别检测水平方向和垂直方向的梯度,合起来得到梯度幅值和方向。简单但噪声敏感。

Canny 是更完整的边缘检测流水线,分四步:

双阈值是 Canny 的精髓:高阈值确认强边缘,低阈值连接弱边缘(只有和强边缘相连的弱边缘才保留),这样能滤掉大部分噪声响应,同时保持边缘连续。

2.5 HOG 与 SIFT:手工特征的巅峰

在深度学习统治 CV 之前,HOG 和 SIFT 是特征工程的代表。

HOG(方向梯度直方图) 把图像分成小格,每个格统计该区域内像素的梯度方向分布,得到一个直方图作为特征。它的核心思想是局部物体的外观和形状可以通过梯度方向分布描述,而不需要精确知道梯度位置。HOG 配合 SVM 是经典的行人检测方案。

SIFT(尺度不变特征变换) 解决了一个更难的问题:在不同尺度、旋转、光照下找到同一个特征点。它的四步流程是:尺度空间极值检测(用高斯金字塔找候选点)、关键点定位(亚像素精化)、方向分配(让特征对旋转不变)、描述子生成(128 维向量描述局部梯度)。

特征 不变性 维度 典型应用
HOG 光照、小幅平移 几百到几千维 行人检测
SIFT 尺度、旋转、光照 128 维/点 图像拼接、匹配
SURF 同 SIFT 但更快 64 维 实时匹配
ORB 旋转、部分尺度 256 位二进制 实时 SLAM

💡 关键直觉:SIFT 的"尺度空间"思想被 CNN 继承了——CNN 的多层特征金字塔本质上就是不同感受野对应的尺度。理解 SIFT 的尺度不变性,再读 FPN(特征金字塔网络)会顺理成章。

三、工程实践要点

3.1 数据增强:让小数据变大的关键

CV 任务里数据增强几乎是标配,尤其在数据量有限时。增强分两类:几何增强(翻转、旋转、缩放、裁剪)和像素增强(亮度、对比度、颜色抖动、加噪)。

def augment(image, label): # 几何增强 if np.random.rand() > 0.5: image = np.fliplr(image) # 水平翻转 angle = np.random.uniform(-15, 15) image = rotate(image, angle) # 像素增强 image = adjust_brightness(image, np.random.uniform(0.8, 1.2)) return image, label

⚠️ 常见坑:不是所有任务都能任意翻转。车牌识别不能上下翻转(6 和 9 会混淆),医学影像左右翻转可能改变病灶语义。增强策略要结合任务语义,不能盲目套用。

3.2 传统特征 vs 深度特征的取舍

维度 传统特征(HOG/SIFT) 深度特征(CNN)
数据需求 小数据可用 需要大量数据
计算资源 低,CPU 可跑 高,需要 GPU
可解释性 强,特征语义清晰 弱,黑盒
性能上限 有限
部署成本 高(模型大)

实战选型:数据量小(< 1000 张)、计算资源受限、需要可解释性(医疗、工业)的场景,传统方法仍是合理选择。否则深度学习几乎总是更优。

3.3 预处理流水线的标准步骤

一个典型的 CV 预处理流水线:读图 → 转 RGB(防止 OpenCV 默认 BGR 顺序坑)→ Resize(保持长宽比 + padding 或裁剪)→ 归一化(减均值除标准差)→ 增强(仅训练时)。

def preprocess(image_path, target_size=(224, 224), training=False): img = cv2.imread(image_path) # BGR img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转 RGB img = letterbox_resize(img, target_size) # 保持长宽比 img = img.astype(np.float32) / 255.0 # 归一化到 [0,1] img = (img - mean) / std # 标准化 if training: img = augment(img) return img

💡 关键直觉:减均值除标准差的均值和标准差,必须用训练集的统计量,不能用单张图自己的。ImageNet 预训练模型用 ImageNet 的均值标准差,自训模型要用自己训练集的。这个细节错了,模型精度会莫名下降几个点。

本节要点回顾

  • 图像是数字矩阵,RGB 三通道、灰度单通道;HSV 把色相和亮度分离,适合颜色任务。
  • 卷积是滑动窗口点积,输出尺寸公式 \lfloor \frac{in - k + 2p}{s} \rfloor + 1 必须记牢。
  • 滤波要先看噪声类型:高斯噪声用高斯滤波,椒盐噪声用中值滤波,选错越滤越糟。
  • Canny 边缘检测四步:高斯去噪、Sobel 求梯度、非极大值抑制、双阈值连接。
  • HOG 统计梯度方向直方图配 SVM 做行人检测,SIFT 实现尺度旋转不变用于图像匹配。
  • 传统特征胜在可解释和小数据,深度特征胜在性能上限;医疗、工业等场景仍用传统方法。
  • 预处理均值标准差要用训练集统计量,OpenCV 默认 BGR 顺序是经典坑。

下一节我们进入 CNN 的演进史,看 ResNet、YOLO、U-Net 这些经典模型如何针对不同任务演化,以及它们解决了什么瓶颈。

四、传统特征的现代回声

这部分内容在面试里最有区分度的问题不是"HOG 怎么算",而是"深度学习时代为什么还要学传统特征"。这里给出三层答案。

第一层是历史逻辑:深度网络的很多设计直接继承自传统方法。SIFT 的尺度空间理论(高斯差分金字塔)和 CNN 的多尺度特征金字塔(FPN)是同一个思想的两代实现;HOG 的梯度统计直方图,本质上就是手工版的卷积特征。理解传统方法,才能看懂深度网络"自动化"掉的到底是什么——是特征设计这件事,而不是特征本身。

第二层是工程现实:资源极度受限的场景里传统方法仍是首选。工业质检里有些划痕检测,几个方向的 Gabor 滤波加阈值就够,上深度模型反而增加部署与维护成本;嵌入式设备的 OCR 预处理、老照片修复的边缘引导,传统滤波依然在生产线里跑着。面试官问你"什么时候不用深度学习",答这类场景能体现工程判断力。

第三层是能力互补:传统特征常作为深度模型的补充信号。行人检测的经典做法是把 HOG 特征和 CNN 特征拼接;图像检索系统里,颜色直方图做粗筛、深度向量做精排,两层漏斗比单一方案又快又准。把传统方法定位成"工具箱里的扳手"而不是"被淘汰的遗物",是面试里体现成熟度的一个细节。

顺带一个高频计算题:对 64×64 的图做 3×3 卷积(步长 1、不填充),输出尺寸是多少?答案是 62×62,公式是输出等于输入减核大小加一。再追问:同样参数下膨胀卷积(膨胀率 2)的输出是多少?58×58,等效核大小变成 5。这类手算题在 CV 面试里出现率极高,务必练到条件反射。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U