龙空技术网

一文教会!如何用Python实现Mask R-CNN及其在图像处理的运用?

读芯术 166

前言:

现在我们对“python图像编码算法实现”大致比较关切,大家都需要剖析一些“python图像编码算法实现”的相关内容。那么小编同时在网络上网罗了一些关于“python图像编码算法实现””的相关知识,希望兄弟们能喜欢,咱们快快来了解一下吧!

全文共6625字,预计学习时长13分钟或更长

划重点!!!本文主要内容:

· Mask R-CNN是一种先进的算法框架,用于解决图像分割问题

· 本文将采用逐步推进、层层推进的方式来剖析Mask R-CNN的工作原理

· 本文还将探析如何用Python实现Mask R-CNN及其在图像处理的运用

图片来源:unsplash.com/@mcnoble

自动驾驶系统所囊括的计算机视觉技术复杂巧妙,种类繁多,在数据科学家眼中,这种复杂性与混合性堪比梦中天籁,引人入胜。

因此,笔者开始研究这一系统,试图理解自动驾驶赋予汽车的这双“火眼金睛”的背后,究竟隐藏着何等玄机。仅凭一个物体检测框架可能行不通,因为它仅能识别对象,并用某种固定的形状将其标出。

然而若运用于现实中,这种方法风险很大。试想,倘若前方有一处急转弯,系统只在道路上给出一个矩形标识,这样以来车辆很有可能判断不出是该避让还是径直上前,车祸一触即发!

因此,对新技术的诉求应运而生,该技术须能识别具体路况,以指引车辆顺利过弯。

到底什么样的黑科技能够满足这一需求呢—— Mask R-CNN闪亮登场!

本文将简要阐释何为图像分割,并以此引入全文的核心主角—— Mask R-CNN算法框架。最后本文将探析如何用Python实现Mask R-CNN框架。

目录

1. 图像分割概览

2. 剖析Mask R-CNN

3. 实现Mask R-CNN的步骤

4. 实现Mask R-CNN

1. 图像分割概览

让我们先来简单回顾一下图像分割:图像分割即为图片的每个对象创建一个像素级的掩膜,该技术可使大家对图像中的对象有更深入的了解。下图将助你理解何为图像分割。

如图所示,每个对象(即该图中的每个单元)已彼此分离,这就是图像分割的工作原理。

图像分割可分为两种,语义分割与实例分割,具体实例详见下文。

左图五个对象均为人,因此语义分割会将这五个对象视为一个整体。而右图同样也有五个对象(亦均为人),但同一类别的不同对象在此被视为不同的实例,这就是实例分割。

2. 剖析Mask-CNN

Mask R-CNN可算作是Faster R-CNN的升级版。Faster R-CNN广泛用于对象检测。对于给定图像,它会给图中每个对象加上类别标签与边界框坐标。如果你输入下图:

Fast R-CNN将会返回如下结果:

Mask R-CNN框架是以Faster R-CNN为基础而架构的。因此,针对给定图像, Mask R-CNN不仅会给每个对象添加类标签与边界框坐标,还会返回其对象掩膜。

先来分析Faster R-CNN的工作原理,因为这也助于促进对Mask R-CNN的直观感受。

· Faster R-CNN通过ConvNet从图片中提取特征图

· 特征图通过区域候选网络 (RPN) 予以传递,该网络会返回候选边界框

· 应用Rol池化层,将所有候选区域修正到同一尺寸

· 将候选区域传递到全连接层,将对象边界框分类及输出

一旦掌握了Faster R-CNN 的工作原理, Mask R-CNN 自然也就易如反掌。接下来将从输入到预测类标签、边界框与对象掩膜,逐步剖析Mask R-CNN 的背后玄机。

骨干模型 (Backbone Model)

与在Faster R-CNN 中从图片提取特征图所用的ConvNet相似,在Mask R-CNN中提取特征图用的是残差网络 101结构。因此,先选取图片,用残差网络 101结构提取特征,这些特征便是下一层的输入数据。

区域候选网络 (RPN)

将上一步提取的特征图应用于区域候选网络 (RPN)。这基本能预测出一个对象是否位于该区域。该步骤可得到那些可能包含某些对象的区域或特征图。

