点击上方“蓝字”关注“AI开发者”

原标题 | Demystifying Object Detection and Instance Segmentation for Data Scientists

作者 | Rahul Agarwal

翻译 |  天字一号、孤独818、熊壮

审校 | 鸢尾、唐里

注:敬请点击文末【阅读原文】访问文中相关链接,PC查看体验更佳。

我喜欢深度学习,但目标检测对我来说并不容易。

目标检测很重要,并且确实有其用途。最常见的应用是自动驾驶汽车、医学成像和面部检测。

目标检测很难,它在漫长的历史中不断的变换和引入新概念,因此就更难理解了。本篇文章将目标检测的历史提炼成一个简单的解释,并解释目标检测和实例分割的细节。

  介绍

我们都知道图片分类问题:能否对给定的图片进行分类?

我们可以使用卷积神经网络以及用已经训练好的网络进行迁移来处理任何图片分类问题。

使用在ImageNet数据集上已经训练好的卷积神经网络模型作为固定的特征提取器,移除最后一层全连接层(这一层的输出是针对像imageNet一样有一千种类别的分类任务),然后训练这个网络模型的其他部分作为新数据集的特征提取器,在AlexNet模型中,这一方法将对在分类器之前(即最后全连接层)对每一个包含激活的隐藏层直接计算一个4096维的向量。我们将他们称之为卷积神经网络中的特征,如果在这些数据集上进行卷积神经网络计算之前对他们进行了阈值处理(一般都会处理),那么将这些代码进行ReLU处理对代码的表现十分重要(设置阈值维0)一旦你对每张照片都提取4096维的代码,为新的数据集训练一个线性分类器(如:SVM Softmax)

但是在图像处理领域还有很多其他有趣的问题:

via http://cs231n.github.io/transfer-learning/#tf  

这些问题可以具体划分为四个主要的方向,在我们进行深层次的讨论前我先为你们简要介绍一下这四个问题:

1.语义分割: 给定一张图片,我们能不能对每个像素点分类

2.分类加定位: 我们已经可以划分图片为猫,但是我们能不能通过在猫周围画锚框来获取猫的位置呢?这里我们先假设图片上只有猫这一个物体

3.对象检测: 分类与定位的一般情况:在实际情况下,我们不知道一张图片上有多少个物体,所以我们能不能检测并用锚框框选出图片上的所有物体呢?

4.实例分割: 我们能不能对图片上的每个对象创建标签?与语义划分不同,为什么?如果你看上面的第四张图,我们无法用语义分割具体区分这两只狗,因为他们某种意义上被划分在一起了。

如你所见,以上这四者之间既有一些相同之处但也有一些不同之处,这篇文章中,我将 重点介绍对象检测以及实例分割 ,因为他们最有趣。我将介绍四种著名的对象检测技术,以及他们随时间与新思想的发展取得的进展。

  分类+定位

因此,让我们首先尝试了解当图像中只有一个目标时,我们如何能够解决这个问题。分类+定位案例。

:bulb:  将定位视为回归问题!

via http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture11.pdf

输入数据

让我们先来谈谈这种模型需要什么样的数据。通常,在图像分类设置中,数据是 (X,y),通常采用 X 是图像,y 是类标签的类别。

在 分类+定位 设置中,我们将通常以 (X,y) 的形式(X,y)提供数据,其中 X 仍然是图像,y 是包含 (class_label, x,y, w, h) 的数组,

x = 边界框左上角 x 坐标

y = 边界框左上角 y 坐标

w = 边界框的宽度(以像素为单位)

h = 边界框的高度(以像素为单位)

模型

因此,在此设置中,我们创建一个多输出模型,该模型以图像为输入,具有(n_labels + 4)个输出节点。n_label用于每个输出每个类的节点和 4 个提供预测 (x,y,w,h) 的节点。

损失

通常,损失是 Softmax 损失(来自分类问题)和回归 L2 损失(来自边界框坐标)的加权总和。

