目标检测学习笔记
这篇是看完吴恩达老师的 deeplearning.ai 课程里目标检测课程的学习笔记,文章的图片主要来自课程。
目录如下:
- 目标定位
- 基于滑动窗口的目标检测算法
- 滑动窗口的卷积实现
- Bounding Box 预测
- 交并比
- 非极大值抑制
- Anchor Boxes
- 候选区域
1. 目标定位(object localization)
图像分类、目标定位以及检测的区别如下图所示,前两个是图片中只有 1 个对象的情况,而检测是图片有多个对象的情况。
所以,目标定位实际上是在分类的基础上定位到对象的位置,即找到对象在哪里并且直到这个对象是属于哪一类。
在图像分类中,一般定义的标签 y 的维度和类别是一样的,即假如是有 3 个类别,那么标签 y 的维度也是 3 个,比如令 y=[c_1, c_2, c_3],然后输出的时候就判断哪个类别的预测概率大,就将其作为该对象的预测类别。
而在目标定位中,增加了寻找对象的位置的工作,那么标签就需要有坐标信息,所以这里假设是 3 个类别,定义其标签为:
其中, p_c 表示图片是否包含有对象,如果对象属于指定的3 个类别中的一个,那么 p_c = 1, 否则就是 p_c=0,然后接下来的b_x,b_y,b_h,b_w 表示的就是坐标,或者说就是边界框参数,一般来说就是左上角的坐标加上边界框的宽和高,然后最后 3 个就是代表类别了,有多少个类别,就有多少个参数,其数值表示的预测概率。
然后神经网络的损失函数,一般就是采用平方误差策略,假设类别y 和网络的输出 y^,那么损失函数就是这么计算了,根据上述的标签定义,是有 9 维的:
当然了,这里是用平方误差简化了,实际应用中,通常做法是对边界框的坐标应用平方差或者类似方法,对 应用逻辑回归函数,或者评分预测误差,而对类别标签应用对数损失函数。
2. 基于滑动窗口的目标检测算法
对于基于滑动窗口的目标检测算法,首先是创建一个标签训练集,也就是将图片进行剪切成多个图片样本,如下图所示,将左图进行剪切,得到中间的 5个样本,然后按照样本是否包含汽车,进行标注标签,然后将这个训练集输入 CNN 中,训练得到一个模型。
当训练好模型后,就可以进行测试,测试的例子如下所示,选择一个特定大小的窗口,然后从图片左上角开始滑动,每次将窗口内的图片送入模型中,判断该图片内是否有汽车,依次重复操作,直到滑动窗口滑过测试图片的每个角落。
上述做法就是滑动窗口目标检测。以某个步幅滑动这些方框窗口遍历整张图片,对这些方形区域进行分类,判断是否包含目标对象。
该算法的一个很明显的缺点,就是计算成本。主要原因是跟滑动窗口的大小有关系,选择太小的,那么就会需要滑动很多次,也就是需要检测多个小窗口,提高了计算成本;而如果窗口过大,那么窗口数量会减少,但是会影响模型的性能。
滑动窗口的卷积实现
上述介绍的实现基于滑动窗口的目标检测的方法,效率是比较低,这里会介绍如何通过卷积实现滑动窗口,首先需要将 CNN 的全连接层转换为卷积层,也就是得到一个全卷积网络(FCN),如下图所示:
这里的输入图片例子是一个 14*14*3 的图片,然后经过一个卷积核大小是 5*5 的卷积层,输出是 14*14*3,接着是一个 Max pooling 层,参数是 2*2,输出就是 5*5*16,原本是接着两个400*400 的全连接层,现在改为用 1*1*400 的两个卷积层。
接着是主要参考论文 OverFeat 来介绍如何通过卷积实现滑动窗口对象检测算法。
具体实现例子如下所示,第一行表示训练时候使用 14*14*3 的图片,第二行表示测试时候使用的输入图片大小是 16*16*3 。而使用这个图片,在经过卷积层的时候,这里步幅是 2,所以卷积核是移动了四次,得到了输出是 12*12*16,最终的输出也是 2*2*4。
可以看到,其实在这 4 次卷积操作中有很多计算是重复的,因为有很多区域都是重叠的,具体四次如下所示,不同颜色的框表示四次操作的范围,左边第一个图的红色,然后移动 2 格,是第二个图中绿色框的区域,接着是第三张图里橙色,也就是左下角,然后第四张图里右下角,其实中间区域都是重叠的,也就是四个角落是有所不同。
简单说,通过这个卷积操作,我们就可以不用将测试图片分割成 4 个子图片,分别输入网络中,执行前向操作,进行预测,直接整张图输入网络即可,卷积层就会帮我们完成这个操作,也就是一次前向操作即可,节省了 4 倍的时间。
不过,这种方法虽然提高了算法的效率,但也有一个缺点,就是边界框的位置可能不够准确。
Bounding Box预测(Bounding box predictions)
接下来要介绍如何可以得到精确的边界框,这里介绍的就是著名的 YOLO(You only look once) 算法,目前也是目标检测里很常用的一种算法,以及有了更多的版本,从最初的 YOLO,到目前的 YOLOv5,持续进行改进和提升。
YOLO 算法的做法如下图所示,采用一个 3*3 的网格,将输入图片分成了 9 个区域,然后检测每个区域内是否有目标对象,YOLO 算法会将检测到的对象,根据其中点位置,将其分配到中点所在的格子里,所以下图中编号 4 和 6 包含了汽车,但是编号 5 虽然同时有两辆车的一部分,但因为中心点不在,所以这个格子输出的结果是不包含有汽车。
采用这个算法,网络输出的结果就是 3*3*8, 这里表示 3*3 的网格,每个网格的结果是一个 8 维的向量,也是之前定义好的,即 p_c, b_x, b_y, b_w, b_h, c_1, c_2, c_3。
该算法的优点就是CNN 可以输、出精确的边界框,在实践中可以采用更多的网格,比如 19*19,即便图片中包含多个对象,但如果网格数量越多,每个格子就越小,一个格子存在多个对象的概率就会很低。
YOLO 算法的另一个优点是它采用卷积实现,速度非常快,这也是它很受欢迎的原因。
交并比(Intersection over union)
交并比(IoU)表示两个边界框交集和并集之比。并集就是如下图中绿色区域部分,即同时包含两个边界框的区域;而交集就是两个边界框重叠部分,下图中橙色区域。所以交并比就是橙色区域面积除以绿色区域的面积。
一般来说,IoU 大于等于 0.5,就可以说检测正确,结果是可以接受的,这也是一般的约定。但IoU 越大,边界框就约精确了。
这也是衡量定位精确到的一种方式,IoU 是衡量了两个边界框重叠的相对大小。
3. 非极大值抑制
目前的检测算法还会存在一个问题,就是对同一个对象作出多次的检测,而非极大值抑制就可以确保算法只对每个对象检测一次。
非极大值抑制算法的执行过程如下图所示,这里是采用 19*19 的网格,对每个网格先执行检测算法,得到的输出就是 19*19*8。当然这里只是预测是否有汽车,那么其实可以暂时不需要分类部分,也就是每个网格输出一个 5 维向量, p_c 以及边界框的四个坐标参数。
然后开始实现非极大值抑制算法:
- 去掉所有预测概率低于阈值的边界框,比如设置阈值是 0.6,那么对于 p_c <= 0.6 的边界框都被抛弃;
- 在剩下的边界框里,将预测概率最高的边界框,将其输出作为预测结果;
- 然后将还剩下的边界框里,和第一步被抛弃的边界框有高 IoU 的,比如 IoU >= 0.5 的边界框都抛弃掉;
- 对所有边界框都进行处理,按照上述 3 个步骤来判断,抛弃还是作为输出结果;
4. Anchor Boxes
上述说的检测都是限制于一个格子检测出一个对象,但如果需要一个格子可以检测多个对象,那么就需要用到 anchor box。
如下图所示,假设现在输入图片是左图中的例子,在第三行的第二个格子中是刚好同时存在人和汽车,并且中心点都落在这个格子里,但根据之前的算法,只能检测到其中一个对象。而要解决这个问题,就需要用到 anchor box 了。
这里 anchor box 的思路是预先定义两个不同形状的 anchor box,如上图的两个,当然实际情况里可能会采用更多的 anchor box,比如 5 个甚至更多。不过这里只需要两个即可。
接着就是重新定义标签,不再是开始的 8 维向量,而是 2*8 的向量,前面 8 个和 anchor box1 相关联,而后面 8 个和 anchor box2 相关联。如上图右侧的 所示。
在实际例子中,还有一些情况:
- 比如使用两个 anchor box,但一个格子里出现 3 个对象,这种情况算法也处理不好;
- 同个格子有两个对象,但它们的 anchor box 形状也一样,这种也是算法处理不好的情况;
另外,一般怎么选择 anchor box 呢?通常是手工指定 anchor box 形状,选择 5-10 个不同形状的,尽量覆盖多种不同的形状,覆盖你想要检测对象的各种形状。
另一种做法是在 YOLO 后期论文中介绍的,k-平均算法,用它来选择一组 anchor box,最具有代表性的一组 anchor box。
5. 候选区域
目标检测里另一个比较出名的算法,R-CNN,跟 YOLO 相比,是另一种思路,所以也基于此算法产生了很多检测算法,比如对其持续改进优化的,Fast-RCNN,Faster-RCNN 等。
R-CNN 算法是尝试找到一些区域,在这部分区域里运行 CNN 进行检测。而选择这些候选区域的方法是运行图像分割算法,分割的结果如下图所示。根据分割算法得到的结果,在不同的区域运行分类器,判断该区域是否有目标对象,比如图中标注号码的几个区域。
这种做法相比滑动窗口,可能是不需要图片的每个地方都去检测一遍,只需要对分割算法得到的色块,加上边界框,然后对边界框内的区域运行分类器,虽然是工作量会减少一些,但实际上速度还是很慢,但优点是精度会很不错,这个就和 YOLO 算法刚好相反。
因为速度太慢的问题,后续也有很多改进的算法
- Fast-RCNN:同样的方法进行候选区域的筛选,但通过卷积实现滑动窗口,对候选区域进行分类;
- Faster-RCNN:采用 CNN 来生成候选区域
参考
- deeplearning.ai 04 课程第三周--目标检测