本文主要是介绍Splash of Color: Instance Segmentation with Mask R-CNN and TensorFlow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
喷色:使用Mask R-CNN和TensorFlow进行实例分割
原文:Splash of Color: Instance Segmentation with Mask R-CNN and TensorFlow
原作者:Waleed Abdulla
0 概述
早在11月,我们就将Mask R-CNN的实现开源了,此后,它被forked了1400次,在许多项目中使用,并得到了许多贡献者的改进。我们也收到了很多问题,因此在这篇文章中,我将解释该模型的工作原理,并展示如何在实际应用中使用它。
我将介绍两件事:
- 首先,Mask RCNN概述。
- 其次,如何从头训练模型并使用它来构建智能的彩色喷涂滤镜。
1 Mask RCNN概述
1.1 什么是图像实例分割(Instance Segmentation)?
图像识别领域有以下几个研究方向,如下图所示:
- 分类:此图像中有一个气球。
- 语义分割:所有这些都是气球像素。
- 物体检测:此图像中的这些位置有7个气球。我们开始考虑重叠的对象。
- 实例分割:在这些位置有7个气球,它们是每个像素的像素。
其中,实例分割是在像素级别识别对象轮廓的任务。与类似的计算机视觉任务相比,它是最难的视觉任务之一。
1.2 Mask R-CNN
Mask R-CNN(区域卷积神经网络)是一个两阶段的框架:第一阶段扫描图像并生成提案(可能包含对象的区域)。第二阶段对候选区域进行分类,并生成边框和masks。
去年,它是通过Mask R-CNN论文引入的,目的是扩展同一作者的前身Faster R-CNN。Faster R-CNN是流行的对象检测框架,而Mask R-CNN则通过实例分割对其进行了扩展。
如上图所示,Mask R-CNN包含以下模块:
1.2.1 Backbone
这是用作特征提取器的标准卷积神经网络(通常为ResNet50或ResNet101)。较早的层检测低层特征(边缘和角落),而较后的层依次检测高层特征(汽车,人,天空)。
通过backbone ,图像从1024x1024px x 3(RGB)转换为形状为32x32x2048的特征图。此功能图成为以下阶段的输入。
代码提示:backbone 内置在函数resnet_graph()中。该代码支持ResNet50和ResNet101。
1.2.1.1 Feature Pyramid Network
尽管上面描述的主干机制很好用,但是可以对其进行改进。Mask R-CNN的同一作者介绍了Feature Pyramid Network (FPN) ,作为可以更好地表示多个比例对象的扩展。
FPN通过添加第二个金字塔来改进标准特征提取金字塔,该金字塔从第一个金字塔中获取高级特征并将其向下传递到较低层。这样,它允许每个级别的功能都可以访问较低和较高级别的功能。
我们的Mask RCNN实现使用ResNet101 + FPN backbone
代码提示:FPN在MaskRCNN.build()中创建。构建ResNet之后的部分。RPN引入了额外的复杂性:而不是标准主干网(即第一金字塔的顶层)中的单个主干特征图,在FPN中,第二个金字塔的每个级别都有一个特征图。我们根据对象的大小选择动态使用的对象。我将继续参考主干要素地图,就像它是一个要素地图一样,但是请记住,在使用FPN时,实际上是在运行时从多个要素中选择一个。
1.2.2 Region Proposal Network (RPN)
RPN是一个轻量级的神经网络,它以滑动窗口的方式扫描图像并查找包含对象的区域。
RPN扫描的区域称为锚点。如左图所示,它们是分布在图像区域上的框。
不过,这是一个简化的视图。实际上,大约有20万个不同大小和纵横比的锚点,并且它们重叠以覆盖尽可能多的图像。
RPN可以扫描这么多锚点的速度有多快?实际上,速度非常快。滑动窗口由RPN的卷积特性处理,这使其可以并行(在GPU上)扫描所有区域。此外,RPN不会直接扫描图像(即使我们在图像上画了锚点也只是为了说明)。相反,RPN扫描骨干特征图。这使RPN可以有效地重用提取的特征,并避免重复计算。通过这些优化,根据引入它的Faster RCNN论文,RPN运行大约10毫秒。在Mask RCNN中,我们通常使用更大的图像和更多的锚点,因此可能需要更长的时间。
代码提示:RPN在rpn_graph()中创建。锚定比例和纵横比由config.py中的RPN_ANCHOR_SCALES和RPN_ANCHOR_RATIOS控制。
RPN为每个锚点生成两个输出:
- 锚类(Anchor Class):两种类之一:前景或背景。FG类表示该框中可能有一个对象。
- 边界框优化(Bounding Box Refinement):前景定位点(也称为正定位点)可能未在对象上完美居中。因此,RPN估算出一个增量(x,y,宽度,高度的百分比变化)以细化锚框以更好地适合对象。
使用RPN预测,我们选择可能包含对象的顶部锚点,并优化其位置和大小。
如果多个锚点重叠太多,我们保留前景得分最高的锚点,并丢弃其余的锚点(称为非最大抑制)。
之后,我们将获得最终建议(感兴趣的区域),并将其传递到下一阶段.
代码提示:ProposalLayer是自定义的Keras图层,可读取RPN的输出,选择顶部锚点并应用边界框优化。
1.2.3 ROI Classifier & Bounding Box Regressor
此阶段在RPN建议的感兴趣区域(ROI)上运行。就像RPN一样,它为每个ROI生成两个输出:
- 类(Class):ROI中对象的类。与具有两个类别(FG / BG)的RPN不同,此网络更深入,并且具有将区域分类为特定类别(人,汽车,椅子等)的能力。它还可以生成背景类,从而导致ROI被丢弃。
- 边界框优化(Bounding Box Refinement):与RPN中的操作非常相似,其目的是进一步优化边界框的位置和大小以封装对象。
Code Tip:
The classifier and bounding box regressor are created in fpn_classifier_graph().
ROI Pooling
在继续之前,有一个问题需要解决。分类器无法很好地处理可变输入大小。它们通常需要固定的输入大小。但是,由于RPN中的边界框优化步骤,ROI框可以具有不同的大小。这就是ROI池发挥作用的地方。
ROI合并是指裁剪要素地图的一部分并将其大小调整为固定大小。从原理上讲,它类似于裁剪图像的一部分然后调整其大小(但实现细节有所不同)。
Mask R-CNN的作者提出了一种名为ROIAlign的方法,在该方法中,他们在不同点采样特征图并应用双线性插值。
在我们的实施中,为简单起见,我们使用TensorFlow的crop_and_resize函数,因为它对于大多数用途而言都足够接近。
1.2.4 Segmentation Masks
如果您在上一节的末尾停下来,那么您将拥有用于对象检测的Faster R-CNN框架。Mask网络是Mask R-CNN论文引入的补充。
遮罩分支是一个卷积网络,它采用ROI分类器选择的正区域并为其生成遮罩。生成的蒙版分辨率很低:28x28像素。但是它们是软掩码,由浮点数表示,因此与二进制掩码相比,它们具有更多的细节。较小的面罩尺寸有助于使面罩分支保持明亮。
在训练过程中,我们将真实的蒙版按比例缩小到28x28以计算损失,而在推理过程中,我们将预测的蒙版按比例缩放到ROI边界框的大小,这为我们提供了最终的masks(每个对象一个)。
2 Mask RCNN实战
与大多数包含此滤镜的图像编辑应用程序不同,我们的滤镜会更聪明:它会自动查找对象。如果您想将其应用于视频而不是单个图像,该功能将变得更加有用。
2.1 Training Dataset
通常,我会先搜索包含所需对象的公共数据集。但是在这种情况下,我想记录整个周期并展示如何从头开始构建数据集。
我在flickr上搜索了气球图像,将许可证类型限制为“允许商业使用和改装”。这样返回的图像足以满足我的需求。我总共选择了75张图像,并将它们分为训练集和验证集。查找图像很容易。注释它们是困难的部分。
等待!我们是否不需要一百万张图像来训练深度学习模型?有时您会这样做,但通常却不会。我主要依靠两点来大大减少培训需求:
首先,转移学习。这只是意味着,我不是从头开始训练模型,而是从在COCO数据集上得到训练的权重文件开始(我们在github存储库中提供了该文件)。尽管COCO数据集不包含气球类,但它包含许多其他图像(〜120K),因此训练的权重已经学习了自然图像中许多常见的功能,这确实有帮助。其次,考虑到这里的简单用例,我不要求该模型具有很高的准确性,因此微小的数据集就足够了。
有很多用于注释图像的工具。由于其简单性,我最终使用了VIA(VGG图像注释器)。该文件是您下载并在浏览器中打开的一个HTML文件。批注最初的几幅图像非常慢,但是一旦习惯了用户界面,我就在一分钟左右对一个对象进行批注。
如果您不喜欢VIA工具,以下是我测试过的其他工具的列表:
- LabelMe:最知名的工具之一。但是,UI太慢了,特别是在放大大图像时。
- RectLabel:简单易用。仅Mac。
- LabelBox:非常适合大型标签项目,并且具有用于不同类型标签任务的选项。
- VGG图像注释器(VIA):快速,轻巧,设计精良。这是我最终使用的那个。
- COCO UI:用于注释COCO数据集的工具。
2.2 Loading the Dataset
没有通用的格式来存储细分掩码。一些数据集将它们保存为PNG图像,其他数据集将它们存储为多边形点,依此类推。为了处理所有这些情况,我们的实现提供了一个Dataset类,您可以从该类继承该Dataset类,然后重写一些函数来以可能的任何格式读取数据。
VIA tool 将注释保存在JSON文件中,每个mask 是一组多边形点。我没有找到该格式的文档,但是通过查看生成的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_class和add_image函数来构建数据集。
load_mask通过绘制多边形为图像中的每个对象生成位图蒙版。
image_reference只是返回一个标识图像的字符串以进行调试。在这里,它只是返回图像文件的路径。
您可能已经注意到,我的课程不包含用于加载图像或返回边界框的函数。基本Dataset类中的默认load_image函数处理加载图像。并且,边界框是从masks动态生成的。
2.3 Verify the Dataset
为了验证新代码是否正确实现,我添加了此Jupyter笔记本。它加载数据集,可视化蒙版和边界框,并可视化锚点,以验证我的锚点大小是否适合我的对象大小。这是您应该看到的示例:
代码提示:为了创建此笔记本,我复制了我们为COCO数据集编写的inspect_data.ipynb,并在顶部修改了一段代码以加载Balloons数据集。
2.4 Configurations
该项目的配置类似于用于训练COCO数据集的基本配置,因此我只需要覆盖3个值。正如我对Dataset类所做的那样,我继承自Config类的基础并添加了覆盖:
class BalloonConfig(Config):# Give the configuration a recognizable nameNAME = "balloons"# Number of classes (including background)NUM_CLASSES = 1 + 1 # Background + balloon# Number of training steps per epochSTEPS_PER_EPOCH = 100
基本配置使用大小为1024x1024 px的输入图像以获得最佳准确性。我保持这种方式。我的图像稍小,但是模型会自动调整其大小。
代码提示:基本的Config类位于config.py中。而且BalloonConfig位于Balloons.py中。
2.5Training
Mask R-CNN是一个相当大的模型。特别是我们的实现使用ResNet101和FPN。因此,您需要具有12GB内存的现代GPU。它的工作量可能更少,但我没有尝试过。我使用Amazon的P2实例来训练该模型,并且由于数据集很小,训练花费了不到一个小时的时间。
从气球目录运行,使用此命令开始训练。在这里,我们指定训练应从预先训练的COCO权重开始。该代码将自动从我们的存储库下载权重:
python3 balloon.py train --dataset=/path/to/dataset --model=coco
并继续训练(如果停止):
python3 balloon.py train --dataset=/path/to/dataset --model=last
代码提示:除了Balloons.py之外,该存储库还有另外三个示例:train_shapes.ipynb(用于训练玩具模型以检测几何形状),coco.py(用于在COCO数据集上进行训练)和核(用于在显微镜图像中分割核)。
2.6 Inspecting the Results
inspect_balloon_model笔记本显示了经过训练的模型生成的结果。检查笔记本以获取更多可视化效果,并逐步完成检测流程。
代码提示:该笔记本是inspect_mode.ipynb的简化版本,其中包括COCO数据集的可视化和调试代码。
2.7 Color Splash
最后,既然有了对象遮罩,我们就可以使用它们来应用颜色飞溅效果。该方法非常简单:创建图像的灰度版本,然后在对象蒙版标记的区域中,从原始图像中复制回彩色像素。这是一个例子:
代码提示:施加效果的代码在color_splash()函数中。detect_and_color_splash()处理整个过程,包括加载图像,运行实例分割以及应用颜色飞溅过滤器。
这篇关于Splash of Color: Instance Segmentation with Mask R-CNN and TensorFlow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!