本节摘要:SOURCE 3.2:卷积核在邻域滑动。本节动手均值/高斯平滑、Sobel 梯度、拉普拉斯锐化,理解核大小与边缘响应。
filter2D 应用自定义核import cv2, numpy as np img = cv2.imread('gray.png', 0) kernel = np.ones((3,3), np.float32)/9 blur = cv2.filter2D(img, -1, kernel) sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) mag = cv2.magnitude(sobelx, sobely)
SOURCE Sobel X 核:
[-1 0 1] [-2 0 2] [-1 0 1]
lap = cv2.Laplacian(img, cv2.CV_64F) sharp = cv2.convertScaleAbs(img - 0.3*lap)
| 核 | 效果 |
|---|---|
| 均值/高斯 | 平滑去噪 |
| Sobel/Prewitt | 边缘 |
| Laplacian | 锐化 |

cv2.threshold 得粗边缘图⚠️ 常见坑:Sobel 输出 CV_64F 直接 imshow 全白 — 需 convertScaleAbs。
💡 关键直觉:卷积 = 局部线性组合 — 深度学习卷积层由此推广。
下一节 FFT 频域滤波。
空间域滤波的数学操作是卷积:一个核(核矩阵)在图像上逐像素滑动,每个位置做加权求和,输出该位置的响应。核决定了滤波的语义——全 1 的核求平均(均值滤波),中心权重大外围小的核是高斯滤波,[-1 0 1] 形式的核提取水平方向梯度。边界处理有四种常见策略:补零、镜像、复制边缘、截断,OpenCV 默认 BORDER_DEFAULT 是镜像式,做实验时如果发现边缘出现异常暗带,往往是边界策略与预期不符。
import cv2, numpy as np # 自定义核:垂直方向的边缘检测(Prewitt Y) k = np.array([[-1,-1,-1],[0,0,0],[1,1,1]], np.float32) edge_y = cv2.filter2D(img, cv2.CV_32F, k)
滤波核按用途分三类。平滑核(均值、高斯)让图像变糊,用于去噪和抑制细节;锐化核(拉普拉斯)提取二阶导数信息,原图减去拉普拉斯结果即锐化,让边缘更锐利;梯度核(Sobel、Prewitt、Scharr)提取一阶导数,响应强的位置就是边缘候选。理解"核的形状决定滤波语义"就能看懂任何空间滤波代码——看到核矩阵,心里就能推测它是在平滑、提边还是锐化。
高斯核由标准差 sigma 决定形状:sigma 越大,核中心权重相对越平,平滑越强。核大小 ksize 一般取 3×sigma 附近(覆盖约 99% 权重)。高斯滤波比均值滤波保边更好的原因在于权重递减——距离中心远的像素影响小。Sobel 核通常对图像先做高斯平滑(或核本身就含平滑权重),因此输出对噪声比纯差分稳定,这也是 Canny 边缘检测第一步先高斯平滑的原因。
空间滤波的核滑动,正是深度学习卷积层的原型。CNN 的卷积核也是局部加权和,区别在于核参数从手工设定变成数据学习,且多个核并行提取多种特征。理解传统滤波的"核大小、步长、边界"概念,再去看卷积网络的 kernel_size、padding、stride 参数,会发现是完全对应的。这也是本节被安排在深度学习章节之前的原因——它是理解 CNN 最直观的起点。
实验建议:把均值、高斯、Sobel、拉普拉斯四种核分别打印出来看形状,再各自对同一张图做滤波观察效果,最后用 filter2D 复现 cv2.blur 的结果验证理解。完成这个"核-效果"对照实验,本节的核心就真正掌握了。
锐化的原理补充一句:拉普拉斯是二阶导数,在平坦区域响应为零,在边缘两侧响应一正一负。原图减去拉普拉斯,相当于在边缘两侧做"亮更亮、暗更暗"的调整,视觉上边缘更鲜明。锐化过度会在边缘出现白边黑边的光晕,调整系数时要观察这一现象。
最后,输出 dtype 的坑再强调:Sobel 和拉普拉斯输出是带符号浮点(CV_64F),直接 imshow 会因负数被截断而全黑。转成绝对值再用 convertScaleAbs 归一化到 0-255,是标准处理,务必养成习惯。本节学完你应该能回答:均值与高斯的区别是什么?拉普拉斯为什么能锐化?Sobel 输出为什么是浮点?这三个问题对应"核形状、核语义、输出类型"三层理解,也是空间滤波的三个核心知识点。
补一个核的实现细节:高斯核可以用 cv2.getGaussianKernel 生成一维核,再与外积得到二维核;卷积核的归一化很重要——平滑核的系数总和应为 1,否则整图亮度会偏移。filter2D 默认不做归一化,均值核要自己除以 9,这是初学者常见的亮度变化 bug 来源。另外,滤波的核也可以分离成两个一维核(如高斯、Sobel 都是可分离的),先水平再垂直卷积能显著减少计算量,OpenCV 内部正是这么优化的。理解可分离卷积,对理解深度学习里的深度可分离卷积也很有帮助。