『深度应用』一小时教你上手MaskRCNN·Keras开源实战(Windows&Linux)

0. 前言介绍

开源地址:https://github.com/matterport/Mask_RCNN

个人主页:http://www.yansongsong.cn/

MaskRCNN是何凯明基于以往的faster rcnn架构提出的新的卷积网络,一举完成了object instance segmentation. 该方法在有效地目标的同时完成了高质量的语义分割。 文章的主要思路就是把原有的Faster-RCNN进行扩展,添加一个分支使用现有的检测对目标进行并行预测。

此开源代码:这是在Python 3,Keras和TensorFlow上实现Mask R-CNN。该模型为图像中对象的每个实例生成边界框和分割蒙版。它基于特征金字塔网络(FPN)和ResNet101骨干网。

存储库包括:

  • Mask R-CNN的源代码,建立在FPN和ResNet101之上。
  • MS COCO的培训代码
  • MS COCO的预训练重量
  • Jupyter笔记本可以在每一步都可视化检测管道
  • ParallelModel类用于多GPU培训
  • 评估MS COCO指标(AP)
  • 您自己的数据集培训示例

代码记录在案,设计易于扩展。如果您在研究中使用它,请考虑引用此存储库(下面的bibtex)。如果您从事3D视觉,您可能会发现我们最近发布的Matterport3D数据集也很有用。该数据集是由我们的客户捕获的3D重建空间创建的,这些客户同意将其公开供学术使用。您可以在此处查看更多示例。

1. MaskRCNN环境搭建

首先在项目源码地址下载源码到本机中:https://github.com/matterport/Mask_RCNN

1.1 要求

Python 3.4,TensorFlow 1.3,Keras 2.0.8和其他常见软件包requirements.txt

  • 亲测Python版本为3.6也可以,建议3.4及以上。
  • Python安装建议使用mini conda 安装和管理环境
  • TensorFlow,Keras也建议直接使用 conda install tensorflow keras

1.2 MS COCO要求:

要在MS COCO上进行训练或测试,还需要:

如果您使用Docker,则已验证代码可以在 此Docker容器上运行

为什么需要安装pycocotools,经过看源码发现,训练coco数据集时用到了pycocotools这个模块,如果不安装会报错无法正常运行。

