Mask_RCNN训练自己的数据,制作类似于COCO数据集中所需要的Json注释

#2018/05/22 更新

使用训练好的Mask_RCNN模型进行预测看这里:


https://blog.csdn.net/qq_15969343/article/details/80388311

该Mask_RCNN版本为基于:Python3,Keras,TensorFlow,我使用的具体版本为:

  • Python 3.6.3
  • TensorFlow 1.7
  • Keras 2.1.5
  • PyQt5  5.9.2
  • VIA 1.0.5

tensorflow安装:

https://blog.csdn.net/qq_15969343/article/details/79971469

Mask-RCNN :

https://github.com/matterport/Mask_RCNN

安装scikit-image(0.14):

https://blog.csdn.net/qq_15969343/article/details/79957924


标注工具(墙裂推荐VIA):

VGG Image Annotator(VIA):

http://www.robots.ox.ac.uk/~vgg/software/via/

备选标注工具:

labelme:

https://github.com/wkentaro/labelme

RectLabel:

https://rectlabel.com/

LabelBox:

https://www.labelbox.io/

COCO UI:

https://github.com/tylin/coco-ui


这篇文章中,我将介绍两件事情:首先是Mask RCNN的概述。 其次,如何从头开始训练模型并用它来进行实例分割。


什么是实例分割?

实例分割是在像素级识别对象轮廓的任务。 与类似的计算机视觉任务相比,这是最困难的视觉任务之一。如下:



分类:此图像中有气球。

语义分割:将气球和背景分离出来。

对象检测:在这些位置的图像中有7个气球,并且给出每个气球的位置。

实例分割:在这些位置的图像中有7个不同的气球,在像素层面给出属于每个气球的像素。


1.Mask R-CNN

Mask R-CNN(区域卷积神经网络)是一个两阶段框架:第一阶段扫描图像并生成proposals(可能包含对象的区域)。 第二阶段对proposals进行分类并生成边界框和掩码。

它是2017年时,在其前身Faster R-CNN的基础上提出的。 Faster R-CNN是一种流行的对象检测框架,Mask R-CNN通过添加mask进行实例分割对其进行了扩展。


                      Mask R-CNN framework. Source: https://arxiv.org/abs/1703.06870

首先,Mask R-CNN由以下几部分组成:


1.1.骨干网络(Backbone)

这是一个标准的卷积神经网络(通常是ResNet50或ResNet101),我们用它来提取特征。 较低层检测低级特征(边缘和角落),后续层检测更高级别的特征(汽车,人物,天空)。

通过骨干网络,图像从1024x1024x3(RGB)转换为形状为32x32x2048的feature map,并且成为后续阶段的输入。


1.1.1特征金字塔网络(Feature Pyramid Network)

虽然上述骨干网络很好,但是可以改进。特征金字塔网络可以更好地在多个尺度上进行检测。该Mask RCNN的实现使用ResNet101 + FPN。

1.2. 区域提议网络(Region Proposal Network,RPN)

RPN是一个轻量级的神经网络,以滑动窗口的方式扫描图像并找到包含对象的区域。RPN扫描的区域称为 锚点也就是分布在图像区域上的红框,如上图所示。不过,这只是是一个简化的视图。实际上,大约有200K的不同尺寸和高宽比的锚,它们重叠覆盖尽可能多的图像。

RPN扫描速度有多快?其实很快。滑动窗口允许它并行扫描所有区域(在GPU上)。此外,RPN不会直接扫描图像(即使我们在图像上绘制锚点以便说明)。相反,RPN扫描骨干网络生成的Feature map。这允许RPN有效地重用提取的特征并避免大量的重复计算。根据Faster-RCNN的论文,RPN运行大约10 ms。在Mask RCNN中,我们通常使用更大的图像和更多的锚点,因此可能需要更长的时间。针对每个锚点,RPN有 两个输出

1.锚点的种类:前景或背景。前景类意味着该框中可能有一个对象。

2.边界框细化:前景锚点(也称为正锚点)可能没有完全正对该对象。 因此,RPN会输出一个很小的微量变化(百分比):(x, y, width, heigh),以更好地适应物体。

使用RPN预测,我们选择可能包含对象并优化其位置和大小的顶部锚点。如果几个锚点重叠太多,我们会保留具有最高前景分数的锚点并丢弃其余的(称为非极大值抑制:Non-max Suppression)。在这之后我们会得到进入下一阶段的最终提案(感兴趣的区)。


1.3.ROI分类器和边界框回归(ROI Classifier & Bounding Box Regressor)

