采用Mask RCNN分割自己的数据集

采用Mask RCNN分割自己的数据集

  1. 下载源工程代码:https://github.com/matterport/Mask_RCNN;
  2. 解压,进入主文件夹,安装所需模块:
pip3 install -r requirements.txt;
  1. 下载Jupyter Notebook以及coco权重:mask_rcnn_coco.h5,了解Jupyter Notebook的使用方法,采用Jupyter Notebook打开文件夹samples下的balloon或者shapes子文件夹,在web界面左上角的file下面将其download为python格式的文件;

    说明: samples文件夹下面的几个示例例程基本都有三个文件:inspect_data,inspect_model,shapes,其中第一个文件是生成数据,第二个用来检测模型,可查看分步计算的结果并展示,第三个是主文件,用来训练或者预测分割;

  2. 结合shapes和balloon两个例程,在其基础上进行修改使得代码可以处理自己的数据,就是继承已有的类(mrcnn类)进行函数覆盖,使其适用于自己的data。在继承的过程中,除了sample文件夹下面的代码在改变,其他如mrcnn文件夹下面的文件都不要动。具体来说需要修改的有以下几个类:

  • 类1: class BrainwebConfig(Config), 在其下面定义自己的环境配置,例如每个GPU处理的图像数目、每步迭代的次数等;

  • 类2:class BrainwebDataset(utils.Dataset),继承原数据类,定义自己的类,该类需要覆盖的函数主要有两个:load_brainweb和load_mask。

    在load_brainweb函数中需要注意的主要有两个函数:add_class,add_image,前者添加类别,后者添加有关图像的信息,特别需要注意的是,在这一步并不需要导入所有图像的数据,只需要添加原始图像所在路径和有关图像的信息即可,原add_image中没有的参数都将被合并至self.imageinfo的一个dict下,以方便后续使用,比如mask数据的导入,具体代码如下图:

   # 添加图像
   for img_name in train_img_names:
       image_path = os.path.join(dataset_dir, img_name)
       image = skimage.io.imread(image_path)
       height, width = image.shape[:2]
       self.add_image("brainweb", image_id = img_name,  path = image_path,width = width, height=height)

在load_mask函数中需要利用到self.image_info中的信息,所以load_brainweb和load_mask要配合使用;具体代码如下:

        # 添加图像
        # 以下是自己编写的读取mask的代码
        image_info = self.image_info[image_id]
        mask = np.zeros([image_info["height"], image_info["width"], 3], dtype=np.uint8)                        # 每个实例中只有3种mask
        image_name = image_info['id']
        
        root_path = '/home/mdd/work/MRCNN_UNet/Mask_RCNN/self_Mask_RCNN/datasets/brainweb/mask_train_val/label_0_255_'
        for r_num in range(3):
            mask_name = root_path + str(r_num+1) + '/' + image_name
            mask_data = scipy.misc.imread(mask_name)              # 这里时读取的,后面显示会一块显示所以得去缓存
            mask[:,:,r_num] = mask_data
        return mask.astype(np.bool), np.array([1,2,3], dtype=np.int32)
  1. 除了修改覆盖上面两个类之外,剩下就是定义自己的训练(train)和测试(test)主函数。
  • 训练主函数格式比较固定,基本都是以下形式:
