入职以后,慢慢接触到图像分类以及目标检测这一块,由于之前一直做的都是NLP相关,对于图像这一块了解甚少。因此觉得需要记录一下学习的一个过程,以便以后复习。由于个人水平有限,如果文章有错误,还恳请各位指出,万分感谢~


对于目标检测,这是一个十分复杂和困难的任务,其主要有两个部分:

  • 目标定位
  • 物体分类

用通俗的话来说就是,先要找出图片中的object,再去识别这个object是什么。本文主要分析目标检测中如何去定位到这个物体的方法。

单物体的定位

首先我们针对图片中只有单个物体来进行讨论分析。最初的物体定位的方法是参考图片分类的方法。如下图所示

在图片分类中,输入一张图片给网络,将经过一个卷积网络,然后把提取的特征输入到softmax层中,输出这张图片的label。而在物体检测中,我们在提取完特征之后多加了一个输出,也就是输出物体所在的bounding box的坐标。这样,我们的网络就可以得到图片中物体所在的位置以及类别了。

假设我们现在需要检测一张图片中是否有车,行人,摩托车这三个类。那么我们可以定义网络的输出为:

$y=[p_c,b_x,b_y,b_w,b_h,c_1,c_2,c_3]$

其中,输出 $y$ 的第一项 $p_c$ 代表这张图片中是否存在我们需要检测的物体的概率,0代表图片中不存在需要检测的物体,1代表图片中存在。紧接着的四项 $[b_x,b_y,b_w,b_h]$ 代表bounding box的位置,$[b_x,b_y]$ 为物体的bounding box的中点坐标,$b_w$ 为bounding box的宽,$b_h$ 为bounding box的高。$[c_1,c_2,c_3]$ 代表检测出的物体属于车,行人以及摩托车这三个类的概率。

那么损失函数可以定义为

$loss(x)= \begin{cases} (\hat{y}_1-y_1)^2+(\hat{y}_2-y_2)^2+...+(\hat{y}_8-y_8)^2, & \text{if $y_1=1$, 即图片中存在物体} \\\\ (\hat{y}_1-y_1)^2, & \text{if $y_1=0$, 即图片中不存在物体} \end{cases} $

其中 $y_i$ 代表网络输出 $y$ 的第 $i$ 项。当图片中有我们需要检测的物体时,我们的损失函数就是计算整个向量 $y$ 的均方误差;而当图片中不包含我们需要检测的物体时,我们只需要计算 $y_1$ 的均方误差,而对其余的输出不再关心。

这样我们就可以检测这种图片中只包含有一种物体的情况,对于一张图内有多个物体的情况,我们可以是用滑窗的思想来进行处理。假设我们的识别任务是,识别出图片中的车辆位置


step1: 制作一个数据集,使得汽车占了图像的绝大部分;
step2: 针对上一步制作的数据集,训练一个分类模型,判断图片是否是汽车;
step3: 在图片中取一个固定大小的框,固定步长,滑动窗口遍历整个图片。每次对滑窗中的图片输入到第二步中训练好的模型,判断图片是否有汽车;
step4: 扩大框的大小,重新执行第三步,直到框的大小取到整个图的大小;


这样我们就可以识别出一张图片里多个汽车了。但是这个方法有两个缺点:

  1. 针对一个滑窗,我们需要遍历整个图像,其中有大量的计算是重复的;
  2. 针对一张图像,我们需要迭代不同大小的滑窗;

针对第一点,研究学者们做出了改进。假设我们的图片分类模型如下图所示

研究学者们针对模型的全连接层进行了调整,把第一个全连接层改为了有400个大小为5*5*16的卷积核的卷积层,这样卷积的输出形状为1*1*400;针对第二个全连接层,我们可以使用400个大小为1*1*400的卷积核的卷积层代替,这样我们卷积层的输出仍然是1*1*400,最后使用4个1*1*400的卷积核的卷积层。这样我们的网络就是一个全卷积网络了。具体结构如下图所示:

这样做有一个好处,就是针对一张图片,我们的滑窗操作可以直接类似于卷积,在整张图片上做一次计算即可,这样就避免了许多冗余的计算,具体过程如下图所示:

假设我们的图片大小为16*16,而我们取的滑窗大小为14*14。此时,我们就不需要再把图片中14*14的滑窗从图中取出来输入到网络中,而是直接对整张图片输入到网络中进行计算。这样我们最后会得到的向量是2*2*4。输出向量的前两个维度2*2代表我们的滑窗的个数,对于16*16的图像,我们使用14*14的滑窗最后得到的结果是2*2。而向量的最后一个维度代表了当前滑窗识别出的物体属于4个类的概率。这样就避免了许多冗余的计算。

针对第二点,研究学者不再遍历滑窗大小,而是通过一些方法去得到大约2000个候选框。再对这2000个候选框进行分类,最后通过回归的方法对bounding box进行完善。

对于候选框的选取方法,主流的有如下几种:

  1. select

交并比(IoU,Intersection over union)

那么我们一般如何来定义bounding box的正确性呢。一般是用IoU来定义bounding box的准确性。那么IoU是如何计算得出的呢,我们可以看下面这个例子。

![](https://i.imgur.com/Hk7zrTr.jpg)

如上图所示,红色框框是真实的bounding box,而灰色的框框是我们模型预测的bouding box。那么我们怎么去计算IoU呢?

$IoU={S({bounding box} \bigcap {predict box}) \over {S({bounding box} \bigcup S{predict box})}}$

IoU的计算就是把bouding box与predict box的交集面积除以两者并集的面积,一般如果 $IoU>0.5$ 我们就会认为预测的框是框对的。当然,如果你想要模型预测的框更加准确,你可以把阈值调高到0.6或者0.7都可以。

非极大值抑制

针对一个物体,我们检测出了多个box都框住了它,那么我们如何去除掉多余的box,但是不会去除掉别的物体的box呢。这个时候就可以使用非极大值抑制的方法。这个算法的主要思想如下所示:


step1: 在当前图片中选取一个概率值最大的bounding box;
step2: 计算其他bounding box与当前选定的box的IoU,去除掉IoU大于0.5的box;
step3: 从剩下的bounding box中继续选取概率值最大的那个,重复第二步,直到遍历完所有的box后停止;


这样我们就可以得到多个物体的bounding box了。