这个阶段运行在RPN提出的感兴趣区(ROI)上。就像RPN一样,对每个ROI生成两个输出:


                Illustration of stage 2. Source: Fast R-CNN (https://arxiv.org/abs/1504.08083)

1.具体的类别:ROI中对象的类。 与具有两个类别(前景/ 背景)的RPN不同,该网络更深并且具有将区域分类为特定类别(人,车,椅子等)的能力。并且它也可以生成背景类,这样可以让部分消极的ROI被丢弃。

2.边界框细化:与RPN中的完成方式非常相似,其目的是进一步细化边界框的位置和大小以包含对象。


1.3.1ROI池化

在进行下一步之前,有一点问题需要解决:分类器不能很好地处理可变的输入大小。通常需要固定的输入大小。 但是,由于RPN中的边界框细化步骤,ROI框可能具有不同的大小。 这时就需要ROI Pooling。


ROI池化是指裁剪feature map的一部分并将其大小调整为固定大小。 原则上类似于裁剪图像的一部分,然后重新调整大小(但实现细节存在差异)。Mask R-CNN的作者提出了一种称为ROIAlign的方法,他们在不同的点对feature map进行采样并应用双线性插值。 在我们的实现中,为了简单起见,我们使用了TensorFlow的crop_and_resize函数,因为它对于大多数目的来说已经足够用了。


1.4. 分割掩膜(Segmentation Masks)

如果你在上一步停下来,那么你已经得到了Faster R-CNN来进行对象检测。 而Mask网络是则是在其上进行的扩展:
该Mask网络分支是一个卷积网络,它采用由ROI分类器选择的正区域并为它们生成mask。生成了低分辨率的mask:28x28像素。但它们是以浮点数表示的soft masks,因此它们比二进制的mask拥有更多的细节;低分辨率的mask可以得到轻量级的Mask网络。 在训练期间,我们将mask缩小到28x28以计算Loss,并且在预测期间,我们将mask放大到ROI边界框的大小,得到了最终的mask。

2.利用Mask R-CNN进行实例分割

生成的示例1

示例2

2.1训练数据

首先,你可以搜索公共的数据集:像COCO这一类,在这里,我会展示如何从头开始构建自己的数据集。为了训练时间的减少,我总共选取了75张图片,并将它们分为训练集和验证集。得到图像很容易。注释图像才是困难的部分。


等等!难道我们不需要一百万幅图像来训练深度学习的模型吗?有时候你会,但在这里我们并没有那么多数据。因此,基于以下两点来显著减少训练样本的数量:

1.迁移学习

这意味着,不是从头开始训练模型,而是从COCO数据集上训练的权重文件开始。尽管COCO数据集不包含气球类别,但它包含许多其他图像(大约120K),因此训练后的权重已经学习了很多自然图像中常见的特征,这是非常有帮助的。

2.只是一个简单的示例

在这里,只是为了阐述如何实现Mask-RCNN,因此,并不需要这个模型有很高的准确性,这个小数据集已经足够了。

有很多工具来注释图像。根据其简单性,我最终使用了VIA(VGG Image Annotator)。这是一个单独的HTML文件,你可以下载并在浏览器中打开:


如果你不喜欢VIA,你也可以使用以下工具:

VGG Image Annotator(VIA):快速,轻便,设计精良。这是我最终使用的那个。我使用其中的rectangle进行标记,其中用到了skimage,但是现在发行的版本还不能使用rectangle,因此你需要从源码编译安装,见这篇文章:

从github下载开发者版本的源码进行编译安装scikit-image(0.14)

Labelme:最知名的工具之一。 但是UI有点太慢了,尤其是在放大图像时。它的具体使用方式见我的另外一篇博客:

Mask_RCNN训练自己的数据,其中Labelme的使用说明

RectLabel:简单易用。但是仅限Mac。

LabelBox:适用于大型标签项目,并且可以选择不同类型的标签。

COCO UI:用于注释COCO数据集的工具。


2.2加载数据集

掩码的加载方式并没有普遍接受的格式。 一些数据集将它们保存为PNG图像(像labelme),其他数据集将它们存储为多边形点(VIA, COCO)等等。 为了处理这些情况,需要实现提供一个继承的Dataset类,然后重写几个函数以便以恰好的格式读取数据。

VIA工具将注释保存在JSON文件中,每个掩码都是一组多边形点。 通过查看生成的JSON很容易找到这些注释。 我在代码中加入了注释来解释这是如何完成的。

小提示:为新数据集编写代码的简单方法是复制coco.py并将其修改为自己所需要的。在这里,以气球为例子,并且将新文件保存为balloons.py

我的BalloonDataset类看起来像这样:

class BalloonDataset(utils.Dataset):
     def load_balloons(self,dataset_dir,subset):
        ...
     def load_mask(self,image_id):
        ...
     def image_reference(self,image_id):
        ...

load_balloons读取JSON文件,并且提取注释,并迭代调用内部的add_classadd_image函数来构建数据集。

load_mask通过绘制多边形为图像中的每个对象生成mask。

image_reference只是返回一个字符串,用于识别图像以进行调试。 这里它只是返回图像文件的路径。

你可能已经注意到这个类不包含加载图像或返回边界框的函数。这是因为基础数据集类中默认的load_image函数处理加载图像。 而且,边界框是从mask动态生成的。


2.2.1验证数据集及代码是否正确

为了验证新代码是否正确实现,需要加载数据集,可视化mask和边界框,并可视化锚点以验证的锚点大小是否适合对象的大小:


2.3配置


此项目的配置与用于训练COCO数据集的基本配置类似,所以只需要重写3个值即可。 正如上述对Dataset类所做的那样,可以从基础配置类继承并添加需要修改的值:

class BalloonConfig(Config):
    # Give the configuration a recognizable name
    NAME = "balloons"
    # Number of classes (including background)
    NUM_CLASSES = 1 + 1  # Background + balloon
    # Number of training steps per epoch
    STEPS_PER_EPOCH = 100

基本配置使用尺寸为1024x1024的输入图像以获得最佳准确性。但是你的图像可能尺寸大小不一,别怕!该模型可以自动调整大小,如果你实在不放心的话,你也像我一样可以自己写个程序调整尺寸。


2.4训练

Mask R-CNN是一个相当大的模型,特别是我们使用ResNet101和FPN。所以你需要一个具有12GB内存的GPU。在这里,我们应该从预先训练好的COCO权重开始,并且只需要训练Heads即可,毕竟我们的数据集很小;当然,你也可以全部层都训练,但是那样速度很慢。


2.5检查结果

inspect_balloon_model文件显示训练模型生成的结果。你可以查看其中的其他细节,结果如下:


猜你喜欢

转载自blog.csdn.net/qq_15969343/article/details/80167215