目标检测基础
目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边缘从而更准确地预测目标的真实边界框(ground-truth bounding box)。
-
锚框
以每个像素为中心生成多个大小和宽高比(aspect ratio)不同的边界框。
-
生成多个锚框:
假设输入图像高为 h h h,宽为 w w w。我们分别以图像的每个像素为中心生成不同形状的锚框。设大小为 s ∈ ( 0 , 1 ] s\in (0,1] s∈(0,1]且宽高比为 r > 0 r > 0 r>0,那么锚框的宽和高将分别为 w s r ws\sqrt{r} wsr和 h s / r hs/\sqrt{r} hs/r。
通常只对包含 s 1 s_1 s1或 r 1 r_1 r1的大小与宽高比的组合感兴趣,也就是说,以相同像素为中心的锚框的数量为 n + m − 1 n+m-1 n+m−1。对于整个输入图像,我们将一共生成 w h ( n + m − 1 ) wh(n+m-1) wh(n+m−1)个锚框。(其中n是锚框大小的数量,r是宽高比的数量)
以上生成锚框的方法已实现在MultiBoxPrior函数中。指定输入、一组大小和一组宽高比,该函数将返回输入的所有锚框。
X = nd.random.uniform(shape=(1, 3, h, w)) # 构造输入数据 #Y的size和ratio分别是锚框大小和比例 Y = contrib.nd.MultiBoxPrior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
-
交并比
Jaccard系数(Jaccard index)可以衡量两个集合的相似度。给定集合 A \mathcal{A} A和 B \mathcal{B} B,它们的Jaccard系数即二者交集大小除以二者并集大小:
J ( A , B ) = ∣ A ∩ B ∣ ∣ A ∪ B ∣ . J(\mathcal{A},\mathcal{B}) = \frac{\left|\mathcal{A} \cap \mathcal{B}\right|}{\left| \mathcal{A} \cup \mathcal{B}\right|}. J(A,B)=∣A∪B∣∣A∩B∣. -
标注训练集的锚框
为了训练目标检测模型,我们需要为每个锚框标注两类标签:
一是锚框所含目标的类别,简称类别;
二是真实边界框相对锚框的偏移量,简称偏移量(offset)。在目标检测时,我们首先生成多个锚框,然后为每个锚框预测类别以及偏移量,接着根据预测的偏移量调整锚框位置从而得到预测边界框,最后筛选需要输出的预测边界框。
假设图像中锚框分别为 A 1 , A 2 , … , A n a A_1, A_2, \ldots, A_{n_a} A1,A2,…,Ana,真实边界框分别为 B 1 , B 2 , … , B n b B_1, B_2, \ldots, B_{n_b} B1,B2,…,Bnb,且 n a ≥ n b n_a \geq n_b na≥nb。定义矩阵 X ∈ R n a × n b \boldsymbol{X} \in \mathbb{R}^{n_a \times n_b} X∈Rna×nb,其中第 i i i行第 j j j列的元素 x i j x_{ij} xij为锚框 A i A_i Ai与真实边界框 B j B_j Bj的交并比。
首先,我们找出矩阵 X \boldsymbol{X} X中最大元素,并将该元素的行索引与列索引分别记为 i 1 , j 1 i_1,j_1 i1,j1。我们为锚框 A i 1 A_{i_1} Ai1分配真实边界框 B j 1 B_{j_1} Bj1。显然,锚框 A i 1 A_{i_1} Ai1和真实边界框 B j 1 B_{j_1} Bj1在所有的“锚框—真实边界框”的配对中相似度最高。接下来,将矩阵 X \boldsymbol{X} X中第 i 1 i_1 i1行和第 j 1 j_1 j1列上的所有元素丢弃。找出矩阵 X \boldsymbol{X} X中剩余的最大元素,并将该元素的行索引与列索引分别记为 i 2 , j 2 i_2,j_2 i2,j2。我们为锚框 A i 2 A_{i_2} Ai2分配真实边界框 B j 2 B_{j_2} Bj2,再将矩阵 X \boldsymbol{X} X中第 i 2 i_2 i2行和第 j 2 j_2 j2列上的所有元素丢弃。此时矩阵 X \boldsymbol{X} X中已有两行两列的元素被丢弃。
依此类推,直到矩阵 X \boldsymbol{X} X中所有 n b n_b nb列元素全部被丢弃。这个时候,我们已为 n b n_b nb个锚框各分配了一个真实边界框。
接下来,我们只遍历剩余的 n a − n b n_a - n_b na−nb个锚框:给定其中的锚框 A i A_i Ai,根据矩阵 X \boldsymbol{X} X的第 i i i行找到与 A i A_i Ai交并比最大的真实边界框 B j B_j Bj,且只有当该交并比大于预先设定的阈值时,才为锚框 A i A_i Ai分配真实边界框 B j B_j Bj。
-
输出预测边界框
当锚框数量较多时,同一个目标上可能会输出较多相似的预测边界框。为了使结果更加简洁,我们可以移除相似的预测边界框。常用的方法叫作非极大值抑制(non-maximum suppression,NMS)。
对于一个预测边界框 B B B,模型会计算各个类别的预测概率。设其中最大的预测概率为 p p p,该概率所对应的类别即 B B B的预测类别。我们也将 p p p称为预测边界框 B B B的置信度。在同一图像上,我们将预测类别非背景的预测边界框按置信度从高到低排序,得到列表 L L L。从 L L L中选取置信度最高的预测边界框 B 1 B_1 B1作为基准,将所有与 B 1 B_1 B1的交并比大于某阈值的非基准预测边界框从 L L L中移除。这里的阈值是预先设定的超参数。此时, L L L保留了置信度最高的预测边界框并移除了与其相似的其他预测边界框。
图像风格迁移
使用卷积神经网络自动将某图像中的样式应用在另一图像之上。
两张输入图像,一张是内容图像,另一张是样式图像,我们将使用神经网络修改内容图像使其在样式上接近样式图像。
-
方法
首先,我们初始化合成图像,例如将其初始化成内容图像。该合成图像是样式迁移过程中唯一需要更新的变量。
然后,选择一个预训练的卷积神经网络来抽取图像的特征,其中的模型参数在训练中无须更新。
这里选取的预训练的神经网络含有3个卷积层,其中第二层输出图像的内容特征,而第一层和第三层的输出被作为图像的样式特征。
接下来,我们通过正向传播(实线箭头方向)计算样式迁移的损失函数,并通过反向传播(虚线箭头方向)迭代模型参数,即不断更新合成图像。
样式迁移常用的损失函数由3部分组成:内容损失(content loss)使合成图像与内容图像在内容特征上接近,样式损失(style loss)令合成图像与样式图像在样式特征上接近,而总变差损失(total variation loss)则有助于减少合成图像中的噪点。最后,当模型训练结束时,我们输出样式迁移的模型参数,即得到最终的合成图像。
-
预处理和后处理图像
预处理函数preprocess对输入图像在RGB三个通道分别做标准化,并将结果变换成卷积神经网络接受的输入格式。后处理函数postprocess则将输出图像中的像素值还原回标准化之前的值。
-
抽取特征
一般来说,越靠近输入层的输出越容易抽取图像的细节信息,反之则越容易抽取图像的全局信息。为了避免合成图像过多保留内容图像的细节,我们选择VGG较靠近输出的层,也称内容层,来输出图像的内容特征。我们还从VGG中选择不同层的输出来匹配局部和全局的样式,这些层也叫样式层。
-
定义损失函数
内容损失:
通过平方误差函数衡量合成图像与内容图像在内容特征上的差异。样式损失:
也通过平方误差,用格拉姆矩阵表达样式层输出的样式。自然地,样式损失的平方误差函数的两个格拉姆矩阵输入分别基于合成图像与样式图像的样式层输出,且各个样式层的格拉姆矩阵将在训练前预先计算好。。总变差损失:
一种常用的降噪方法是总变差降噪(total variation denoising)。假设 x i , j x_{i,j} xi,j表示坐标为 ( i , j ) (i,j) (i,j)的像素值,降低总变差损失
∑ i , j ∣ x i , j − x i + 1 , j ∣ + ∣ x i , j − x i , j + 1 ∣ \sum_{i,j} \left|x_{i,j} - x_{i+1,j}\right| + \left|x_{i,j} - x_{i,j+1}\right| i,j∑∣xi,j−xi+1,j∣+∣xi,j−xi,j+1∣
能够尽可能使邻近的像素值相似。损失函数:
即内容损失、样式损失和总变差损失的加权和。
图像分类案例1
从原始的图像文件开始,一步步整理、读取并将其变换为NDArray格式。