卷积图像处理的线性代数诠释
前言
决定现在开始先学习一些卷积操作,为后期的卷积神经网络的学习打牢基本功。
还要抽时间搞王俊刚老师的课题 《随机矩阵理论视角下的神经网络训练动力学实验研究》 感觉很高大上,但又不难理解,很有意思。
卷积核
构造kernel
kernel = np.ones((3,3), np.float32) / 9
数据上,生成了一个全为$1\over9$的$3\times3$矩阵
\[\frac{1}{9} \begin{pmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{pmatrix}\]这是一个 均值滤波核(Mean Filter)
输出像素 = 周围 3×3 像素的平均值
卷积核可以自己构造,或通过机器学习(如反向传播)来学习参数。
经典的卷积核包括:
低通卷积核(平滑处理核)
- 均值滤波
- 高斯滤波
高通卷积核(边缘检测核)
一阶导数
- Sobel 算子
竖向边缘检测 \(\begin{bmatrix} -1& 0& +1\\ -2& 0& +2\\ -1& 0& +1 \end{bmatrix}\)
横向边缘检测 \(\begin{bmatrix} -1& -2& -1\\ 0& 0& 0\\ +1& +2& +1 \end{bmatrix}\)
本质是对像素值的离散一阶导数
简化后变为Prewitt 算子
\[\begin{bmatrix} -1& 0& +1\\ -1& 0& +1\\ -1& 0& +1 \end{bmatrix}\]改进核为Scharr 算子
\[\begin{bmatrix} -3& 0& +3\\ -10& 0& +10\\ -3& 0& +3 \end{bmatrix}\]OpenCV 推荐小核用 Scharr
二阶导数
- Laplacian(拉普拉斯算子)
4邻域版本
\[\begin{bmatrix} 0& -1& 0\\ -1& +4& -1\\ 0& -1& 0 \end{bmatrix}\]8邻域版本
\[\begin{bmatrix} -1& -1& -1\\ -1& +8& -1\\ -1& -1& -1 \end{bmatrix}\]对噪声非常敏感,通常先高斯平滑
- LoG(Laplacian of Gaussian)(高斯后拉普拉斯核)
锐化(高通增强)
- 锐化核(Sharpen)
- Unsharp Mask(反遮罩)
等价形式是原图 − 模糊图
其他核
- Gabor 滤波器 ⭐⭐⭐
形式:
g(x,y) = exp(-(x²+y²)/2σ²) · cos(2πfx)
特点:
-
方向性
-
频率选择性
-
类似 V1 视觉皮层感受野
-
CNN 第一层学到的核 ≈ Gabor
示例代码
def smooth_filter(self):
img = cv2.imread(self.imagePath)
kernel = np.ones((3,3), np.float32) / 9
det = cv2.filter2D(img, -1, kernel)
※线性代数角度的卷积操作本质
前言
首先,线性代数中,矩阵一词是有精确定义的:
矩阵 = 表示“线性映射”的对象
而图像不是线性映射,而是被作用的对象,所以图像需要先被拉成向量,再作用线性变换(即矩阵变换)
一个非常关键的区分(请记住)
| 角色 | 在线代中是什么 |
|---|---|
| 图像 | 向量(元素是像素) |
| 卷积 / 滤波 | 线性变换 |
| 卷积核 | 变换的参数 |
| 卷积矩阵 | 表示该变换的矩阵 |
卷积运算是线性运算,符合上述定义。
那么,假设:
- 图像是 5×5(25 个像素)
- 使用 3×3 卷积核
- 输出仍然是 25 个像素
那么一定存在一个 $25 × 25$ 的矩阵 $A$ ,使得:
\[y = Ax\]其中:
- x:原图拉直后的向量
- y:卷积结果拉直后的向量
所以,卷积 ≡ 某个固定矩阵乘以图像向量
譬如,一个$5\times5$的图像,因为基有25个元素,所以自由度是25,是25维的向量。有一个卷积核生成的$25\times 25$的卷积矩阵 $A$,作用于图像,可以生成处理后的图像
关键点解答:
- 这个图像要被拉成一个向量,叫做 vectorization
-
基有 25 个元素
可以这样选择标准基:
e₁ = (1,0,0,...) e₂ = (0,1,0,...) ... e₂₅ = (0,0,...,1)每个基向量对应 一个像素位置
-
变换需要一个 25×25 的变换矩阵
这是一个:
\[T : ℝ^{25} → ℝ^{25}\]所以根据线性代数的语境,卷积核生成了一个卷积矩阵 $A$ ,使得
\[y = Ax\] -
变成另一幅向量
输出向量经过 reshape 回 5×5,就是新图像
- 关于生成的卷积矩阵:
- 这个 25×25 矩阵
- 非常大
- 非常稀疏
- 结构高度重复
- 完全由卷积核生成
-
所以我们用 kernel + 滑动 的方式计算,等价但高效
对于一个像素,卷积操作只和 周围 3×3 共 9 个像素有关,
所以矩阵的一行里:
- 只有 9 个非零数
- 其他全是 0
这种“沿着对角线重复出现结构”的矩阵,就叫:
Toeplitz / Block-Toeplitz 矩阵
所以,卷积 ≈ 一个结构高度重复、非常稀疏的线性变换
小结
卷积核 = 一个局部线性算子
图像 = 高维向量
卷积 = 稀疏 Toeplitz 矩阵 × 向量
不同卷积核 ➡ 选择不同的「局部基」
这和 随机矩阵 / Jacobian / NTK 在思想上是完全同源的。
示例
接下来,使用一个例子来帮助理解:
-
一个 5×5 图像 + 3×3 kernel
-
对应的 25×25 卷积矩阵
-
指出哪 9 个元素非零、为什么是 Toeplitz
1. 图像表示和向量化
一张 $5\times 5$ 的图像 $X$ 记作:
\[X = \begin{bmatrix} x_1 & x_2 & x_3 & x_4 & x_5 \\ x_6 & x_7 & x_8 & x_9 & x_{10} \\ x_{11} & x_{12} & x_{13} & x_{14} & x_{15} \\ x_{16} & x_{17} & x_{18} & x_{19} & x_{20} \\ x_{21} & x_{22} & x_{23} & x_{24} & x_{25} \end{bmatrix}\]按行优先向量化(拉直到向量):
\[\mathrm{vec}(X) = \begin{bmatrix} x_1, x_2, \dots, x_{25} \end{bmatrix}^\top \in \mathbb{R}^{25}\]2.卷积核表示
将卷积核 $K$ 记作:
\[K = \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix}\]接下来进行卷积操作,并还原出卷积矩阵
3. 卷积方式
- stride = 1
- padding = 0(valid 卷积)
- 输出大小:3×3
为了简单,先只看 valid (same 卷积只是多几行零)
输出左上角像素 $y_1$ 来自:
\[\begin{bmatrix} x_1 & x_2 & x_3 \\ x_6 & x_7 & x_8 \\ x_{11} & x_{12} & x_{13} \end{bmatrix}\]所以:
\[y_1 = a x_1 + b x_2 + c x_3 + d x_6 + e x_7 + f x_8 + g x_{11} + h x_{12} + i x_{13}\]把这句话写成:
\[y_1 = \begin{bmatrix} a & b & c & 0 & 0 & d & e & f & 0 & 0 & g & h & i & 0 & \cdots & 0 \end{bmatrix} \cdot \mathrm{vec}(X)\]这就是 25×25 矩阵的第一行
输出 $y_2$ 用到:
\[\begin{bmatrix} x_2 & x_3 & x_4 \\ x_7 & x_8 & x_9 \\ x_{12} & x_{13} & x_{14} \end{bmatrix}\]对应:
\[y_2 = a x_2 + b x_3 + c x_4 + d x_7 + e x_8 + f x_9 + g x_{12} + h x_{13} + i x_{14}\]写成矩阵行:
\[y_2 = \begin{bmatrix} 0 & a & b & c & 0 & 0 & d & e & f & 0 & 0 & g & h & i & 0 & \cdots \end{bmatrix} \cdot \mathrm{vec}(X)\]所以这就是卷积矩阵的第二行
可以看出,本质上是将卷积核的各元素向右平移了一格。
而对于第三行结束后,卷积窗口进行“换行”:
比如 $y_4$ (第二行第一个输出):
\[\begin{bmatrix} x_6 & x_7 & x_8 \\ x_{11} & x_{12} & x_{13} \\ x_{16} & x_{17} & x_{18} \end{bmatrix}\]对应矩阵行:
\[[0,0,0,0,0,\; a,b,c,0,0,\; d,e,f,0,0,\; g,h,i,0,\dots]\]整体向右跳了 5 格
(因为一行有 5 个像素)
所以,我们可以写出这个卷积矩阵的表示:
\[\underbrace{ \begin{bmatrix} \text{—— 9 个非零 ——} & 0 & \cdots \\ 0 & \text{—— 9 个非零 ——} & \cdots \\ \vdots & \vdots & \ddots \end{bmatrix} }_{\text{卷积矩阵 } A}\]满足:
\[\mathrm{vec}(Y) = A \, \mathrm{vec}(X)\]其中:
- $A \in \mathbb{R}^{9 \times 25}$ (valid)
- 或 $A \in \mathbb{R}^{25 \times 25}$ (same)
4. 小结
至此,我们可以重新理解一遍这个诠释:
卷积层 = 一个带强结构约束、权重共享的稀疏大矩阵
卷积 ≈ 一个结构高度重复、非常稀疏的线性变换
总结
在这篇文章里,我们从具体的卷积核入手,深入探讨了卷积操作的线性代数本质,为后续理解CNN理论,Jacobian矩阵,NTK构造奠定了重要的基础。
文章分为三个部分。
第一部分,列举了常见的卷积核参数,包括低通滤波,高通滤波和Gabor等特殊核,提供了操作的示例代码。
第二部分,介绍了图像的卷积处理在线性代数中的明确定义,对卷积操作做出了诠释:
卷积操作 ≈ 一个结构高度重复、非常稀疏的线性变换
第三部分,给出了$5\times 5$图像的卷积操作实例,并写出了$3\times 3$卷积操作的卷积矩阵,明确了:
卷积层 = 一个带强结构约束、权重共享的稀疏大矩阵
希望这篇文章能对我有一些启示作用,并帮助我更好地理解图像卷积处理和卷积神经网络的相关内容。
如有纰漏,请批评指正
留下评论