查看全课大纲(第 9 / 93 节)
- 1.计算机视觉概述
- 2.计算机视觉应用场景
- 3.困难与挑战
- 4.开源库介绍
- 5.图像显示与存储
- 6.CLAHE
- 7.腐蚀膨胀与开闭运算
- 8.滤波与边缘填充
- 9.各种滤波
- 10.图像金字塔
- 11.傅里叶变换
- 12.短时傅里叶变换与小波变换
- 13.颜色特征与颜色直方图
- 14.几何特征_边缘
- 15.几何特征-角点与斑点
- 16.局部特征-SIFT特征描述子
- 17.局部特征-SURF特征描述子
- 18.局部特征-ORB特征描述子
- 19.其他特征描述子
- 20.传统图像分割技术
- 21.GraphCut
- 22.GrabCut
- 23.人脸检测的传统方法
- 24.行人检测的传统方法HOG+SVM
- 25.行人检测DPM
- 26.人工神经网络的架构
- 27.目标函数与梯度下降
- 28.误差反向传播
- 29.可手算的神经网络
- 30.改进目标函数与克服梯度消散
- 31.神经网络之传统神经网络与深度网络的差异
- 32.各种梯度下降算法
- 33.如何选择合适的梯度下降算法
- 34.避免过适应
- 35.CNN的架构
- 36.CNN的误差反向传播_卷积层
- 37.CNN的误差反向传播_池化层
- 38.分类所用的数据集
- 39.Alexnet详解
- 40.VGG详解
- 41.GoogLeNet_v1
- 42.BatchNormalization
- 43.GoogLeNet_v3v4
- 44.ResNet
- 45.ResNeXt
- 46.CNN设计准则
- 47.图像检索与推土机距离
- 48.基于颜色相似性
- 49.基于形状相似性
- 50.基于纹理相似性
- 51.基于局部特征相似性
- 52.DL的二值哈希编码
- 53.高维空间中检索KDTree
- 54.高维空间中检索LSH
- 55.目标识别任务综述
- 56.RCNN
- 57.SPP-Net
- 58.Fast R-CNN
- 59.Faster R-CNN
- 60.R-CNN系列模型回顾
- 61.R-FCN的设计思路
- 62.R-FCN的实现
- 63.YOLOv1
- 64.YOLOv2_9000
- 65.YOLOv3
- 66.图像分割应用场景与数据集
- 67.上采样的实现方式
- 68.FCN网络架构的由来
- 69.FCN构建细节
- 70.DeepLabv1
- 71.CRF
- 72.DeepLabv2
- 73.DeepLabv3
- 74.特定的医学影像分割任务
- 75.U-Net
- 76.3D U-Net
- 77.V-Net
- 78.DenseNet
- 79.病理切片分析任务及数据集
- 80.病理切片分析
- 81.图说任务及其传统处理方法
- 82.深度语言模型与RNN
- 83.LSTM及其变种
- 84.NIC模型
- 85.SAT模型
- 86.图说的性能指标
- 87.判别模型与生成模型
- 88.KL散度与JS散度
- 89.VAE
- 90.GAN的基本原理
- 91.DCGAN与CGAN
- 92.Wasserstein GAN
- 93.SRGAN
各种滤波
小象实战讲义 · 基于深度学习的计算机视觉
在图像处理中,滤波是一种基础且强大的操作,它通过局部邻域计算来改变或提取图像信息。本节我们将系统学习多种经典滤波方法,理解它们如何实现图像平滑、去噪、边缘检测和锐化等核心功能。掌握这些传统滤波操作,不仅是理解后续深度学习卷积操作的基础,也是构建完整计算机视觉知识体系的关键一环。
💡 核心导读
- 滤波与卷积的同一性:理解传统滤波与深度学习卷积在操作本质上的高度一致。
- 平滑滤波三剑客:掌握均值滤波、中值滤波和高斯滤波的原理、效果差异及适用场景。
- 边缘检测利器:学习 Prewitt、Sobel 和 Laplacian 等梯度滤波算子如何捕捉图像边缘。
- 计算优化技巧:了解将二维高斯卷积分解为两个一维卷积以大幅降低计算量的方法。
滤波与卷积:同一本质的两种表述
在课程开始,我们需要明确一个核心概念:这里提到的“滤波”与后续深度学习中将介绍的“卷积”,在操作上都是基于权重模板的滑动窗口加权求和。严格来说,图像处理中的“相关”与“卷积”相差一次核翻转;但本节使用的均值核、高斯核是(近似)对称核,相关与卷积结果一致;Prewitt/Sobel 核沿梯度方向是反对称的,二者只差一个符号,而在边缘检测中我们只关心响应的幅值,因此下面不再区分这两个词。
它们都是基于一个称为“卷积核”(Kernel)或“滤波器”(Filter)的权重模板,在图像上滑动并进行局部加权求和的过程。其数学形式可以统一表示为:
其中:
- 是输出图像中像素的位置坐标。
- 是卷积核内部的相对坐标,通常以核中心为原点 。
- 是卷积核在位置 上的权重参数。
- 是输入图像中与权重 对应的像素值。
- 是经过滤波/卷积后,输出图像在 位置的结果值。
两者的区别更多在于语境和目标:
- 传统图像处理中,我们称之为滤波,目的是进行图像预处理,如去噪、平滑、边缘检测等。滤波器(如高斯核、Sobel核)是人工设计、具有明确物理或数学意义的固定模板。
- 深度学习中,我们称之为卷积,其卷积核的权重是通过数据驱动、反向传播算法自动学习得到的,目的是提取能够有效完成特定任务(如分类、检测)的层次化特征。
理解这种同一性,能帮助我们将传统视觉的直觉与深度学习的机制顺畅地连接起来。
平滑滤波:从模糊到智能平滑
平滑滤波的主要目的是抑制噪声、模糊细节或进行图像预处理。我们将介绍三种经典的平滑滤波方法。
均值滤波:最简单的模糊
均值滤波是最直观的平滑方法。它使用一个所有元素值相等的卷积核,对邻域内所有像素取算术平均值作为中心像素的新值。
一个标准的 均值滤波核如下:
其操作是:以目标像素为中心的 邻域内,9个像素值相加,然后乘以 (即取平均),结果作为该目标像素的新值。
效果与局限:
- 作用:实现图像平滑。但更准确地说,其效果是强烈的模糊,而非精细的平滑。
- 缺点:
- 去噪效果差:对于明显的噪声点(如椒盐噪声),取平均后噪声值被“稀释”到邻域,但并未被移除,图像依然留有污点。
- 边缘破坏严重:在物体边缘,一侧的像素值与另一侧差异巨大。取平均会混合两侧的值,导致边缘变得模糊、扩散,丢失清晰的轮廓信息。
为什么还要学它? 均值滤波因其极致的简单性,是理解滤波/卷积操作最理想的起点。它引出了核心问题:如何设计更好的滤波器,在平滑的同时更好地保护边缘信息?
中值滤波:椒盐噪声的克星
中值滤波是一种非线性滤波方法。它不再进行加权平均,而是对邻域内的像素值进行排序,然后取中位数作为中心像素的新值。
操作原理:
- 选取以目标像素为中心的邻域窗口(如 )。
- 将该窗口内所有像素的灰度值从小到大排序。
- 取排序后位于中间位置的值(中位数)作为输出。
import numpy as np
# 模拟一个3x3的图像块,其中包含一个极端的椒盐噪声点(255)
image_patch = np.array([
[120, 130, 110],
[125, 255, 115], # 中心点是一个椒盐噪声(白色点)
[118, 122, 128]
], dtype=np.uint8)
print("原始 3x3 图像块:")
print(image_patch)
print()
# 手动实现中值滤波:展平、排序、取中值
flat_values = image_patch.flatten()
sorted_values = np.sort(flat_values)
median_value = sorted_values[len(sorted_values) // 2] # 取中间索引的值
print(f"展平后像素值: {flat_values}")
print(f"排序后像素值: {sorted_values}")
print(f"中值: {median_value}")原始 3x3 图像块:
[[120 130 110]
[125 255 115]
[118 122 128]]
展平后像素值: [120 130 110 125 255 115 118 122 128]
排序后像素值: [110 115 118 120 122 125 128 130 255]
中值: 122优势分析:
- 去除椒盐噪声:椒盐噪声表现为极黑(0)或极白(255)的孤立点。在排序中,这些极端值会落在序列的首或尾,取中位数时自然被排除,从而被有效去除。
- 保护边缘:在边缘区域,像素值发生跃变。中值滤波取的是邻域内排序中间的值,这个值更可能来自边缘的某一侧,而不是两侧的混合平均值,因此能较好地保持边缘的锐利度。
- 平滑区域:在平坦区域,像素值相近,中位数与平均值接近,平滑效果自然。
因此,中值滤波在去除椒盐噪声方面效果显著,同时边缘保持能力远优于均值滤波。
高斯滤波:符合人眼感知的平滑
高斯滤波是一种加权平均滤波,其权重分布符合二维高斯函数(正态分布)。它模拟了人眼的视觉特性:对注视中心区域敏感,对周边区域敏感度随距离增加而逐渐降低。
高斯核函数: 二维高斯函数的公式为:
其中:
- 是相对于核中心的坐标。
- 是标准差,控制高斯分布的“胖瘦”程度。
- 核内所有权重之和为1。
关键参数 的影响:
- 小:高斯分布“又瘦又高”,权重高度集中在中心点。滤波效果是轻微的平滑,图像细节保留较多。
- 大:高斯分布“又扁又宽”,权重分布更分散。滤波效果更强,更接近均值滤波的模糊效果,但过渡更自然。
与均值滤波的本质区别: 均值滤波对所有邻域像素赋予相同权重,是“一视同仁”的模糊。 高斯滤波对中心像素赋予最高权重,权重随距离增加而指数衰减。这意味着中心像素自身对结果贡献最大,邻近像素贡献次之,远处像素贡献微乎其微。因此,高斯滤波能实现真正的、自然的平滑,而不是生硬的模糊。
import cv2
import numpy as np
# 创建一个简单的6x6测试图像,包含两个不同灰度的区域和一个噪声点
test_image = np.array([
[9, 9, 9, 18, 18, 18],
[9, 9, 9, 18, 18, 18],
[9, 9, 9, 18, 18, 18],
[18, 18, 18, 9, 9, 9],
[18, 18, 18, 9, 9, 9],
[18, 18, 255, 9, 9, 9] # 加入一个椒盐噪声点255
], dtype=np.uint8)
print("原始测试图像:")
print(test_image)
print()
# 应用高斯滤波 (3x3核, sigma=1)
# 转为 float32 以保留小数精度(GaussianBlur 本身也支持 uint8 输入)
gaussian_blurred = cv2.GaussianBlur(test_image.astype(np.float32), (3, 3), sigmaX=1)
print("高斯滤波后图像 (取整):")
print(gaussian_blurred.astype(np.int32))
print()
# 应用中值滤波 (3x3核)
median_blurred = cv2.medianBlur(test_image, 3)
print("中值滤波后图像:")
print(median_blurred)原始测试图像:
[[ 9 9 9 18 18 18]
[ 9 9 9 18 18 18]
[ 9 9 9 18 18 18]
[ 18 18 18 9 9 9]
[ 18 18 18 9 9 9]
[ 18 18 255 9 9 9]]
高斯滤波后图像 (取整):
[[ 9 9 11 15 18 18]
[ 9 9 11 15 18 18]
[11 11 12 14 15 15]
[15 15 14 12 11 11]
[18 35 44 29 9 9]
[18 47 63 40 9 9]]
中值滤波后图像:
[[ 9 9 9 18 18 18]
[ 9 9 9 18 18 18]
[ 9 9 9 18 18 18]
[18 18 18 9 9 9]
[18 18 18 9 9 9]
[18 18 18 9 9 9]]观察结果:
- 高斯滤波:平滑了区域内部,边缘处产生了渐变过渡(如左上区域到右上区域)。对于噪声点(255),它被“平均化”到周围,该位置的值从255降到了约63,但并未完全消失,且影响了周围一片区域。
- 中值滤波:完美地去除了孤立的椒盐噪声点(255),将其恢复为周围像素的中值18。同时,不同灰度区域之间的边缘保持得非常锐利,没有产生模糊。
计算优化:二维高斯核的分解
当使用较大的卷积核(如 , )时,二维卷积的计算量会急剧增加。对于一个 的核,每个输出像素需要进行 次乘加运算。
分解技巧: 一个二维高斯核可以被分离为两个一维高斯核的外积。即:
例如,一个近似的 高斯核 可以分解为: 列向量 与行向量 的乘积。
计算量对比:
- 原始 2D 卷积: 次运算。
- 分解后的 2 次 1D 卷积:先进行垂直方向的 1D 卷积( 次运算),再进行水平方向的 1D 卷积( 次运算),总计 次运算。
当 较大时,计算量节省非常显著(例如 , vs )。这种优化思想在深度学习卷积网络的优化中也经常被采用。
梯度滤波:捕捉图像的边缘
边缘是图像中像素值发生剧烈变化的地方,是物体识别的重要特征。梯度滤波通过计算像素邻域的灰度变化来检测边缘。
Prewitt 滤波器
Prewitt 滤波器使用两个核分别检测水平和垂直方向的梯度。
- 水平梯度核(检测垂直边缘):
- 垂直梯度核(检测水平边缘):
工作原理: 以水平梯度核为例。当它滑动到图像区域时:
- 如果该区域左右两侧灰度相同(如
[100, 100, 100]),则计算结果为 ,响应最小,不是边缘。 - 如果该区域左侧暗、右侧亮(如
[50, 100, 150]),则计算结果为 ,响应很大,表明存在一个垂直边缘。 垂直梯度核原理类似,它响应的是垂直方向(上下)的灰度变化,因此用来检测水平边缘。
Sobel 滤波器
Sobel 滤波器是 Prewitt 的改进版,它在中心行(或列)赋予了更高的权重(2倍),相当于在梯度计算前先进行了一个轻微的高斯平滑,对噪声的敏感性略低于 Prewitt。
- 水平梯度核:
- 垂直梯度核:
Laplacian 滤波器:二阶微分与锐化
Laplacian 滤波器基于二阶微分,用于检测图像中的“团块”(Blob)和边缘。一阶导数的极值点对应边缘,而二阶导数的过零点也对应边缘,并且对灰度阶跃变化更敏感。
Laplacian 算子: 二维拉普拉斯算子定义为:
其离散近似模板有多种形式,例如:
- 4邻域:
- 8邻域:
作用:
- 团块检测:如果中心点像素值显著高于或低于周围所有点,Laplacian 响应会很强,这对应一个团块(斑点或角点)。
- 边缘检测:在像素值快速变化的边缘区域,Laplacian 响应也会很明显。
- 图像锐化:这是 Laplacian 滤波器的一个重要应用。锐化的原理是增强图像中的高频成分(边缘和细节)。可以通过从原始图像中减去其拉普拉斯变换结果来实现(因为拉普拉斯结果突出了边缘和细节):
锐化图像 = 原始图像 - Laplacian(原始图像)这相当于使用了一个锐化卷积核,例如:。该核中心为强正值,周围为负值,能强化与众不同的点(边缘),削弱平坦区域。
import cv2
import numpy as np
# 创建一个有清晰边缘的测试图像
sharp_edge = np.zeros((6, 6), dtype=np.uint8)
sharp_edge[:, 3:] = 150 # 右半部分设置为150,形成垂直边缘
print("原始图像(清晰边缘):")
print(sharp_edge)
print()
# 使用Sobel算子计算x方向梯度(检测垂直边缘)
sobel_x = cv2.Sobel(sharp_edge, cv2.CV_32F, 1, 0, ksize=3)
print("Sobel X方向梯度 (检测垂直边缘):")
# 取绝对值并转换为整数显示,突出边缘响应
print(np.abs(sobel_x).astype(np.int32))
print()
# 使用Laplacian算子
laplacian = cv2.Laplacian(sharp_edge, cv2.CV_32F, ksize=3)
print("Laplacian 结果:")
print(laplacian.astype(np.int32))
print()
# 使用一个锐化核进行滤波
sharpen_kernel = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]], dtype=np.float32)
sharpened = cv2.filter2D(sharp_edge.astype(np.float32), -1, sharpen_kernel)
print("锐化后图像 (取整):")
print(sharpened.astype(np.int32))原始图像(清晰边缘):
[[ 0 0 0 150 150 150]
[ 0 0 0 150 150 150]
[ 0 0 0 150 150 150]
[ 0 0 0 150 150 150]
[ 0 0 0 150 150 150]
[ 0 0 0 150 150 150]]
Sobel X方向梯度 (检测垂直边缘):
[[ 0 0 600 600 0 0]
[ 0 0 600 600 0 0]
[ 0 0 600 600 0 0]
[ 0 0 600 600 0 0]
[ 0 0 600 600 0 0]
[ 0 0 600 600 0 0]]
Laplacian 结果:
[[ 0 0 600 -600 0 0]
[ 0 0 600 -600 0 0]
[ 0 0 600 -600 0 0]
[ 0 0 600 -600 0 0]
[ 0 0 600 -600 0 0]
[ 0 0 600 -600 0 0]]
锐化后图像 (取整):
[[ 0 0 -150 300 150 150]
[ 0 0 -150 300 150 150]
[ 0 0 -150 300 150 150]
[ 0 0 -150 300 150 150]
[ 0 0 -150 300 150 150]
[ 0 0 -150 300 150 150]]结果分析:
- Sobel:在灰度从0跳变到150的垂直边缘处(第2、3列之间),产生了强烈的梯度响应(值600)。
- Laplacian:在边缘的两侧(跳变发生处)分别产生了正(600)和负(-600)的响应,这是二阶微分的特征。
- 锐化:右侧边缘像素由150变为300,左侧平坦区由0变为-150(负值在正常显示时会被截断到0),边缘两侧的对比被拉大,因此看起来更锐利。
📝 动手练一练
- 概念辨析:均值滤波、中值滤波和高斯滤波都可以用于图像平滑,但它们处理噪声和保护边缘的策略截然不同。请简述它们各自的核心原理,并说明哪种滤波最适合去除椒盐噪声,哪种最能保护图像边缘。
👉 点击查看参考答案
- 均值滤波:线性操作。对邻域内所有像素取算术平均值。它平等对待所有像素,导致噪声被平均化但未消除,边缘被严重模糊。
- 中值滤波:非线性操作。对邻域内像素值排序并取中位数。椒盐噪声(极值点)在排序中会落在序列两端,取中位数时被排除,因此最适合去除椒盐噪声。同时,取中值更可能保留边缘某一侧的值,因此保护边缘能力较强。
- 高斯滤波:线性加权平均。权重按二维高斯分布分配,中心权重最高,向外衰减。它能实现自然的平滑,对高斯噪声效果好。由于中心权重高,对边缘的模糊程度介于均值和中值之间,但比均值滤波能更好地保持边缘过渡。
结论:中值滤波最适合去除椒盐噪声,并且在三种平滑滤波中保护边缘的能力通常最好。
- 手动计算:假设有一个 的图像块
I和一个 Prewitt 垂直梯度核K,如下所示。请手动计算卷积结果h[1,1](即中心点的输出值)。这能帮助你直观理解梯度滤波如何响应边缘。I = [[10, 10, 10], [20, 20, 20], [30, 30, 30]] K = [[-1, -1, -1], [ 0, 0, 0], [ 1, 1, 1]]
👉 点击查看参考答案
卷积计算 h[1,1] 是将核 K 的中心 (0,0) 对准 I 的 (1,1) 位置,然后对应位置相乘后求和。
对齐后:
I 区域 (以(1,1)为中心的3x3邻域) 就是 I 本身:
[10, 10, 10]
[20, 20, 20]
[30, 30, 30]
核 K:
[-1, -1, -1]
[ 0, 0, 0]
[ 1, 1, 1]对应位置相乘: 第一行:10*(-1) + 10*(-1) + 10*(-1) = -30 第二行:200 + 200 + 200 = 0 第三行:301 + 301 + 301 = 90
求和:(-30) + 0 + 90 = 60
结果分析:输出值 60 是一个较大的正数,表明在图像 I 的 (1,1) 点处存在一个强烈的垂直梯度(因为使用的是垂直梯度核,它检测水平边缘)。这正对应了图像 I 中从上到下(10 -> 20 -> 30)的明显灰度变化,即一个水平方向的边缘(灰度在垂直方向变化)。
本章小结
本节我们深入探讨了图像处理中一系列经典的滤波操作,它们是计算机视觉的基石。
- 统一本质:传统滤波与深度学习卷积在数学操作上是一致的,都是基于卷积核的局部加权求和。
- 平滑去噪:学习了均值滤波(简单但模糊)、中值滤波(非线性,擅长去除椒盐噪声并保护边缘)和高斯滤波(加权平均,模拟人眼,实现自然平滑)的原理与效果。
- 边缘检测:掌握了 Prewitt、Sobel(一阶梯度)和 Laplacian(二阶微分)等滤波器如何通过检测像素值的突变来捕捉图像边缘,并了解了 Laplacian 在图像锐化中的应用。
- 优化思想:认识到将二维高斯卷积分解为两个一维卷积可以显著降低计算量,这种思想在后续的深度学习优化中也会见到。
这些手工设计的滤波器虽然功能明确,但其表达能力有限,且需要针对不同任务精心选择和调整参数。在接下来的深度学习中,我们将看到如何通过数据驱动的方式,让网络自动学习出最适合特定任务的“滤波器”(卷积核),从而获得更强大、更灵活的视觉特征提取能力。
📋 行动清单
- 在代码编辑器中,尝试用 OpenCV 的
cv2.filter2D函数,对一张小灰度图(可自建矩阵)分别应用均值、高斯、Sobel 核,观察输出矩阵的变化。 - 思考:如果一张图像同时存在高斯噪声和椒盐噪声,仅使用本节介绍的一种滤波方法,能否完美去除?如果不能,可能的处理思路是什么?
- 回顾拉普拉斯锐化的公式(
原始图像 - Laplacian(图像)),理解为什么“减去”边缘信息反而能使图像看起来更锐利。
—— 小象教研组