感兴趣区域 (RoI)

从RPN获得的区域可能形状不一。因此,须将所得区域应用于一个池化层,将所有区域转换为同一形状。随后,这些区域通过全连接网络,以此预测出类标签与边界框。

在该步骤之前,一切似乎与Faster R-CNN 并无二致。不过RoI便是这两者的区别所在。除此之外,另一个区别在于,Mask R-CNN可创建掩膜。

我们先算出感兴趣区域,以减少计算时间。在所有预测区域中,原标记框可用于计算交并比。计算公式如下:

交并比=交集区域/并集区域

只有当交并比大于等于0.5时,这一区域方为感兴趣区域;若小于0.5,该区域将不予考虑。计算所有区域的交并比,并选出交并比大于0.5的区域。

以下图为例:

红框即该图的原标记框,如下图所示,通过RPN得出4个区域:

如图所示,框1与框2的交并比应该小于0.5,而框3与框4的交并比约大于0.5。因此可判定框3与框4属于该图的感兴趣区域,而框1及框2可弃之不用。

接下来便是Mask R-CNN操作流程的尾声。

分割掩膜

基于交并比值获得感兴趣区域后,给已有框架加上一个掩膜分支,每个囊括特定对象的区域都会被赋予一个掩膜。每个区域都会被赋予一个28 X 28掩膜,并按比例放大以便推断。

详见下图:

该图分割掩膜效果如下:

到此,图上所有对象已被分割。这就是Mask R-CNN给图中所有对象预测掩膜的最后一步。

谨记, Mask R-CNN的训练周期很长。笔者曾用享有盛名的COCO数据集训练Mask R-CNN ,耗时长达一到两天。受篇幅所限,本文不会讨论Mask R-CNN的训练详情。

不过笔者会用到COCO数据集中Mask R-CNN的预训练权值。在探析如何用Python编码前,先来了解Mask R-CNN在执行实例分割时的所需步骤。

3. 实现Mask R-CNN的步骤

以下即图像分割环节。该环节所用的Mask R-CNN框架 是由Facebook AI Research(FAIR) 的数据科学家与研究员联手打造。

Mask R-CNN分割图像所要遵循的步骤,详见下文。

第1步:克隆知识库

首先,克隆mask rcnn知识库,其库应具有Mask R-CNN架构。可利用以下命令克隆该知识库:

git clone

克隆完成后,需要安装Mask R-CNN所需的依赖库。

第2步:安装依赖库

以下是Mask R-CNN的所有依赖库:

· numpy

· scipy

· Pillow

· cython

· matplotlib

· scikit-image

· tensorflow>=1.3.0

· keras>=2.0.8

· opencv-python

· h5py

· imgaug

· IPython

使用Mask R-CNN框架前必须安装所有依赖库。

第3步:下载预训练模型权值

接下来,需要下载预训练模型权值。可以采用此链接下载预训练模型权值:。这些权值从MS COCO数据集所训练的一种模型而来。下载完成后,粘贴此文件于第一步克隆的Mask_RCNN知识库样本文件夹中。

第4步:图像预测

最后,采用Mask R-CNN架构和预训练模型权值生成图像预测。

四步完成后,开始转入Jupyter Notebook。用python实现上述所有代码并为图像中各个对象生成掩膜、类和边界框

4. 基于Python的Mask R-CNN实现

为了执行所有本节将谈到的代码块,须创建一个新的Python笔记本,然后将其放入所克隆的Mask_RCNN “样本”文件夹中。

开始导入所需程序库:

import osimport sysimport randomimport mathimport numpy as npimport skimage.ioimport matplotlibimport matplotlib.pyplot as plt# Root directory of the projectROOT_DIR = os.path.abspath("../")import warningswarnings.filterwarnings("ignore")# Import Mask RCNNsys.path.append(ROOT_DIR) # To find local version of the libraryfrom mrcnn import utilsimport mrcnn.model as modellibfrom mrcnn import visualize# Import COCO configsys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local versionimport coco%matplotlib inline

接下来,将对预训练权值及待分割的图像定义路径:

