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