目标检测学习笔记

看完吴恩达老师的 deeplearning.ai 课程目标检测这节课程的学习笔记。

1. 目标定位(object localization)

图像分类、目标定位以及检测的区别如下图所示,前两个是图片中只有 1 个对象的情况,而检测是图片有多个对象的情况。

所以,目标定位实际上是在分类的基础上定位到对象的位置,即找到对象在哪里并且直到这个对象是属于哪一类。

在图像分类中,一般定义的标签 y 的维度和类别是一样的,即假如是有 3 个类别,那么标签 y 的维度也是 3 个,比如令 y = [ c 1 , c 2 , c 3 ] y=[c_1, c_2, c_3] y=[c1,c2,c3] ,然后输出的时候就判断哪个类别的预测概率大,就将其作为该对象的预测类别。

而在目标定位中,增加了寻找对象的位置的工作,那么标签就需要有坐标信息,所以这里假设是 3 个类别,定义其标签为:
y =   [ p c b x b y b h b w c 1 c 2 c 3 ] y = \ \begin{bmatrix}p_c \\ b_x \\ b_y \\ b_h \\ b_w \\ c_1 \\ c_2 \\ c_3 \\\end{bmatrix} y= pcbxbybhbwc1c2c3
其中, p c p_c pc 表示图片是否包含有对象,如果对象属于指定的3 个类别中的一个,那么 p c = 1 p_c=1 pc=1, 否则就是 p c = 0 p_c=0 pc=0,然后接下来的 b x , b y , b h , b w b_x, b_y, b_h, b_w bx,by,bh,bw 表示的就是坐标,或者说就是边界框参数,一般来说就是左上角的坐标加上边界框的宽和高,然后最后 3 个就是代表类别了,有多少个类别,就有多少个参数,其数值表示的预测概率。

然后神经网络的损失函数,一般就是采用平方误差策略,假设类别 y y y 和网络的输出 y ^ \hat{y} y^,那么损失函数就是这么计算了,根据上述的标签定义,是有 9 维的:
L ( y ^ , y ) = ( y 1 ^ − y 1 ) 2 + ( y 2 ^ − y 2 ) 2 + ⋯ + ( y 8 ^ − y 8 ) 2 L(\hat{y}, y) = (\hat{y_1}-y_1)^2+(\hat{y_2}-y_2)^2+\dots +(\hat{y_8}-y_8)^2 L(y^,y)=(y1^y1)2+(y2^y2)2++(y8^y8)2
当然了,这里是用平方误差简化了,实际应用中,通常做法是对边界框的坐标应用平方差或者类似方法,对 p c p_c pc 应用逻辑回归函数,或者评分预测误差,而对类别标签应用对数损失函数。

2. 基于滑动窗口的目标检测算法

对于基于滑动窗口的目标检测算法,首先是创建一个标签训练集,也就是将图片进行剪切成多个图片样本,如下图所示,将左图进行剪切,得到中间的 5个样本,然后按照样本是否包含汽车,进行标注标签,然后将这个训练集输入 CNN 中,训练得到一个模型。

当训练好模型后,就可以进行测试,测试的例子如下所示,选择一个特定大小的窗口,然后从图片左上角开始滑动,每次将窗口内的图片送入模型中,判断该图片内是否有汽车,依次重复操作,直到滑动窗口滑过测试图片的每个角落。

上述做法就是滑动窗口目标检测。以某个步幅滑动这些方框窗口遍历整张图片,对这些方形区域进行分类,判断是否包含目标对象。

该算法的一个很明显的缺点,就是计算成本。主要原因是跟滑动窗口的大小有关系,选择太小的,那么就会需要滑动很多次,也就是需要检测多个小窗口,提高了计算成本;而如果窗口过大,那么窗口数量会减少,但是会影响模型的性能。

滑动窗口的卷积实现

上述介绍的实现基于滑动窗口的目标检测的方法,效率是比较低,这里会介绍如何通过卷积实现滑动窗口,首先需要将 CNN 的全连接层转换为卷积层,也就是得到一个全卷积网络(FCN),如下图所示:

这里的输入图片例子是一个 14 × 14 × 3 14\times 14\times 3 14×14×3 的图片,然后经过一个卷积核大小是 5 × 5 5\times 5 5×5 的卷积层,输出是 14 × 14 × 3 14\times 14\times 3 14×14×3 ,接着是一个 Max pooling 层,参数是 2 × 2 2\times 2 2×2 ,输出就是 5 × 5 × 16 5\times 5\times 16 5×5×16 ,原本是接着两个 400 × 400 400\times 400 400×400 的全连接层,现在改为用 1 × 1 × 400 1\times 1\times 400 1×1×400 的两个卷积层。

接着是主要参考论文 OverFeat 来介绍如何通过卷积实现滑动窗口对象检测算法。

具体实现例子如下所示,第一行表示训练时候使用 14 × 14 × 3 14\times 14\times 3 14×14×3的图片,第二行表示测试时候使用的输入图片大小是 16 × 16 × 3 16\times 16\times 3 16×16×3。而使用这个图片,在经过卷积层的时候,这里步幅是 2,所以卷积核是移动了四次,得到了输出是 12 × 12 × 16 12\times 12\times 16 12×12×16,最终的输出也是 2 × 2 × 4 2\times 2\times 4 2×2×4