1.3 安装

  1. 克隆此存储库:https://github.com/matterport/Mask_RCNN

  2. 安装依赖项(CD 进入项目根目录,pip3 不行的话可以尝试用 pip

    pip3 install -r requirements.txt
    
    image.gif

    在linux安装时,使用此方法一切正常,就是速度会有些慢,因为安装内容较多。
    使用Windows安装时可能会遇到shapely,无法安装的情况,解决方法如下:

    conda install shapely -y
    
    image.gif
  3. 从存储库根目录运行安装程序

    python3 setup.py install
    
    image.gif
    不报错的话就安装完成了,如果报错可以根据错误提示,网络搜索解决。python3 不行的话就用 python,还要注意一点你使用哪个python环境安装,后面运行的时候也要用此python环境运行MaskRCNN。
    
  4. 发布页面下载预先训练的COCO权重(mask_rcnn_coco.h5)。

    这里提供一个下载地址,可以直接下载使用:https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5

  5. (可选)pycocotools从这些回购中的一个训练或测试MS COCO安装。(这里就是1.2 MS COCO要求,需要安装pycocotools

    • Linux:https//github.com/waleedka/coco

    • Windows:https//github.com/philferriere/cocoapi。您必须在路径上安装Visual C ++ 2015构建工具(有关其他详细信息,请参阅存储库)

      **经过本人安装测试,可以使用较为简单的方式来安装:

      Linux中直接使用:**

      pip3 install pycocotools
      
      image.gif

      windows 中需要先安装 Visual C++ 2015,下载地址:https://go.microsoft.com/fwlink/?LinkId=691126
      然后执行:注意要和安装MaskRCNN同一Python环境

      pip3 install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
      
      image.gif

上述都执行完成的话,keras版本的MaskRCNN就安装完成了。下面我们动手试用一下。

2. 使用演示

用安装Mask RCNN的python环境打开 jupyter notebook,命令行,或shell运行:

jupyter notebook
image.gif

指定jupyter notebook默认路径,便于打开项目工程可以参考这个博客:https://www.cnblogs.com/awakenedy/p/9075712.html

运行完成后,会自动打开一个网页,如果不能就手动复制一下地址打开。

进入下载的MaskRCNN的根目录,打开 samples/demo.ipynb 文件。

代码如下:

Mask R-CNN Demo

A quick intro to using the pre-trained model to detect and segment objects.

In [1]:导入相关文件,设置参数,下载网络模型等:由于下载速度慢,建议直接下载https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5到根目录在运行下面代码

import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt

# Root directory of the project
ROOT_DIR = os.path.abspath("../")

# Import Mask RCNN
sys.path.append(ROOT_DIR)  # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# Import COCO config
sys.path.append(os.path.join(ROOT_DIR, "samples/coco/"))  # To find local version
import coco

%matplotlib inline 

# Directory to save logs and trained model
MODEL_DIR = os.path.join(ROOT_DIR, "logs")

# Local path to trained weights file
COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
# Download COCO trained weights from Releases if needed
if not os.path.exists(COCO_MODEL_PATH):
    utils.download_trained_weights(COCO_MODEL_PATH)

# Directory of images to run detection on
IMAGE_DIR = os.path.join(ROOT_DIR, "images")
image.gif
Using TensorFlow backend.

Configurations

We'll be using a model trained on the MS-COCO dataset. The configurations of this model are in the CocoConfig class in coco.py.

For inferencing, modify the configurations a bit to fit the task. To do so, sub-class the CocoConfig class and override the attributes you need to change.

In [2]:进行一些参数设置

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 = 1

config = InferenceConfig()
config.display()
image.gif
Configurations:BACKBONE                       resnet101BACKBONE_STRIDES               [4, 8, 16, 32, 64]BATCH_SIZE                     1BBOX_STD_DEV                   [0.1 0.1 0.2 0.2]COMPUTE_BACKBONE_SHAPE         NoneDETECTION_MAX_INSTANCES        100DETECTION_MIN_CONFIDENCE       0.7DETECTION_NMS_THRESHOLD        0.3FPN_CLASSIF_FC_LAYERS_SIZE     1024GPU_COUNT                      1GRADIENT_CLIP_NORM             5.0IMAGES_PER_GPU                 1IMAGE_CHANNEL_COUNT            3IMAGE_MAX_DIM                  1024IMAGE_META_SIZE                93IMAGE_MIN_DIM                  800IMAGE_MIN_SCALE                0IMAGE_RESIZE_MODE              squareIMAGE_SHAPE                    [1024 1024    3]LEARNING_MOMENTUM              0.9LEARNING_RATE                  0.001LOSS_WEIGHTS                   {'rpn_class_loss': 1.0, 'rpn_bbox_loss': 1.0, 'mrcnn_class_loss': 1.0, 'mrcnn_bbox_loss': 1.0, 'mrcnn_mask_loss': 1.0}MASK_POOL_SIZE                 14MASK_SHAPE                     [28, 28]MAX_GT_INSTANCES               100MEAN_PIXEL                     [123.7 116.8 103.9]MINI_MASK_SHAPE                (56, 56)NAME                           cocoNUM_CLASSES                    81POOL_SIZE                      7POST_NMS_ROIS_INFERENCE        1000POST_NMS_ROIS_TRAINING         2000PRE_NMS_LIMIT                  6000ROI_POSITIVE_RATIO             0.33RPN_ANCHOR_RATIOS              [0.5, 1, 2]RPN_ANCHOR_SCALES              (32, 64, 128, 256, 512)RPN_ANCHOR_STRIDE              1RPN_BBOX_STD_DEV               [0.1 0.1 0.2 0.2]RPN_NMS_THRESHOLD              0.7RPN_TRAIN_ANCHORS_PER_IMAGE    256STEPS_PER_EPOCH                1000TOP_DOWN_PYRAMID_SIZE          256TRAIN_BN                       FalseTRAIN_ROIS_PER_IMAGE           200USE_MINI_MASK                  TrueUSE_RPN_ROIS                   TrueVALIDATION_STEPS               50WEIGHT_DECAY                   0.0001

Create Model and Load Trained Weights

In [3]:建立网络模型,载入参数

# Create model object in inference mode.
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)

# Load weights trained on MS-COCO
model.load_weights(COCO_MODEL_PATH, by_name=True)
image.gif
WARNING:tensorflow:From c:\datas\apps\rj\miniconda3\envs\tf_gpu\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.Instructions for updating:Colocations handled automatically by placer.WARNING:tensorflow:From c:\datas\apps\rj\miniconda3\envs\tf_gpu\lib\site-packages\mask_rcnn-2.1-py3.6.egg\mrcnn\model.py:772: to_float (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.Instructions for updating:Use tf.cast instead.

Class Names

The model classifies objects and returns class IDs, which are integer value that identify each class. Some datasets assign integer values to their classes and some don't. For example, in the MS-COCO dataset, the 'person' class is 1 and 'teddy bear' is 88. The IDs are often sequential, but not always. The COCO dataset, for example, has classes associated with class IDs 70 and 72, but not 71.

To improve consistency, and to support training on data from multiple sources at the same time, our Dataset class assigns it's own sequential integer IDs to each class. For example, if you load the COCO dataset using our Dataset class, the 'person' class would get class ID = 1 (just like COCO) and the 'teddy bear' class is 78 (different from COCO). Keep that in mind when mapping class IDs to class names.

To get the list of class names, you'd load the dataset and then use the class_names property like this.

# Load COCO dataset
dataset = coco.CocoDataset()
dataset.load_coco(COCO_DIR, "train")
dataset.prepare()

# Print class names
print(dataset.class_names)
image.gif

We don't want to require you to download the COCO dataset just to run this demo, so we're including the list of class names below. The index of the class name in the list represent its ID (first class is 0, second is 1, third is 2, ...etc.)

In [4]:配置类别名

# COCO Class names
# Index of the class in the list is its ID. For example, to get ID of
# the teddy bear class, use: class_names.index('teddy bear')
class_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']
image.gif

Run Object Detection

In [5]:读入照片进行识别,原文中采用从images文件夹随机读取的方式。我这里注释掉了前两句,采用读取自己准备的照片,这里是我的母校照片。
大家只需要将image_file改为自己准备照片地址即可。

# Load a random image from the images folder
#file_names = next(os.walk(IMAGE_DIR))[2]
#image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names)))

image_file = os.path.join(IMAGE_DIR, "ahnu.jpg")

image = skimage.io.imread(image_file)

# Run detection
results = model.detect([image], verbose=1)

# Visualize results
r = results[0]
visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
                            class_names, r['scores'])
image.gif
Processing 1 imagesimage                    shape: (768, 1024, 3)        min:    0.00000  max:  255.00000  uint8molded_images            shape: (1, 1024, 1024, 3)    min: -123.70000  max:  151.10000  float64image_metas              shape: (1, 93)               min:    0.00000  max: 1024.00000  float64anchors                  shape: (1, 261888, 4)        min:   -0.35390  max:    1.29134  float32
image
image.gif

3. 训练模型

由于训练模型我正在准备中,还没有开始训练,这里先贴上官方的指南,后期我训练完成也会及时更新。如果与什么问题也欢迎评论私信我。

3.1 MS COCO培训

我们为MS COCO提供预先训练的砝码,使其更容易入手。您可以使用这些权重作为起点来训练您自己在网络上的变化。培训和评估代码在samples/coco/coco.py。您可以在Jupyter笔记本中导入此模块(请参阅提供的笔记本中的示例),或者您可以直接从命令行运行它:

<pre>`# Train a new model starting from pre-trained COCO weights
python3 samples/coco/coco.py train --dataset=/path/to/coco/ --model=coco

Train a new model starting from ImageNet weights

python3 samples/coco/coco.py train --dataset=/path/to/coco/ --model=imagenet

Continue training a model that you had trained earlier

python3 samples/coco/coco.py train --dataset=/path/to/coco/ --model=/path/to/weights.h5

Continue training the last model you trained. This will find

the last trained weights in the model directory.

python3 samples/coco/coco.py train --dataset=/path/to/coco/ --model=last` </pre>

您还可以使用以下命令运行COCO评估代码:

<pre># Run COCO evaluation on the last trained model python3 samples/coco/coco.py evaluate --dataset=/path/to/coco/ --model=last </pre>

应设置培训计划,学习率和其他参数samples/coco/coco.py

3.2 对您自己的数据集进行培训

首先阅读关于气球颜色飞溅样本的博客文章。它涵盖了从注释图像到培训再到在示例应用程序中使用结果的过程。

总之,要在您自己的数据集上训练模型,您需要扩展两个类:

Config 该类包含默认配置。对其进行子类化并修改您需要更改的属性。

Dataset 此类提供了一种使用任何数据集的一致方法。它允许您使用新数据集进行培训,而无需更改模型的代码。它还支持同时加载多个数据集,如果要检测的对象在一个数据集中并非全部可用,则此选项非常有用。

见例子samples/shapes/train_shapes.ipynbsamples/coco/coco.pysamples/balloon/balloon.py,和samples/nucleus/nucleus.py

3.3 与官方文件的不同之处

这个实现大部分都遵循Mask RCNN文章,但在一些情况下我们偏向于代码简单性和泛化。这些是我们意识到的一些差异。如果您遇到其他差异,请告诉我们。

  • 图像大小调整:为了支持每批训练多个图像,我们将所有图像调整为相同大小。例如,MS COCO上的1024x1024px。我们保留纵横比,因此如果图像不是正方形,我们用零填充它。在论文中,调整大小使得最小边为800px,最大边为1000px。

  • 边界框:一些数据集提供边界框,一些仅提供蒙版。为了支持对多个数据集的训练,我们选择忽略数据集附带的边界框,而是动态生成它们。我们选择封装掩码所有像素的最小盒子作为边界框。这简化了实现,并且还使得应用图像增强变得容易,否则图像增强将更难以应用于边界框,例如图像旋转。

    为了验证这种方法,我们将计算出的边界框与COCO数据集提供的边界框进行了比较。我们发现2%的边界框相差1px或更多,0.05%相差5px或更多,仅0.01%相差10px或更多。

  • 学习率:本文使用0.02的学习率,但我们发现它太高,并且经常导致重量爆炸,特别是当使用小批量时。这可能与Caffe和TensorFlow如何计算梯度(总和与批次和GPU之间的平均值之间的差异)有关。或者,也许官方模型使用渐变剪辑来避免这个问题。我们使用渐变剪辑,但不要过于激进。我们发现较小的学习率无论如何都会更快收敛,所以我们继续这样做。

4. 总结

花了数个小时完成了这个上手教程,希望能对MaskRCNN感兴趣朋友提供帮助。

如果觉得有用的话,欢迎点赞收藏,也欢迎翻阅我之前博客。

往期优秀博文:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容