Loss = alpha*Softmax_Loss + (1-alpha)*L2_Loss

由于这两个损失将处于不同的尺度上,因此 alpha 超参数需要调整。

有一件事我想在这里提醒一下,我们正在尝试执行目标定位任务,但这里仍有我们的卷积神经网络。我们只是增加了一个输出层,也预测边界框的坐标和调整我们的损失函数。

这里就是整个深度学习框架的精髓—— 将层叠在一起,重用组件以创建更好的模型,并创建架构来解决您自己的问题。 而这正是我们接下来将会看到的内容。

  目标检测

那么,这种使用回归进行定位的想法是如何映射到目标检测的呢?实施情况不是这样的。

我们没有固定数量的目标。因此,我们不能有4个输出表示边界框坐标。

一个最简单的想法是将CNN应用于图像的许多不同切片上,CNN 将每个切片分类为目标类或背景类。但这可能会创造太多这样的切片。

区域建议:

因此,有一个方法(通常称为区域建议网络),它可以为我们自动找到一些较小的裁剪区域,我们可以在这些区域上运行 convnet,然后完成目标检测。这就是在物体检测方面取得的第一个重大突破RCNN算法背后的基本理念。

这就是选择性搜索(Uijlings等人,"目标识别的选择性搜索",IJCV 2013,http://www.huppelen.nl/publications/selectiveSearchDraft.pdf)所提供的。

那么,什么是区域建议?

  • 查找可能包含目标的"blobby"图像区域

  • 运行速度相对较快;例如,选择性搜索在几秒钟内在 CPU 上提供 2000 个区域建议

那么,区域建议究竟是如何提出的呢?

选择性搜索目标识别

(http://www.huppelen.nl/publications/selectiveSearchDraft.pdf)

本文分两步查找区域。

首先,我们从一组使用P.F.Felzenszwalb和D.P.Huttenlocher提出的基于图的图像分割方法提取初始区域开始(http://people.cs.uchicago.edu/~pff/papers/seg-ijcv.pdf)。

基于图的图像分割技术通常以图 G = (V, E) 表示问题,其中每个节点 v + V 对应于图像中的像素,E 中的边缘连接某些相邻像素对。

在本文中,他们采取了一种方法:

每个边 (vi, vj )∈ E 具有相应的权重 w((vi, vj)),这是相邻元素 vi 和 vj 之间的 相似性的非负度量 。在基于图的方法中,分段 S 是 V 到组件的分区,以便每个组件(或区域)C∈S 对应于图中的连接组件。

简而言之,它们使用基于图形方法查找图像中的连接组件,边缘是在像素之间的某种相似性测量上进行的。

正如您所看到的,如果我们在这些掩码周围创建边界框,我们将失去很多区域。我们希望让整个棒球运动员在一个单一的边界框/框架。我们需要以某种方式对这些初始区域进行分组。这是第二步。

为此, 选择性搜索对象识别 (http://www.huppelen.nl/publications/selectiveSearchDraft.pdf)的作者将分层分组算法应用于这些初始区域。在此算法中,它们基于颜色、纹理、大小和填充的不同相似性概念将大多数相似区域合并在一起,从而为我们提供了更好的区域建议。

RCNN 中使用的区域建议算法

  1. R-CNN

现在我们有了区域建议,在R-CNN中准确使用它们?

目标检测系统概述。我们的系统

(1) 获取输入图像(2) 提取大约 2000 个自下而上的建议区域(3) 使用大型卷积神经网络 (CNN) 计算每个建议区域的特征(4) 使用类特定的线性 SVM 对每个区域进行分类。

此外,作者还使用了类特定的边界框回归器,该回归器需要:

输入 :(Px、Py、Ph、Pw) = 建议区域的位置。

目标:(Gx、Gy、Gh、Gw)=该区域地面真实标签。

目标是学习将建议区域 (P) 映射到地面真正框 (G) 的转换

训练 R-CNN

RCNN 的输入是什么?

我们得到图像,利用RPN策略得到的建议区域和地面目标真正标签框(标签,地面标签框)

接下来,我们将所有区域建议与地面真实标签框IoU(交并比)大于等于 0.5 的,作为该检测框训练的正样本,其余建议为负样本。我们训练特定类的 SVM分类。每个区域的建议都成为训练示例,convnet 提取该区域的特征矢量。然后,可以使用特定类的数据来训练 n-SVM。

测试时间 R-CNN

在测试时,我们使用特定于类的 SVM 预测检测框。在测试时,我们将得到很多重叠的检测框。因此,非最大抑制是目标检测算法中的重要组成部分。

首先,它根据所有检测框的分数对它们进行排序。选择具有最大分数的检测框 M,并去掉与 M 大于一定重叠阈值的所有其他检测框。

此过程递归应用于所有剩余的框,直到我们只剩下良好的边界框。

https://www.pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_nms.jpg

RCNN 的问题

  • 训练速度慢

  • 利用VGG16检测一张图像需要47秒,卷积神经网络的提取需要很长时间

为了提高速度,出现了Fast R-CNN。

  2. Fast R-CNN

:bulb:那么,作者的下一个想法:为什么不创建输入图像的卷积图,然后从卷积图中选择区域?我们真的需要运行这么多的convnets吗?我们可以做的是只运行单个 convnet,然后在 convnet 计算的特征上应用区域建议裁剪块,并使用简单的 SVM/分类器对这些裁剪块进行分类。

像这样:

来自论文 (https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/Girshick_Fast_R-CNN_ICCV_2015_paper.pdf) :上图说明了Fast R-CNN 体系结构。Fast  R-CNN 网络将整个图像和一组目标建议框作为输入。网络首先使用多个卷积和最大池图层处理整个图像,以生成 conv 特征图。然后,对于每个目标建议感兴趣的区域 (RoI) 池图层从特征图中提取固定长度的特征矢量。每个特征矢量被输入一个全连接的图层 (fc) 序列中,这些图层最终分支为两个同级输出层:一个在 K 目标类上生成softmax最大概率估计值,外加一个捕获的"背景"类,另一个图层输出每个 K 目标类的四个实际值数字。每组 4 个值对其中一个 K 类的细化边界框位置进行编码。

:bulb: 新想法

因此, 基本的想法是必须只在图像中运行一次卷积,而不是在 R-CNN 中运行这么多卷积网络。 然后,我们可以使用某种方法映射 ROI 建议区域,并筛选最后一个卷积层,然后运行最终分类器。

这个想法有点依赖于模型的体系结构,但也很有用。

因此,作者提出的体系结构是:

我们试验了三个预先训练的 ImageNet 网络,每个网络具有五个最大池化层和五到十三个 conv 层(有关网络详细信息,请参阅第 4.1 节)。当预先训练的网络初始化FastR-CNN 网络时,它将经历三次转换。首先,最后一个最大池化层被一个 RoI 池化层替换,该层通过将 H 和 W 设置为与网络的第一个全连接层兼容(例如,VGG16 的 H = W = 7)。其次,网络的最后一个全连接层和 softmax(经过 1000 分支的ImageNet 分类训练)替换为前面描述的两个同级层(K + 1 类别和特定类别的全连接层和 softmax边界框回归器)。第三,修改网络以获取两个数据输入:图像列表和这些图像中的 RoI 列表。

如果你不了解上面的意思,别担心。这显然有点令人困惑,所以让我们来分解一下。但是,我们需要先看到VGG16架构。

VGG 16 架构

最后一个池层是 7x7x512,这就是网络的作者打算用 ROI 池化层替换的层。此池化层作为输入区域建议(xmin_roi、ymin_roi、h_roi、w_roi)和前一个特征图(14x14x512)。

  

我们需要固定大小的特征图来用于最终分类器

现在,ROI 坐标的位置是以图像为单位的,如224x224 像素。但是,我们应用 ROI 池操作的层大小是 14x14x512。

在使用 VGG 时,我们将图像 (224 x 224 x 3) 转换为 (14 x 14 x 512), 即高度和宽度除以 16。我们可以通过将 ROIs 坐标除以 16 来将 ROIs 坐标映射到特征图上。

卷积特征图在其深度上对图像的所有信息进行了编码,同时保持了它编码的"事物"相对于原始图像的位置。例如,如果图像左上角有一个红色方块,并且卷积图层为其激活,则该红色方块的信息仍将位于卷积要素图的左上角。

什么是ROI Pooling?

由于候选框大小不一样,得到的特征图大小也不一样,但是全连接层要求输入的向量大小是固定的,如何把全连接层前面的特征图变成相同大小的特征图呢?这时就要用到ROI Pooling。ROI Pooling是一种类似于Max Pooling的操作。

(图片来源:https://deepsense.ai/region-of-interest-pooling-explained/)

对于上图,假设我们的候选区域是(x, y, w, h) =(0, 3, 5, 7),则候选区域可视化如上图黑框所示。

如果我们使用的ROI pooling的大小为2×2,那么将会把原候选区域分成4个区域,但是由于原候选区域的大小是5×7,5/2=2.5,7/2=3.5,这时一般进行四舍五入得到四个不同大小的子区域,如下图所示是其中一种切分方式。

如果候选区域的大小比ROI Pooling核的大小更小该怎么办呢?例如,候选区域大小是5×5,而ROI Pooling层核的大小为7×7。这时,我们可以将输入图片resize到35×35然后使用最大池化得到7×7的输出。

经过池化后,作者将原始ImageNet的最后一个输出1000维度的全连接层换成了经过softmax函数的全连接层,维度为(K+1),其中K是类别数目,1代表背景类别以及指定类别的候选框回归。

训练Fast-RCNN

Fast-RCNN的输入是什么呢?

和R-CNN非常类似,我们需要准备一张图片、区域候选框(由RPN策略获得)以及类别相关的标定值(类别标签、标定框)。

然后我们将与标定框IoU大于等于0.5的区域候选框当作训练集标定框的正样本,其余的候选框当作负样本。使用这些候选框进行多任务损失训练。

因此,所有的ROI都会成为训练样本,与RCNN不同的是,这里有个多任务损失函数的概念:

Fast R-CNN有两个并联输出层。

其中一个输出层输出K+1个类别在每个ROI上的离散概率分布,p = (p0, . . . , pK)。通常,p是通过全连接层后的softmax函数计算得来。

另一个输出层输出边界框的回归偏置, t= (tx, ty, tw, th)。每一个训练ROI都有一个类别标签u和真实标定边界框v,我们对每一个标定的ROI使用多任务损失函数L进行分类和边界框的联合训练。

分类损失+回归损失

其中Lcls是softmax分类损失,Lloc是回归损失。当u=0时,代表类别为背景,因此我们计算u大于等1的损失,其对应的是真实物体类别。

问题:

下图显示,虽然Fast R-CNN相较于R-CNN的测试时间显著减少,但是诊断时的区域候选框的生成仍然占用大量测试时间。考虑是否可以减少区域候选框的生成时间?

候选框生成占主要的测试运行时间!

  3. Faster-RCNN

下一个问题是:能否实现网络自身可以提取建议区域?

一个想法是:我们使用 Fast RCNN在 CNN 中计算激活图,为什么不通过再多加几个图层运行在激活图上查找兴趣区域,然后通过预测类 + bbox 坐标来结束前向传播?

区域建议网络怎么工作的?

本文的主要思想之一是锚点想法。锚点是固定边界框,放置在整个图像中,其大小和比率不同,将用于在首次预测对象位置时参考。因此,首先,我们在图像上定义锚点中心

在原始图像中定位中心

在 VGG16 网络的情况下,锚点中心以 16 px 分隔,因为 (14x14x512) 子卷积层对图像进行 16倍(224/14) 的降采样。

这是锚点的外观:

左:锚点,居中:单个点的锚点,右侧:所有锚点

1.我们从一些预定义区域开始,我们认为我们的目标可能再在锚点上。

2.我们的区域建议网络 (RPN) 对哪些区域具有目标和目标边界框的偏移量进行分类。训练使用相同的逻辑回归完成。如果 IOU >0.5时为1,否则为0。

3.非最大抑制以减少区域建议

4.Fast RCNN 在建议区域上的检测网络

Fast  RCNN 损失

然后,整个网络联合训练,有 4 个损失:

1.RPN 对目标/非目标进行分类

2.RPN 回归框坐标偏移

3.最终分类分数(目标类)

4.最终框坐标偏移

性能

三种不同方法的 VOC 数据集结果

  实例分割

现在最有趣的部分 - 实例分割。我们可以为图像中的每个对象创建蒙版吗?具体来说,例如:

论文中的蒙版例子

  Mask-RCNN

来自同一个作者的文章。基本的想法是添加另一个输出层来预测蒙版。并使用 ROIAlign 而不是 ROIPooling。

一切都保持不变,只需再增加一个输出层,用于预测蒙版, ROI 池并替换为 ROIAlign。(https://medium.com/@jonathan_hui/image-segmentation-with-mask-r-cnn-ebe6d793272)

Mask R-CNN 采用相同的两阶段过程,第一阶段 (RPN) 相同。

在第二阶段,在预测类和框偏移量的同时,Mask R-CNN 还会为每个 RoI 输出一个二进制掩码。

ROI Align vs ROI Pooling

在ROI Pooling中我们丢失了精确的基于位置的信息,如下图所示,我们将区域任意分成了四个不同大小的框。对于分类问题而言,这样做是没有问题的。

但是在像素级别提供MASK时,我们不希望丢失基于位置的精确信息。因此,我们不量化池层并使用双线性插值来找出正确对齐提取的特征与输入的值。看看0.8和0.88有什么不同。

(图片来源:https://medium.com/@jonathan_hui/image-segmentation-with-mask-r-cnn-ebe6d793272)

训练

训练时,我们在每一个抽样的ROI上定义一个多任务损失函数为:

L = Lcls + Lbox + Lmask

分类损失Lcls和边界框损失Lbox与Faster R-CNN中的相同。掩码分支为每一个ROI输出一个K×m×m维特征图,对应着K个种类,每个种类的二值掩码大小为m×m。

为此,我们将每个像素通过sigmoid,并定义Lmask为平均二元交叉熵损失。对于一个拥有类别k的ROI,Lmask只决定于第k个掩码,其他掩码输出对其损失没有贡献。

Mask Prediction

掩码层输出K×m×m的特征图,其中K时类别的个数。将m×m浮点数掩码输出调整为ROI的大小,并以0.5的阈值进行二值化以获得最终的掩码。

  结论

祝贺你看完了这篇文章。这篇文章很长。

在这篇文章中,我谈到了目标检测和实例分割领域的一些最重要的进展,并试图尽可能轻松地解释它们。

这是我自己对这些论文的理解,参考了许多互联网上的博客和幻灯片,我衷心感谢创作者。如果你发现我的理解有问题,请告诉我。

目标检测是一个广阔的领域,并且有许多其他方法主导这一领域。其中一些是U-net,SSD和YOLO。

可以有很多资源去学习它们,所以我鼓励你去看看它们。你现在有了坚实的支持/理解。

在这篇文章中,我没有写关于编码和实现。因此,请继续关注我的下一篇文章,我们将在其中为自定义数据集训练Mask RCNN 模型。

如果您想了解更多关于各种目标检测技术,运动估计,视频中的目标跟踪等,我想推荐这个高级机器学习专业中的深度学习计算机视觉课程。

via https://towardsdatascience.com/a-hitchhikers-guide-to-object-detection-and-instance-segmentation-ac0146fe8e11

  点击 阅读原文 ,查看:如何用TensorLayer做目标检测的数据增强

相关文章