可以看到,其实在这 4 次卷积操作中有很多计算是重复的,因为有很多区域都是重叠的,具体四次如下所示,不同颜色的框表示四次操作的范围,左边第一个图的红色,然后移动 2 格,是第二个图中绿色框的区域,接着是第三张图里橙色,也就是左下角,然后第四张图里右下角,其实中间区域都是重叠的,也就是四个角落是有所不同。

简单说,通过这个卷积操作,我们就可以不用将测试图片分割成 4 个子图片,分别输入网络中,执行前向操作,进行预测,直接整张图输入网络即可,卷积层就会帮我们完成这个操作,也就是一次前向操作即可,节省了 4 倍的时间。

不过,这种方法虽然提高了算法的效率,但也有一个缺点,就是边界框的位置可能不够准确。

Bounding Box预测(Bounding box predictions)

接下来要介绍如何可以得到精确的边界框,这里介绍的就是著名的 YOLO(You only look once) 算法,目前也是目标检测里很常用的一种算法,以及有了更多的版本,从最初的 YOLO,到目前的 YOLOv5,持续进行改进和提升。

YOLO 算法的做法如下图所示,采用一个 3 × 3 3\times 3 3×3 的网格,将输入图片分成了 9 个区域,然后检测每个区域内是否有目标对象,YOLO 算法会将检测到的对象,根据其中点位置,将其分配到中点所在的格子里,所以下图中编号 4 和 6 包含了汽车,但是编号 5 虽然同时有两辆车的一部分,但因为中心点不在,所以这个格子输出的结果是不包含有汽车。

采用这个算法,网络输出的结果就是 3 × 3 × 8 3\times 3 \times 8 3×3×8 , 这里表示 3 × 3 3\times 3 3×3 的网格,每个网格的结果是一个 8 维的向量,也是之前定义好的,即 p c , b x , b y , b w , b h , c 1 , c 2 , c 3 p_c, b_x, b_y, b_w, b_h, c_1, c_2, c_3 pc,bx,by,bw,bh,c1,c2,c3

该算法的优点就是CNN 可以输出精确的边界框,在实践中可以采用更多的网格,比如 19 × 19 19\times 19 19×19,即便图片中包含多个对象,但如果网格数量越多,每个格子就越小,一个格子存在多个对象的概率就会很低。

YOLO 算法的另一个优点是它采用卷积实现,速度非常快,这也是它很受欢迎的原因。

交并比(Intersection over union)

交并比(IoU)表示两个边界框交集和并集之比。并集就是如下图中绿色区域部分,即同时包含两个边界框的区域;而交集就是两个边界框重叠部分,下图中橙色区域。所以交并比就是橙色区域面积除以绿色区域的面积。

一般来说,IoU 大于等于 0.5,就可以说检测正确,结果是可以接受的,这也是一般的约定。但IoU 越大,边界框就约精确了。

这也是衡量定位精确到的一种方式,IoU 是衡量了两个边界框重叠的相对大小。

3. 非极大值抑制

目前的检测算法还会存在一个问题,就是对同一个对象作出多次的检测,而非极大值抑制就可以确保算法只对每个对象检测一次。

非极大值抑制算法的执行过程如下图所示,这里是采用 19 × 19 19\times 19 19×19 的网格,对每个网格先执行检测算法,得到的输出就是 19 × 19 × 8 19\times 19 \times 8 19×19×8。当然这里只是预测是否有汽车,那么其实可以暂时不需要分类部分,也就是每个网格输出一个 5 维向量, p c p_c pc 以及边界框的四个坐标参数。

然后开始实现非极大值抑制算法:

  1. 去掉所有预测概率低于阈值的边界框,比如设置阈值是 0.6,那么对于 p c ≤ 0.6 p_c \le 0.6 pc0.6 的边界框都被抛弃;
  2. 在剩下的边界框里,将预测概率最高的边界框,将其输出作为预测结果;
  3. 然后将还剩下的边界框里,和第一步被抛弃的边界框有高 IoU 的,比如 I o U ≥ 0.5 IoU \ge 0.5 IoU0.5 的边界框都抛弃掉;
  4. 对所有边界框都进行处理,按照上述 3 个步骤来判断,抛弃还是作为输出结果;

4. Anchor Boxes

上述说的检测都是限制于一个格子检测出一个对象,但如果需要一个格子可以检测多个对象,那么就需要用到 anchor box。

如下图所示,假设现在输入图片是左图中的例子,在第三行的第二个格子中是刚好同时存在人和汽车,并且中心点都落在这个格子里,但根据之前的算法,只能检测到其中一个对象。而要解决这个问题,就需要用到 anchor box 了。

这里 anchor box 的思路是预先定义两个不同形状的 anchor box,如上图的两个,当然实际情况里可能会采用更多的 anchor box,比如 5 个甚至更多。不过这里只需要两个即可。

接着就是重新定义标签,不再是开始的 8 维向量,而是 2 × 8 2\times 8 2×8 的向量,前面 8 个和 anchor box1 相关联,而后面 8 个和 anchor box2 相关联。如上图右侧的 y y y 所示。

在实际例子中,还有一些情况:

  • 比如使用两个 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 来生成候选区域

参考

  1. deeplearning.ai 04 课程第三周–目标检测
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

spearhead_cai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值