卷积操作:从二维到三维的全面解析
1. 二维卷积基础
在图像处理中,二维卷积是一项核心技术。我们先从输入图像的表示开始,用 $S$ 表示输入图像的定义域,它是一个二维网格,其定义域为 $S = [0, H - 1] \times [0, W - 1]$。在这个网格中,每一个点都是一个像素,像素的颜色值可以是一个标量(灰度值),也可以是一个包含三个值(R、G、B)的向量。
在这个输入点的网格上,我们定义了一个输出点的子网格 $S_o$。$S_o$ 是通过对输入应用基于步长的步进操作得到的。假设 $\vec{s} = [s_H, s_W]$ 表示二维步长向量,第一次滑动停止时,核(这里形象地比喻为“砖块”)的左上角位于 $\vec{p}_0 \equiv (y = 0, x = 0)$,下一次滑动停止位置是 $\vec{p}_1 \equiv (y = 0, x = s_W)$,再下一次是 $\vec{p}_2 \equiv (y = 0, x = 2s_W)$。当到达右端时,$y$ 值增加。总体而言,输出网格由核在输入图像上滑动时左上角停留的点组成,即 $S_o = {\vec{p}_0, \vec{p}_1, \cdots}$,并且 $S_o$ 中的每个点都有一个输出值。
二维卷积中单个输出值的生成由以下公式表示:
$Y_{y,x} = \sum_{i = 0}^{k_H} \sum_{j = 0}^{k_W} X_{y + i, x + j} W_{i,j}$,其中 $\forall (y, x) \in S_o$
这里 $X$ 表示输入,$Y$ 表示输出,$W$ 表示核的权重。核的原点位于 $X_{y,x}$,其尺寸为 $(k_H, k_W)$,它覆盖了定义域 $[y \cdots (y + k_H)] \times [x \cdots (x + k_W)]$ 内的所有输入像素,这些像素参与上述公式的计算,每个输入像素都与覆盖它的核元素相乘。
2. 二维卷积的应用
2.1 图像平滑
在图像处理中,图像平滑是一个常见的需求。就像一维局部平滑可以去除局部波动,使长期模式更清晰一样,二维卷积也能实现类似的效果。例如,对于一张带有椒盐噪声背景的文字图像,噪声没有语义意义,而文字才是需要分析的内容(可能通过光学字符识别)。我们可以使用具有均匀权重的核进行二维卷积来消除噪声,如:
$W =
\begin{bmatrix}
W_{0,0} = \frac{1}{9} & W_{0,1} = \frac{1}{9} & W_{0,2} = \frac{1}{9} \
W_{1,0} = \frac{1}{9} & W_{1,1} = \frac{1}{9} & W_{1,2} = \frac{1}{9} \
W_{2,0} = \frac{1}{9} & W_{2,1} = \frac{1}{9} & W_{2,2} = \frac{1}{9}
\end{bmatrix}
$
使用这个核进行卷积后,得到的是去噪或平滑后的图像。通过观察可以发现,这个均匀核使得每个输出像素是相邻 $3 \times 3$ 输入像素的加权局部平均值。如果你想运行图像平滑的完整功能代码,可以在 Jupyter - Notebook 中执行,代码可在 http://mng.bz/aDM7 找到。
2.2 图像边缘检测
并非图像中的所有像素都具有相同的语义重要性。例如,在一张人站在白色墙壁前的照片中,墙壁的像素颜色均匀,几乎没有什么信息价值,而属于轮廓的像素(即边缘像素)能提供最大的语义线索。这与人类视觉科学相符,实验表明人类大脑更关注颜色急剧变化的区域。同样,人类对待声音也是如此,会忽略均匀的嗡嗡声,而在声音的音量或频率变化时会警觉起来。
因此,识别图像中的边缘对于图像理解至关重要。边缘是局部现象,可以通过使用专门选择的核进行二维卷积来识别。例如,对于垂直边缘检测,使用核:
$W =
\begin{bmatrix}
W_{0,0} = -0.25 & W_{0,1} = 0.25 \
W_{1,0} = -0.25 & W_{1,1} = 0.25
\end{bmatrix}
$
对于水平边缘检测,使用核:
$W =
\begin{bmatrix}
W_{0,0} = -0.25 & W_{0,1} = -0.25 \
W_{1,0} = 0.25 & W_{1,1} = 0.25
\end{bmatrix}
$
在像素值相等的区域(如平坦的墙壁),上述核的输出为零(因为正负核元素作用在相等的值上,加权和为零),这意味着这些核抑制了均匀区域。而当颜色有急剧变化时,核会有高响应(因为核的正负两半作用在非常不同的值上,加权和为大的负值或正值)。如果你想运行边缘检测的完整功能代码,可以在 Jupyter - Notebook 中执行,代码可在 http://mng.bz/g4JV 找到。
3. PyTorch 中的二维卷积
在 PyTorch 中,我们可以进行自定义权重的二维卷积。前面我们已经了解到,具有均匀权重的核(如上述用于图像平滑的核)会对输入数组进行局部平滑,而具有反对称权重的核(如用于边缘检测的核)会在输入数组的边缘位置产生尖峰输出。
下面是 PyTorch 中进行二维局部平均卷积的代码示例:
import torch
x = load_img() # 加载一个有噪声的灰度输入图像
w = torch.tensor(
[
[0.11, 0.11, 0.11],
[0.11, 0.11, 0.11],
[0.11, 0.11, 0.11]
]
) # 实例化卷积核的权重
x = x.unsqueeze(0).unsqueeze(0) # PyTorch 期望输入和权重的形式为 N x C x H x W,这里 N = 1 表示单张图像,C = 1 表示灰度图像,H 和 W 为 5,将 5x5 张量转换为 1 x 1 x 5 x 5 张量
w = w.unsqueeze(0).unsqueeze(0)
conv2d = torch.nn.Conv2d(1, 1, kernel_size=2, stride=1, bias=False) # 实例化二维平滑核
conv2d.weight = torch.nn.Parameter(w, requires_grad=False) # 设置核权重
with torch.no_grad(): # 指示 PyTorch 不计算梯度
y = conv2d(x) # 运行卷积
下面是 PyTorch 中进行二维边缘检测的代码示例:
import torch
x = load_img() # 加载一个有边缘的灰度输入图像
w = torch.tensor(
[[-0.25, 0.25],
[-0.25, 0.25]]
) # 实例化卷积核的权重
x = x.unsqueeze(0).unsqueeze(0) # 将输入转换为 1 x 1 x 4 x 4
w = w.unsqueeze(0).unsqueeze(0)
conv2d = torch.nn.Conv2d(1, 1, kernel_size=2, stride=1, bias=False) # 实例化二维边缘检测核
conv2d.weight = torch.nn.Parameter(w, requires_grad=False) # 设置核权重
with torch.no_grad(): # 指示 PyTorch 不计算梯度
y = conv2d(x) # 运行卷积
4. 二维卷积作为矩阵乘法
在一维卷积中,我们可以将其看作输入向量与块对角矩阵的乘法。这个概念可以扩展到更高维度,尽管权重矩阵会变得更加复杂。在二维卷积的矩阵乘法视角中,输入图像被表示为一个光栅化的一维向量,即一个 $m \times n$ 的输入矩阵会变成一个 $mn$ 大小的向量,对应的权重矩阵的行长度为 $mn$,每一行对应一个特定的滑动停止位置。
为了便于理解,我们考虑一个大小为 $[H, W] = [4, 4]$ 的输入图像,使用大小为 $[k_H, k_W] = [2, 2]$ 的核,步长为 $[s_H, s_W] = [1, 1]$ 进行二维卷积。输入图像 $X$ 可以表示为:
$X =
\begin{bmatrix}
X_{0,0} & X_{0,1} & X_{0,2} & X_{0,3} \
X_{1,0} & X_{1,1} & X_{1,2} & X_{1,3} \
X_{2,0} & X_{2,1} & X_{2,2} & X_{2,3} \
X_{3,0} & X_{3,1} & X_{3,2} & X_{3,3}
\end{bmatrix}
$
光栅化为长度为 $4 \times 4 = 16$ 的输入向量 $\vec{x}$。设核的权重为:
$
\begin{bmatrix}
w_{0,0} & w_{0,1} \
w_{1,0} & w_{1,1}
\end{bmatrix}
$
二维卷积 $Y = W \circledast X$ 可以表示为以下矩阵乘法:
$
Y = W \circledast X =
\begin{bmatrix}
Y_{0,0} \
Y_{0,1} \
Y_{0,2} \
Y_{1,0} \
Y_{1,1} \
Y_{1,2} \
Y_{2,0} \
Y_{2,1} \
Y_{2,2}
\end{bmatrix}
=
\begin{bmatrix}
w_{0,0}X_{0,0} + w_{0,1}X_{0,1} + w_{1,0}X_{1,0} + w_{1,1}X_{1,1} \
w_{0,0}X_{0,1} + w_{0,1}X_{0,2} + w_{1,0}X_{1,1} + w_{1,1}X_{1,2} \
w_{0,0}X_{0,2} + w_{0,1}X_{0,3} + w_{1,0}X_{1,2} + w_{1,1}X_{1,3} \
w_{0,0}X_{1,0} + w_{0,1}X_{1,1} + w_{1,0}X_{2,0} + w_{1,1}X_{2,1} \
w_{0,0}X_{1,1} + w_{0,1}X_{1,2} + w_{1,0}X_{2,1} + w_{1,1}X_{2,2} \
w_{0,0}X_{1,2} + w_{0,1}X_{1,3} + w_{1,0}X_{2,2} + w_{1,1}X_{2,3} \
w_{0,0}X_{2,0} + w_{0,1}X_{2,1} + w_{1,0}X_{3,0} + w_{1,1}X_{3,1} \
w_{0,0}X_{2,1} + w_{0,1}X_{2,2} + w_{1,0}X_{3,1} + w_{1,1}X_{3,2} \
w_{0,0}X_{2,2} + w_{0,1}X_{2,3} + w_{1,0}X_{3,2} + w_{1,1}X_{3,3}
\end{bmatrix}
$
也可以表示为:
$
W \circledast X =
\begin{bmatrix}
w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1} & 0 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & 0 & 0 & w_{1,0} & w_{1,1}
\end{bmatrix}
\begin{bmatrix}
X_{0,0} \
X_{0,1} \
X_{0,2} \
X_{0,3} \
X_{1,0} \
X_{1,1} \
X_{1,2} \
X_{1,3} \
X_{2,0} \
X_{2,1} \
X_{2,2} \
X_{2,3} \
X_{3,0} \
X_{3,1} \
X_{3,2} \
X_{3,3}
\end{bmatrix}
$
这里的二维卷积权重矩阵是一个特殊情况,但它说明了一般原理。二维卷积权重矩阵和一维情况一样是块对角的,核权重的放置方式精确地模拟了卷积过程。该卷积权重矩阵有 9 行 16 列,它接收一个 16 元素的输入向量(从 $4 \times 4$ 输入图像光栅化而来),并生成一个 9 元素的输出矩阵(可以折叠成一个 $3 \times 3$ 的卷积输出图像)。
5. 三维卷积的必要性
俗话说“一张图片胜过千言万语”,那么可以说“一段视频胜过万语千言”。视频是动态现实场景的丰富信息源。随着基于深度学习的图像分析(二维卷积)越来越成功,到 2021 年左右,视频分析正成为下一个需要攻克的研究前沿。
视频本质上是三维实体,其在三个维度上的表示都是离散的。这三个维度分别是:
- 空间:本身是二维的,包括 (a) 高度 (b) 宽度
- 时间:视频由一系列帧组成,每一帧都是一个图像,即一个离散的二维像素数组。一帧代表视频场景在特定(采样)时间点的完整情况,帧中的一个像素代表场景中特定空间采样位置在该时间点的颜色。整个视频由一系列帧组成,代表了在空间和时间上离散点(像素)的动态场景。因此,视频可以扩展到一个时空体积(简称 ST 体积),可以想象成一个长方体,每个横截面是一个矩形,代表一帧。
为了分析视频,我们需要从这个三维体积中提取局部模式。那么能否通过重复的二维卷积来实现呢?答案是否定的。当我们将连续的帧放在一起看时,会有额外的信息,而单独看每一帧时这些信息是缺失的。例如,给你一张半开着的门的图像,你无法从这一张图像中判断门是在打开还是关闭。要理解这一点,需要查看几个连续的帧。换句话说,逐帧分析视频会使我们失去一个重要的信息模态——运动,而只有同时分析多个连续帧才能理解运动信息。这就是我们需要三维卷积的原因。
6. 三维卷积的原理
理解三维卷积的最佳方式是想象一块砖在一个房间的整个体积内滑动。房间对应于输入卷积的视频的 ST 体积,砖对应于核。在滑动过程中,砖会停在连续的位置,我们称这些位置为滑动停止点。每次滑动停止时会产生一个输出点。当砖扫过整个输入 ST 体积时,会生成一个输出 ST 体积。在每个滑动停止点,我们将每个输入像素值与覆盖它的核元素相乘,并对这些乘积求和,这实际上是输入(房间)中被核(砖)覆盖的所有元素的加权和,覆盖的核元素作为权重。
我们用 $S$ 表示输入 ST 体积,它是一个三维网格,定义域为 $S = [0, T - 1] \times [0, H - 1] \times [0, W - 1]$。$S$ 中的每个点都是一个像素,具有颜色值(可以是标量——灰度值,也可以是一个包含三个值 R、G、B 的向量)。在这个输入点的网格上,我们定义一个输出点子网格 $S_o$。$S_o$ 是通过对输入应用基于步长的步进操作得到的。假设 $\vec{s} = [s_T, s_H, s_W]$ 表示三维步长向量,第一次滑动停止时,砖的左上角位于 $\vec{p}_0 \equiv (t = 0, y = 0, x = 0)$,下一次滑动停止位置是 $\vec{p}_1 \equiv (t = 0, y = 0, x = s_W)$,再下一次是 $\vec{p}_2 \equiv (t = 0, y = 0, x = 2s_W)$。当到达右端时,$y$ 值增加;当到达底部时,$t$ 值增加;当到达房间尽头时停止。$S_o = {\vec{p}_0, \vec{p}_1, \cdots}$ 是核在输入体积上滑动时左上角停留的点,$S_o$ 中的每个点都有一个输出。
核也有三个维度(实际上,在实际应用中,它还有另外两个维度对应于输入通道和批次,但为了简单起见,这里先忽略,后续在 PyTorch 实现部分会讨论)。
通过以上对二维卷积和三维卷积的介绍,我们可以看到卷积操作在图像处理和视频分析中的重要性和强大功能。无论是去除图像噪声、检测边缘,还是分析视频中的运动信息,卷积操作都发挥着关键作用。同时,我们也了解了如何在 PyTorch 中实现自定义权重的二维卷积,以及如何从矩阵乘法的角度理解二维卷积。随着技术的不断发展,卷积操作在更多领域的应用值得我们进一步探索。
7. 三维卷积在视频分析中的应用示例
为了更好地理解三维卷积在视频分析中的作用,我们来看一个简单的示例。假设我们有一个视频,视频中包含一个人在房间里行走的场景。我们希望通过三维卷积来检测这个人的运动轨迹。
首先,我们将视频表示为一个三维的张量,其中三个维度分别对应时间、高度和宽度。然后,我们定义一个三维的卷积核,这个卷积核的大小和步长需要根据具体的需求进行调整。
以下是一个简化的步骤说明:
1. 数据准备 :将视频转换为三维张量,每个元素代表一个像素的颜色值。
2. 定义卷积核 :根据需要检测的特征,设计一个合适的三维卷积核。例如,如果我们希望检测水平方向的运动,可以设计一个在时间和水平方向上有特定权重分布的卷积核。
3. 进行卷积操作 :将卷积核在三维张量上滑动,按照三维卷积的原理进行计算,得到输出的三维张量。
4. 分析输出结果 :通过分析输出的三维张量,我们可以得到关于视频中运动特征的信息,例如运动的方向、速度等。
8. 对比二维卷积和三维卷积
为了更清晰地展示二维卷积和三维卷积的区别和联系,我们可以通过以下表格进行对比:
| 对比项 | 二维卷积 | 三维卷积 |
| ---- | ---- | ---- |
| 输入数据维度 | 二维(高度和宽度) | 三维(时间、高度和宽度) |
| 应用场景 | 图像处理,如去噪、边缘检测等 | 视频分析,如运动检测、动作识别等 |
| 信息利用 | 仅考虑空间信息 | 同时考虑空间和时间信息 |
| 卷积核维度 | 二维 | 三维 |
| 计算复杂度 | 相对较低 | 相对较高 |
从表格中可以看出,二维卷积主要用于处理静态图像,而三维卷积则更适合处理动态的视频数据。虽然三维卷积的计算复杂度较高,但它能够利用时间维度上的信息,从而更好地捕捉视频中的动态特征。
9. 三维卷积的 PyTorch 实现思路
在 PyTorch 中实现三维卷积与二维卷积有相似之处,但也有一些不同。以下是一个简单的 PyTorch 代码示例,展示了如何进行三维卷积:
import torch
import torch.nn as nn
# 定义输入数据
# 假设输入视频有 10 帧,每帧的大小为 32x32,通道数为 3
input_tensor = torch.randn(1, 3, 10, 32, 32)
# 定义三维卷积层
# 输入通道数为 3,输出通道数为 6,卷积核大小为 3x3x3,步长为 1
conv3d = nn.Conv3d(in_channels=3, out_channels=6, kernel_size=3, stride=1)
# 进行卷积操作
output_tensor = conv3d(input_tensor)
print("输入张量形状:", input_tensor.shape)
print("输出张量形状:", output_tensor.shape)
在这个示例中,我们首先定义了一个随机的输入三维张量,然后创建了一个三维卷积层。最后,将输入张量传递给卷积层进行卷积操作,并打印出输入和输出张量的形状。
10. 卷积操作的未来发展趋势
随着深度学习技术的不断发展,卷积操作也在不断演进。以下是一些可能的未来发展趋势:
- 多模态融合 :将卷积操作应用于多种模态的数据,如将图像和音频数据结合起来进行分析,以获得更全面的信息。
- 轻量化设计 :为了在资源受限的设备上运行,如移动设备和嵌入式系统,卷积操作将朝着轻量化的方向发展,例如设计更小的卷积核和更高效的算法。
- 自适应卷积 :根据输入数据的特征自动调整卷积核的参数,以提高卷积操作的性能和适应性。
- 与其他技术的结合 :将卷积操作与其他深度学习技术,如循环神经网络(RNN)、生成对抗网络(GAN)等结合起来,以解决更复杂的问题。
11. 总结
卷积操作作为深度学习中一种重要的工具,在图像处理和视频分析领域发挥着至关重要的作用。从二维卷积到三维卷积,我们看到了卷积操作在处理不同维度数据时的强大能力。二维卷积通过对图像进行处理,实现了去噪、边缘检测等功能;而三维卷积则能够利用视频中的时间信息,进行运动检测、动作识别等任务。
在实际应用中,我们可以根据具体的需求选择合适的卷积操作,并利用 PyTorch 等深度学习框架来实现。同时,我们也应该关注卷积操作的未来发展趋势,不断探索其在更多领域的应用可能性。通过不断学习和实践,我们可以更好地掌握卷积操作的原理和技巧,为解决实际问题提供更有效的方法。
以下是一个 mermaid 格式的流程图,展示了从视频输入到通过三维卷积进行分析的整体流程:
graph TD;
A[视频输入] --> B[转换为三维张量];
B --> C[定义三维卷积核];
C --> D[进行三维卷积操作];
D --> E[分析输出结果];
E --> F[获取运动特征信息];
这个流程图清晰地展示了三维卷积在视频分析中的主要步骤,从视频数据的输入,到经过卷积操作得到输出结果,最后分析输出结果获取有用的信息。通过这样的流程,我们可以更好地利用三维卷积来处理视频数据,挖掘其中的潜在信息。
超级会员免费看

1095

被折叠的 条评论
为什么被折叠?