def train(model,config):
    """Train the model."""
    # Training dataset.
    dataset_train = BrainwebDataset()
    dataset_train.load_brainweb(args.dataset, "train")      # 如果用自己的数据集,主要修改在这一句
    dataset_train.prepare()

    # Validation dataset
    dataset_val = BrainwebDataset()
    dataset_val.load_brainweb(args.dataset, "val")          # 如果用自己的数据集,主要修改在这一句
    dataset_val.prepare()

    # 测试显示
    image_id = random.choice(dataset_val.image_ids)
    original_image, image_meta, gt_class_id, gt_bbox, gt_mask = modellib.load_image_gt(dataset_val, config, image_id = image_id, use_mini_mask=False)
    scipy.misc.imshow(original_image)

    # *** This training schedule is an example. Update to your needs ***
    # Since we're using a very small dataset, and starting from
    # COCO trained weights, we don't need to train too long. Also,
    # no need to train all layers, just the heads should do it.
    # 这里需要注意的是: 以下两次训练并不是独立的,而是累计的epochs,就是两次训练的总次数等于all layers第二次的训练epochs
    print("Training network heads")
    model.train(dataset_train, dataset_val,learning_rate = config.LEARNING_RATE, epochs=10, layers='heads')
    print("Training all layers")
    model.train(dataset_train, dataset_val, learning_rate=config.LEARNING_RATE / 10, epochs=20, layers="all")
    print("Training all layers end!")
  • 测试函数的话,主要用于多幅图像分割和Video的分割,这里主要讨论多幅图像的分割。如果测试图像是灰度图,则必须将其扩展到三通道彩色图,具体就是原灰度图复制三次,叠加在一起。代码如下:
def segment(model, image_path = None, video_path = None):
    # 判断是否存在图像路径或者视频路径
    assert image_path or video_path
    # Image or video?
    if image_path:
        # Run model detection and generate the color splash effect
        print("Running on {}".format(args.image_path))
        # Read image
        test_img_names = next(os.walk(args.image_path))[2]

        for i,img_name in enumerate(test_img_names):
            test_img = skimage.io.imread(args.image_path + '/' + img_name)

            expand_image = np.zeros([test_img.shape[0],test_img.shape[1],3])
            expand_image[:, :, 0] = test_img
            expand_image[:, :, 1] = test_img
            expand_image[:, :, 2] = test_img
            test_img = expand_image

            results = model.detect([test_img], verbose=1)[0]
            # visualize.display_instances(test_img, results['rois'], results['masks'], results['class_ids'], ['BG','Class1','Class2','Class3'],results['scores'])  # 显示图

            # 下面将生成的mask保存到对应文件夹中
            predict_masks = results['masks']
            predict_ids = results['class_ids']
            for j, predict_id in enumerate(predict_ids):
                predict_int_mask = np.zeros([predict_masks.shape[0], predict_masks.shape[1]])
                predict_int_mask[predict_masks[:, :, j]] = 1
                save_name = args.image_path + '/' + img_name[:-4] + '_predict_' + str(predict_id) + img_name[-4:]
                skimage.io.imsave(save_name, predict_int_mask)
  1. 加载MaskRCNN模型时,如果时训练模式,应该使用:
    model = modellib.MaskRCNN(mode=“training”, config=config,model_dir=args.logs)
    如果时推理测试模式,应该使用:
    model = modellib.MaskRCNN(mode=“inference”, config=config,model_dir=args.logs)
  2. 主函数中的各种解析指令如下:
if __name__ == '__main__':
    import argparse

    # Parse command line arguments
    parser = argparse.ArgumentParser(description='Train Mask R-CNN to segment brain images.')
    parser.add_argument("--command",metavar="<command>", help="'train' or 'segment'", default = 'train')
    parser.add_argument('--dataset', required=False, metavar="/path/to/balloon/dataset/",
                        default = '/home/mdd/work/MRCNN_UNet/Mask_RCNN/self_Mask_RCNN/datasets/brainweb/',
                        help = 'Directory of the Balloon dataset')
    parser.add_argument('--weights', required=False, metavar="/path/to/weights.h5",
                        default = 'coco',
                        help = "Path to weights .h5 file or 'coco'")
    parser.add_argument('--logs', required=False, default=DEFAULT_LOGS_DIR, metavar="/path/to/logs/",
                        help = 'Logs and checkpoints directory (default=logs/)')
    parser.add_argument('--image_path', required=False, metavar="path or URL to image",
                        default = '/home/mdd/work/MRCNN_UNet/Mask_RCNN/self_Mask_RCNN/datasets/brainweb/test',
                        help = 'Image to apply the color splash effect on')
    parser.add_argument('--video_path', required=False, metavar="path or URL to video",
                        help = 'Video to apply the color splash effect on')
    args = parser.parse_args()
    print (args)

猜你喜欢

转载自blog.csdn.net/u013920434/article/details/88177265