# Directory to save logs and trained modelMODEL_DIR = os.path.join(ROOT_DIR, "logs")# Local path to trained weights fileCOCO_MODEL_PATH = os.path.join('', "mask_rcnn_coco.h5")# Download COCO trained weights from Releases if neededif not os.path.exists(COCO_MODEL_PATH): utils.download_trained_weights(COCO_MODEL_PATH)# Directory of images to run detection onIMAGE_DIR = os.path.join(ROOT_DIR, "images")

若未将权值放置于样本文件夹,则会重新下载权值。现在,创建推理类,用于推断Mask R-CNN模型:

class InferenceConfig(coco.CocoConfig): # Set batch size to 1 since we'll be running inference on # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU GPU_COUNT = 1 IMAGES_PER_GPU = 1config = InferenceConfig()config.display()

由此汇总可推断出什么呢?可看到即将使用的Mask R-CNN模型的多项性能规格。

如上所述,该算法基干是残差网络101。鉴于其训练数据集为COCO,故返回的掩膜形状为28×28。总计81类(包括背景)。

此外,还有其他多项数据如:

· 输入形状

· 待用图形处理器编号

· 验证步骤等

加载权值

接下来,创建模型,加载已下载的预训练模型权值。确保预训练权值与笔记本处在同一文件夹中,否则,必须给出该权值文件夹的位置:

# Create model object in inference mode.model = modellib.MaskRCNN(mode="inference", model_dir='mask_rcnn_coco.hy', config=config)# Load weights trained on MS-COCOmodel.load_weights('mask_rcnn_coco.h5', by_name=True)

现在,定义COCO数据集类别,供预测阶段使用:

# COCO Class namesclass_names = ['BG', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']

加载图像,观察模型运行情况。测试图像任意选择。

# Load a random image from the images folderimage = skimage.io.imread('sample.jpg')# original imageplt.figure(figsize=(12,10))skimage.io.imshow(image)

此即测试用图。两辆汽车(一辆在前,一辆在后)及一辆自行车清晰可辨。

进行预测

开始预测!使用带有预训练权值的Mask R-CNN模型,并观察其图像分割效果。首先对图像进行预测,绘制结果并将其可视化:

# Run detectionresults = model.detect([image], verbose=1)# Visualize resultsr = results[0]visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])

有趣!该模型成功地将图像中的汽车和自行车进行了分割。每个掩膜或所分割对象均可分开研究。其实现方式详见下文。

首先将模型预测的所有掩膜存储在掩膜变量中。现在,这些掩膜是布尔型(True和False),因此需要将其转换为二进制(1和0):

mask = r['masks']mask = mask.astype(int)mask.shape

输出:

(480,640,3)

此会得出一个0和1的数组,其中0表示在那个特定像素处无对象存在,1表示在该像素处有对象存在。注意,掩膜的形状与原始图像的形状相似(这可以通过输出原始图像的形状来进行验证)

然而,掩膜形状里的3不表示路径,相反,它代表模型所分割的对象数量。由于模型在上述样本图像中已识别了3个对象,所以掩模的形状为 (480,640,3) 。如果有5个对象,则此形状应为 (480,640,5) 。

有了原始图像以及其掩膜数组。为了输出或获得各个图像片段,将创建for loop函数,后将每个掩模与原始图像相乘,以求分割后的各图像片段:

for i in range(mask.shape[2]): temp = skimage.io.imread('sample.jpg') for j in range(temp.shape[2]): temp[:,:,j] = temp[:,:,j] * mask[:,:,i] plt.figure(figsize=(8,8)) plt.imshow(temp)

以上即绘制出图片各掩膜或对象的操作方法。有许多有趣又使用的用例。图像分割可以降低计算成本,因为如此一来不需要对整个图像进行预处理,只需要预处理分割片段即可。

推断

下面即Mask R-CNN模型的输出结果:

Mask R-CNN圆满完成图像分割任务。太棒了!你已经成功地使用Mask R-CNN模型建立了属于自己的图像分割。

留言 点赞 关注

我们一起分享AI学习与发展的干货

编译组:董宇阳、柳玥

相关链接:

如需转载,请后台留言,遵守转载规范

标签: #python图像编码算法实现 #pythoncnn