机器视觉:目标检测

计算机视觉的三大基石: 识别,检测,分割。

  • 识别,是告诉你一张图像里有什么;
  • 检测,不光告诉你图像里有什么,还要告诉你目标所在的位置;
  • 分割,就更进一步,告诉你图像里有什么,目标所在的位置,还要告诉你目标在图像里是个什么形状。

在这里插入图片描述

上面这张图,形象的描述了CV中的几个基础问题, 从识别,到检测,到分割,正如我们所看到的,从图像全局层面,到图像的局部,再到图像的像素层面,一层一层的递进。

识别,是研究的最多,也相对最成熟的一个领域,从物体识别,人脸识别到细粒度识别。从传统的特征提取比如 LBP, HOG, SIFT 以及 BoW,multi-scale,高斯金字塔,到如今的 CNN,数据规模也越来越大; 从开始的成百上千,到如今的几十万,几百万的数据规模,曾经被认为高不可攀的 ImageNet,如今也渐渐的成为过去, 当人们渐渐发现,数据堆砌到一定程度,似乎也不会换来性能的明显提升时,所有人也陷入沉思,可能数据的 “质量”,比数据的 “数量” 更加重要。对于全图层面的识别,背景的干扰很大,其实,人类视觉非常厉害的一点就是选择性 “聚焦”,也就是说,可以自动聚焦到自己所关注的目标上面,并且排除其他无关背景的干扰。

所以,简单的单一主体明确的图像识别,可能不是什么问题了,而真实的世界里,场景总是很复杂的,越来越多的人将目光聚焦到了检测,分割上面。

检测,是介于全局与像素之间的一个层面,从局部考察图像的特征。在 CNN 流行起来之前,最常用的检测就是人脸检测了,通过滑动窗口,提取不同 scale 的特征,利用 Ada-boost 进行分类。

目标检测的概念

目标检测,目前来说,有两种思路,一种是基于候选区域的,比较有代表性的就是 R-CNN 系列; 另外一种,就是利用滑动窗系列的,比如 SSD, 以及 YoLo 系列都是属于滑动窗系列。

  • 基于候选区域的检测方法
    这种方法,就是利用分割的方法,先提炼出某些候选区域,然后在这些候选区域上进行识别,回归,找出含有目标物的区域,再利用一些合并原则,将一些区域合并,这种方法的优点是准确度比较高,缺点是慢,因为这是一种 two-stage 的方式,也就是说要分两步才能实现。这类算法的代表是 R-CNN, Fast-RCNN 以及 Faster-RCNN 系列。

  • 基于滑动窗的检测方法
    这种方式,就是把图像分成很多规则的窗口,然后一个窗口一个窗口进行判断,考虑到多尺度的问题,所以也会有多尺度的窗口,然后再进行分类。这种方式在 深度 CNN 时代,似乎有着天然的优势,因为我们知道,CNN 的 feature map 上的点,在原始的输入图像上,都会有对应的 receptive field,这些 receptive field 就类似在图像上画出的窗口,不同的卷积层,对应的 receptive field 的大小也不一样,所以 SSD 利用这个性质,可以直接将多尺度的目标检测,在一个 CNN 网络中实现,不过,这种方式的一个缺点是,准确率没有基于候选区域的方式高,因为一张图像,一般来说,目标区域占比较少,而背景区域一般占比较大,所以,这也会造成图像中的正样本会比负样本少很多,训练的时候,模型可能会偏向负样本,所以滑动窗口的方式,训练的时候,正负样本的比例要保证,不能负样本过多。这类算法的代表是 SSD 以及 YOLO 系列。

目标检测中的多尺度问题

我们都知道,图像中的目标,一般来说都是多尺度的,有的目标大,有的目标小,为了解决图像检测中的多尺度问题,我们可以从两个角度考虑:

  • 一个是改变输入图像的尺度,这是我们容易想到的一种方法,通过改变输入图像的尺度,进而改变了目标的尺度,这个在目前的图像增广中,是比较常用的一种策略,我们可以改变输入图像的尺度,让网络见识到不同大小的图像。
  • 另外一种,就是改变滑动窗口的大小,这就像用网捕鱼一样,不同的网眼,可以捕获不同大小的鱼,在目标检测中,我们可以通过改变滑动窗口的大小,来做多尺度的目标检测,这个策略在目前的目标检测网络中非常流行,比如 SSD, YOLO 和 FPN 等,他们巧妙的利用 CNN 中不同层的 feature map 其实就对应了原始图像中不同大小的滑动窗这个特性,构建了多尺度的目标检测的网络结构。

目标检测中的样本不平衡问题

一般训练模型的时候,我们都希望样本能够均衡,如果样本不均衡,会让模型偏向于样本多的类别,目标检测,是一个典型的样本分布不均衡的问题,因为对于一张图像来说,一般都是背景区域的占比面积远远大于目标区域的占比面积,这样就会导致每次训练输入网络的负样本会多于正样本,这不利于网络的训练,为了保证样本的一定均衡,在目标检测的训练中,一般都会用一定的样本选择策略,一般是保证正反样本的比例大致为 1:3,为啥是这个比例,可能也是实验验证出来的吧,没有什么道理可言。
另外,为了提升模型的泛化能力,一般都会做一些困难样本的挖掘,让模型对困难样本拟合的更好,一般训练集中,肯定是容易拟合的样本占大多数,而困难样本一般占比较少,这也是一个不均衡的问题,也就是所谓的难易样本不均衡问题,为了解决这个问题,一般是针对性的对困难样本进行挑选,或者修改 loss 的设计,不管是困难样本挖掘还是修改 loss,对困难样本的 loss 赋予更高的权重,本质上来说,都是为了提高困难样本在整个数据集上的比重,这里比较简单优雅的就是 focal loss 这种方法,focal loss 是在常规的二分类 loss 上修改而来,常规的二分类loss 就是一个二分类交叉熵:

L = y log p + ( 1 y ) log ( 1 p ) L = y\log p + (1-y) \log (1-p)

这种 loss 对所有样本是一视同仁的,不会区分样本的难易程度,这种 loss 在样本均衡的时候,还是可以的,如果样本不均衡,loss 就会好逸恶劳,趋向于拟合大量的容易样本,忽视掉少量的困难样本,为了让模型重视困难样本的拟合,就要加大对困难样本的权重,所有 focal loss 就是从这点出发,设计了如下的 loss 函数:

F L ( p t ) = α t ( 1 p t ) γ log ( p t ) FL(p_t) = -\alpha_{t}(1-p_{t})^{\gamma} \log (p_{t})

这个 loss 既考虑了样本整体的分布(通过 α t \alpha_{t} 体现),也考虑单个样本的训练难易(通过 γ \gamma 的调节 )

目标检测中的 loss 设计

目标检测中的 loss 设计,也是非常重要的,不同的网络结构,也会有不同的 loss 设计,不过总的来说,目标检测中的 loss 一般包含两个部分,一部分是分类 loss, 一部分是回归 loss,分类 loss 就是用来确定当前的滑动窗里具体是什么类别,而回归 loss 用来评判当前的滑动窗对目标框的回归精度,所以检测算法中一般会有两个loss

L = L c l f + L r e g L = L_{clf} + L_{reg}

我们以 YOLOv3 的框架为例,来看检测中的 loss 设计,YOLOv3 应该是目前很受工业界青睐的一个检测框架,很好的平衡了速度与精度,并且结构相对来说简单清晰,这个框架也借用了多尺度检测的概念,每个 box 的输出是 4 + 1 + C 的维度,4 表示 box 的参数,中心位置 ( c x , c y ) (c_x, c_y) 以及 box 的宽,高 w , h w, h ,1 是一个二分类,表示这个 box 是否含有物体目标,而 C 表示类别数量,为了能够更好的拟合,YOLO v3 将预测值做了一些处理:

b x = σ ( t x ) + c x b y = σ ( t y ) + c y b w = p w e t w b h = p h e t h b_x = \sigma(t_x) + c_x \\ b_y = \sigma(t_y) + c_y \\ b_w = p_w e^{t_w} \\ b_h = p_h e^{t_h}

其中 t x , t y t_x , t_y 表示预测 box 的中心坐标, t w , t h t_w, t_h 表示预测 box k宽,高,这里都经过了一些处理,以便更好地收敛。所以 YOLO v3 一共有四部分的 loss,

L = L x y + L w h + L o b j + L c l f L = L_{xy} + L_{wh} + L_{obj} + L_{clf}

前面两个是回归 loss,用来预测框的位置以及大小,第三个是二分类 loss,表示该框是否含有目标物体,最后一个是分类 loss,这里没有用 softmax,而是用二分类交叉熵来实现的多分类,这个 loss 对于多目标的识别效果更好

目标检测中的 NMS 处理

我们知道,目标检测,一般都会输出很多的预测框,很多框是高度重合的,这个时候,就需要对这些框进行处理,目标检测中一般会用到一种 Non-maximum suppression (非极大值抑制)的方法,非极大值抑制的方法,可以保证从多个预测框中,最后挑选出置信度最高的一个框。NMS 的算法原理也比较简单,就是利用集合中的交与并的概念,计算两个框的 IOU, 要计算 box a, b 的 IOU 可以用如下的表达式:

I O U = a b a b IOU = \frac{a \cap b}{a \cup b }

很显然,如果 a,b 完全重合,则 IOU 为 1,如果 a, b 没有任何交集,则 IOU 为 0,用 IOU 可以衡量两个 box 的重合度,对于重合度高的 box,是可以删掉冗余的,这就是 NMS 的原理。

NMS 实现的时候,一般是先选择一个置信度最高的 box,然后用剩余的 box 与该 box 计算 IOU,对于 IOU 高于某个阈值的,就直接删除,剩下的就是与该 box 重合度较低的,然后从剩下的 box 里,再选择一个置信度最高的,重复上面的步骤,这样直到所有的 box 都被遍历完,对于多个类别的情况,可以单独对每个类做 NMS,经过 NMS 的处理,一般一个区域就会只剩下一个 box 框。

发布了219 篇原创文章 · 获赞 211 · 访问量 113万+

猜你喜欢

转载自blog.csdn.net/shinian1987/article/details/84452907
今日推荐