精华内容
下载资源
问答
  • maskrcnn-benchmark has been deprecated. Please see detectron2, which includes implementations for all models in maskrcnn-benchmark This project aims at providing the necessary building blocks for ...
  • 基于MASK rcnn的老鼠检测,效果还不错,有需要的可以下载,自己更换数据集
  • maskRCNN_homework
  • 该代码用于从学习maskrcnn算法。 我对此做了非常详细的代码注释。 并且我创建了maskrcnn的ros节点来抓取机器人。 当前过程 进行详细的代码注释 写一个maskrcnn的ros节点 编写数据增强python脚本以生成更多数据 ...
  • Mask RCNN

    2020-09-27 15:09:24
    不断更新目标检测和语义分割的文章,感兴趣的请关注我。 令人拍案称奇的Mask RCNN 最近在做一个目标检测项目,用到了Mask RCNN。...Mask RCNN沿用了Faster RCNN的思想,特征提取采用ResNet-FPN的架构,另外多加了一

    不断更新目标检测和语义分割的文章,感兴趣的请关注我。

    令人拍案称奇的Mask RCNN

    最近在做一个目标检测项目,用到了Mask RCNN。我仅仅用了50张训练照片,训练了1000步之后进行测试,发现效果好得令人称奇。就这个任务,很久之前用yolo v1训练则很难收敛。不过把它们拿来比当然不公平,但我更想说的是,mask RCNN效果真的很好。

    所以这篇文章来详细地总结一下Mask RCNN。

    Mask RCNN沿用了Faster RCNN的思想,特征提取采用ResNet-FPN的架构,另外多加了一个Mask预测分支。可见Mask RCNN综合了很多此前优秀的研究成果。为了更好地讲解Mask RCNN,我会先回顾一下几个部分:

    1. Faster RCNN
    2. ResNet-FPN
    3. ResNet-FPN+Fast RCNN

    回顾完之后讲ResNet-FPN+Fast RCNN+Mask,实际上就是Mask RCNN。

    一、Faster RCNN

    Faster RCNN是两阶段的目标检测算法,包括阶段一的Region proposal以及阶段二的bounding box回归和分类。用一张图来直观展示Faster RCNN的整个流程:

    Faster RCNN使用CNN提取图像特征,然后使用region proposal network(RPN)去提取出ROI,然后使用ROI pooling将这些ROI全部变成固定尺寸,再喂给全连接层进行Bounding box回归和分类预测。

    这里只是简单地介绍了Faster RCNN前向预测的过程,但Faster RCNN本身的细节非常多,比一阶段的算法复杂度高不少,并非三言两语能说得清。如果对Faster RCNN算法不熟悉,想了解更多的同学可以看这篇文章:一文读懂Faster RCNN,这是我看过的解释得最清晰的文章。

    二、ResNet-FPN

    多尺度检测在目标检测中变得越来越重要,对小目标的检测尤其如此。现在主流的目标检测方法很多都用到了多尺度的方法,包括最新的yolo v3。Feature Pyramid Network (FPN)则是一种精心设计的多尺度检测方法,下面就开始简要介绍FPN。

    FPN结构中包括自下而上,自上而下和横向连接三个部分,如下图所示。这种结构可以将各个层级的特征进行融合,使其同时具有强语义信息和强空间信息,在特征学习中算是一把利器了。

    FPN实际上是一种通用架构,可以结合各种骨架网络使用,比如VGG,ResNet等。Mask RCNN文章中使用了ResNNet-FPN网络结构。如下图:

    ResNet-FPN包括3个部分,自下而上连接,自上而下连接和横向连接。下面分别介绍。

    自下而上

    从下到上路径。可以明显看出,其实就是简单的特征提取过程,和传统的没有区别。具体就是将ResNet作为骨架网络,根据feature map的大小分为5个stage。stage2,stage3,stage4和stage5各自最后一层输出conv2,conv3,conv4和conv5分别定义为 [公式] ,他们相对于原始图片的stride是{4,8,16,32}。需要注意的是,考虑到内存原因,stage1的conv1并没有使用。

    自上而下和横向连接

    自上而下是从最高层开始进行上采样,这里的上采样直接使用的是最近邻上采样,而不是使用反卷积操作,一方面简单,另外一方面可以减少训练参数。横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合。具体就是对 [公式] 中的每一层经过一个conv 1x1操作(1x1卷积用于降低通道数),无激活函数操作,输出通道全部设置为相同的256通道,然后和上采样的feature map进行加和操作。在融合之后还会再采用3*3的卷积核对已经融合的特征进行处理,目的是消除上采样的混叠效应(aliasing effect)。

    实际上,上图少绘制了一个分支:M5经过步长为2的max pooling下采样得到 P6,作者指出使用P6是想得到更大的anchor尺度512×512。但P6是只用在 RPN中用来得到region proposal的,并不会作为后续Fast RCNN的输入。

    总结一下,ResNet-FPN作为RPN输入的feature map是 [公式] ,而作为后续Fast RCNN的输入则是 [公式] 。

    三、ResNet-FPN+Fast RCNN

    将ResNet-FPN和Fast RCNN进行结合,实际上就是Faster RCNN的了,但与最初的Faster RCNN不同的是,FPN产生了特征金字塔 [公式] ,而并非只是一个feature map。金字塔经过RPN之后会产生很多region proposal。这些region proposal是分别由 [公式] 经过RPN产生的,但用于输入到Fast RCNN中的是 [公式] ,也就是说要在 [公式] 中根据region proposal切出ROI进行后续的分类和回归预测。问题来了,我们要选择哪个feature map来切出这些ROI区域呢?实际上,我们会选择最合适的尺度的feature map来切ROI。具体来说,我们通过一个公式来决定宽w和高h的ROI到底要从哪个[公式] 来切:

    这里224表示用于预训练的ImageNet图片的大小。 [公式] 表示面积为 [公式] 的ROI所应该在的层级。作者将 [公式] 设置为4,也就是说 [公式] 的ROI应该从 [公式] 中切出来。假设ROI的scale小于224(比如说是112 * 112), [公式] ,就意味着要从更高分辨率的 [公式] 中产生。另外,[公式] 值会做取整处理,防止结果不是整数。

    这种做法很合理,大尺度的ROI要从低分辨率的feature map上切,有利于检测大目标,小尺度的ROI要从高分辨率的feature map上切,有利于检测小目标。

    四、ResNet-FPN+Fast RCNN+mask

    我们再进一步,将ResNet-FPN+Fast RCNN+mask,则得到了最终的Mask RCNN,如下图:

    Mask RCNN的构建很简单,只是在ROI pooling(实际上用到的是ROIAlign,后面会讲到)之后添加卷积层,进行mask预测的任务。

    下面总结一下Mask RCNN的网络:

    1. 骨干网络ResNet-FPN,用于特征提取,另外,ResNet还可以是:ResNet-50,ResNet-101,ResNeXt-50,ResNeXt-101;
    2. 头部网络,包括边界框识别(分类和回归)+mask预测。头部结构见下图:

    五、ROI Align

    实际上,Mask RCNN中还有一个很重要的改进,就是ROIAlign。Faster R-CNN存在的问题是:特征图与原始图像是不对准的(mis-alignment),所以会影响检测精度。而Mask R-CNN提出了RoIAlign的方法来取代ROI pooling,RoIAlign可以保留大致的空间位置。

    为了讲清楚ROI Align,这里先插入两个知识,双线性插值和ROI pooling。

    1.双线性插值

    在讲双线性插值之前,还得看最简单的线性插值。

    线性插值

    已知数据 [公式] 与 [公式] ,要计算 [公式] 区间内某一位置 [公式] 在直线上的 [公式] 值,如下图所示。

    计算方法很简单,通过斜率相等就可以构建y和x之间的关系,如下:
    [公式]
    仔细看就是用 [公式] 和 [公式] , [公式] 的距离作为一个权重(除以 [公式] 是归一化的作用),用于 [公式] 和 [公式] 的加权。这个思想很重要,因为知道了这个思想,理解双线性插值就非常简单了。

    双线性插值

    双线性插值本质上就是在两个方向上做线性插值。

    如图,假设我们想得到P点的插值,我们可以先在x方向上,对 [公式] 和 [公式] 之间做线性插值得到 [公式] , [公式] 同理可得。然后在y方向上对 [公式] 和 [公式] 进行线性插值就可以得到最终的P。其实知道这个就已经理解了双线性插值的意思了,如果用公式表达则如下(注意 [公式] 前面的系数看成权重就很好理解了)。

    首先在 x 方向进行线性插值,得到

    然后在 y 方向进行线性插值,得到


    这样就得到所要的结果 [公式]

     

    参考:维基百科:双线性插值

    2.ROIpooling

    ROI pooling就不多解释了,直接通过一个例子来形象理解。假设现在我们有一个8x8大小的feature map,我们要在这个feature map上得到ROI,并且进行ROI pooling到2x2大小的输出。

    假设ROI的bounding box为 [公式] 。如图:

    将它划分为2x2的网格,因为ROI的长宽除以2是不能整除的,所以会出现每个格子大小不一样的情况。

    进行max pooling的最终2x2的输出为:

    最后以一张动图形象概括之:

    参考:Region of interest pooling explained

    3. ROI Align

    在Faster RCNN中,有两次整数化的过程:

    1. region proposal的xywh通常是小数,但是为了方便操作会把它整数化。
    2. 将整数化后的边界区域平均分割成 k x k 个单元,对每一个单元的边界进行整数化。

    两次整数化的过程如下图所示:

    事实上,经过上述两次整数化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,作者把它总结为“不匹配问题”(misalignment)。

    为了解决这个问题,ROI Align方法取消整数化操作,保留了小数,使用以上介绍的双线性插值的方法获得坐标为浮点数的像素点上的图像数值。但在实际操作中,ROI Align并不是简单地补充出候选区域边界上的坐标点,然后进行池化,而是重新进行设计。

    下面通过一个例子来讲解ROI Align操作。如下图所示,虚线部分表示feature map,实线表示ROI,这里将ROI切分成2x2的单元格。如果采样点数是4,那我们首先将每个单元格子均分成四个小方格(如红色线所示),每个小方格中心就是采样点。这些采样点的坐标通常是浮点数,所以需要对采样点像素进行双线性插值(如四个箭头所示),就可以得到该像素点的值了。然后对每个单元格内的四个采样点进行maxpooling,就可以得到最终的ROIAlign的结果。

    需要说明的是,在相关实验中,作者发现将采样点设为4会获得最佳性能,甚至直接设为1在性能上也相差无几。事实上,ROI Align 在遍历取样点的数量上没有ROIPooling那么多,但却可以获得更好的性能,这主要归功于解决了misalignment的问题。

    六、损失

    Mask RCNN定义多任务损失:
    [公式]

    [公式]和 [公式] 与faster rcnn的定义没有区别。需要具体说明的是 [公式] ,假设一共有K个类别,则mask分割分支的输出维度是 [公式] , 对于 [公式] 中的每个点,都会输出K个二值Mask(每个类别使用sigmoid输出)。需要注意的是,计算loss的时候,并不是每个类别的sigmoid输出都计算二值交叉熵损失,而是该像素属于哪个类,哪个类的sigmoid输出才要计算损失(如图红色方形所示)。并且在测试的时候,我们是通过分类分支预测的类别来选择相应的mask预测。这样,mask预测和分类预测就彻底解耦了。

    这与FCN方法是不同,FCN是对每个像素进行多类别softmax分类,然后计算交叉熵损失,很明显,这种做法是会造成类间竞争的,而每个类别使用sigmoid输出并计算二值损失,可以避免类间竞争。实验表明,通过这种方法,可以较好地提升性能。

    七、代码

    我用到的代码是github上star最多的Mask RCNN代码:Mask R-CNN for object detection and instance segmentation on Keras and TensorFlow

    由于篇幅所限,不会在本文中讲解代码。但会由我的一个同事( 

    @深度眸

     知乎用户)视频讲解,视频即将录制,录好之后我会把视频链接发在这里,感兴趣的可以关注。如果对视频内容有什么需求,欢迎留言。

    参考

    文章中有些图片来自medium博主:Jonathan Hui

    如果这篇文章对你有帮助,就给点个赞呗。

    展开全文
  • mask rcnn训练自己的数据集

    万次阅读 多人点赞 2018-07-13 21:05:51
    最近迷上了mask rcnn,也是由于自己工作需要吧,特意研究了其源代码,并基于自己的数据进行训练~ 本博客参考https://blog.csdn.net/disiwei1012/article/details/79928679#commentsedit 实验目的 ...

    前言

    最近迷上了mask rcnn,也是由于自己工作需要吧,特意研究了其源代码,并基于自己的数据进行训练~
    本博客参考https://blog.csdn.net/disiwei1012/article/details/79928679#commentsedit

    实验目的

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    哎~说多了都是泪,谁让我是工科生呢?只能检测工件了。。。做不了高大上的东西了,哈哈

    主要参考及工具

    基于Mask RCNN开源项目:https://github.com/matterport/Mask_RCNN
    图片标记工具基于开源项目:https://github.com/wkentaro/labelme
    训练工具:win10+GTX1060+cuda9.1+cudnn7+tensorflow-gpu-1.6.0+keras-2.1.6,140幅图像,一共3类,1小时左右

    有关labelme的使用可以参考:https://blog.csdn.net/shwan_ma/article/details/77823281

    有关mask-rcnn和Faster RCNN算法可以参考:
    https://blog.csdn.net/linolzhang/article/details/71774168
    https://blog.csdn.net/lk123400/article/details/54343550/

    准备训练数据集

    这是我简历的四个文件夹,下面一一道来~
    这里写图片描述
    1.pic
    这里写图片描述
    这是训练的图像,一共700幅

    2.json
    这里写图片描述
    这是通过labelme处理训练图像后生成的文件

    3.labelme_json
    这里写图片描述
    这里写图片描述
    这个是处理.json文件后产生的数据,使用方法为labelme_json_to_dataset+空格+文件名称.json,这个前提是labelme要准确安装并激活。但是这样会产生一个问题,对多幅图像这样处理,太麻烦,在这里提供一个工具,可以直接在.json文件目录下转换所有的json文件,链接:json数据转换工具

    4.cv2_mask文件

    由于labelme生成的掩码标签 label.png为16位存储,opencv默认读取8位,需要将16位转8位,可通过C++程序转化,代码请参考这篇博文:http://blog.csdn.net/l297969586/article/details/79154150
    这里写图片描述
    一团黑,不过不要怕,正常的~

    源代码

    运行该代码,需要安装pycocotools,在windows下安装该工具非常烦,有的可以轻松的安装成功,有的重装系统也很难成功,哎,都是坑~~关于Windows下安装pycocotools请参考:https://blog.csdn.net/chixia1785/article/details/80040172https://blog.csdn.net/gxiaoyaya/article/details/78363391

    测试的源代码

    Github上开源的代码,是基于ipynb的,我直接把它转换成.py文件,首先做个测试,基于coco数据集上训练好的模型,可以调用摄像头~~~

    import os
    import sys
    import random
    import math
    import numpy as np
    import skimage.io
    import matplotlib
    import matplotlib.pyplot as plt
    import cv2
    import time
    # 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
    
    
    # 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(MODEL_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)
        print("cuiwei***********************")
    
    # Directory of images to run detection on
    IMAGE_DIR = os.path.join(ROOT_DIR, "images")
    
    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()
    
    
    # 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)
    
    # 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']
    # 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)))
    cap = cv2.VideoCapture(0)
    
    while(1):
        # get a frame
        ret, frame = cap.read()
        # show a frame
        start =time.clock()
        results = model.detect([frame], verbose=1)
        r = results[0]
        #cv2.imshow("capture", frame)
        visualize.display_instances(frame, r['rois'], r['masks'], r['class_ids'], 
                                class_names, r['scores'])
        end = time.clock()
        print(end-start)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    cap.release()
    cv2.destroyAllWindows() 
    
    #image= cv2.imread("C:\\Users\\18301\\Desktop\\Mask_RCNN-master\\images\\9.jpg")
    ## Run detection
    #
    #results = model.detect([image], verbose=1)
    #
    #print(end-start)
    ## Visualize results
    #r = results[0]
    #visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
    #                            class_names, r['scores'])
    

    这里写图片描述
    这里写图片描述
    这里写图片描述
    关于训练好的mask rcnn模型,可从此处下载:https://github.com/matterport/Mask_RCNN/releases,下载好后,配置路径即可

    训练数据源代码

    # -*- coding: utf-8 -*-
    
    import os
    import sys
    import random
    import math
    import re
    import time
    import numpy as np
    import cv2
    import matplotlib
    import matplotlib.pyplot as plt
    import tensorflow as tf
    from mrcnn.config import Config
    #import utils
    from mrcnn import model as modellib,utils
    from mrcnn import visualize
    import yaml
    from mrcnn.model import log
    from PIL import Image
    
    
    #os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    # Root directory of the project
    ROOT_DIR = os.getcwd()
    
    #ROOT_DIR = os.path.abspath("../")
    # Directory to save logs and trained model
    MODEL_DIR = os.path.join(ROOT_DIR, "logs")
    
    iter_num=0
    
    # 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)
    
    
    class ShapesConfig(Config):
        """Configuration for training on the toy shapes dataset.
        Derives from the base Config class and overrides values specific
        to the toy shapes dataset.
        """
        # Give the configuration a recognizable name
        NAME = "shapes"
    
        # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
        # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
        GPU_COUNT = 1
        IMAGES_PER_GPU = 2
    
        # Number of classes (including background)
        NUM_CLASSES = 1 + 3  # background + 3 shapes
    
        # Use small images for faster training. Set the limits of the small side
        # the large side, and that determines the image shape.
        IMAGE_MIN_DIM = 320
        IMAGE_MAX_DIM = 384
    
        # Use smaller anchors because our image and objects are small
        RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6)  # anchor side in pixels
    
        # Reduce training ROIs per image because the images are small and have
        # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
        TRAIN_ROIS_PER_IMAGE = 100
    
        # Use a small epoch since the data is simple
        STEPS_PER_EPOCH = 100
    
        # use small validation steps since the epoch is small
        VALIDATION_STEPS = 50
    
    
    config = ShapesConfig()
    config.display()
    
    class DrugDataset(utils.Dataset):
        # 得到该图中有多少个实例(物体)
        def get_obj_index(self, image):
            n = np.max(image)
            return n
    
        # 解析labelme中得到的yaml文件,从而得到mask每一层对应的实例标签
        def from_yaml_get_class(self, image_id):
            info = self.image_info[image_id]
            with open(info['yaml_path']) as f:
                temp = yaml.load(f.read())
                labels = temp['label_names']
                del labels[0]
            return labels
    
        # 重新写draw_mask
        def draw_mask(self, num_obj, mask, image,image_id):
            #print("draw_mask-->",image_id)
            #print("self.image_info",self.image_info)
            info = self.image_info[image_id]
            #print("info-->",info)
            #print("info[width]----->",info['width'],"-info[height]--->",info['height'])
            for index in range(num_obj):
                for i in range(info['width']):
                    for j in range(info['height']):
                        #print("image_id-->",image_id,"-i--->",i,"-j--->",j)
                        #print("info[width]----->",info['width'],"-info[height]--->",info['height'])
                        at_pixel = image.getpixel((i, j))
                        if at_pixel == index + 1:
                            mask[j, i, index] = 1
            return mask
    
        # 重新写load_shapes,里面包含自己的类别,可以任意添加
        # 并在self.image_info信息中添加了path、mask_path 、yaml_path
        # yaml_pathdataset_root_path = "/tongue_dateset/"
        # img_floder = dataset_root_path + "rgb"
        # mask_floder = dataset_root_path + "mask"
        # dataset_root_path = "/tongue_dateset/"
        def load_shapes(self, count, img_floder, mask_floder, imglist, dataset_root_path):
            """Generate the requested number of synthetic images.
            count: number of images to generate.
            height, width: the size of the generated images.
            """
            # Add classes,可通过这种方式扩展多个物体
            self.add_class("shapes", 1, "tank") # 黑色素瘤
            self.add_class("shapes", 2, "triangle")
            self.add_class("shapes", 3, "white")
            for i in range(count):
                # 获取图片宽和高
    
                filestr = imglist[i].split(".")[0]
                #print(imglist[i],"-->",cv_img.shape[1],"--->",cv_img.shape[0])
                #print("id-->", i, " imglist[", i, "]-->", imglist[i],"filestr-->",filestr)
                #filestr = filestr.split("_")[1]
                mask_path = mask_floder + "/" + filestr + ".png"
                yaml_path = dataset_root_path + "labelme_json/" + filestr + "_json/info.yaml"
                print(dataset_root_path + "labelme_json/" + filestr + "_json/img.png")
                cv_img = cv2.imread(dataset_root_path + "labelme_json/" + filestr + "_json/img.png")
    
                self.add_image("shapes", image_id=i, path=img_floder + "/" + imglist[i],
                               width=cv_img.shape[1], height=cv_img.shape[0], mask_path=mask_path, yaml_path=yaml_path)
    
        # 重写load_mask
        def load_mask(self, image_id):
            """Generate instance masks for shapes of the given image ID.
            """
            global iter_num
            print("image_id",image_id)
            info = self.image_info[image_id]
            count = 1  # number of object
            img = Image.open(info['mask_path'])
            num_obj = self.get_obj_index(img)
            mask = np.zeros([info['height'], info['width'], num_obj], dtype=np.uint8)
            mask = self.draw_mask(num_obj, mask, img,image_id)
            occlusion = np.logical_not(mask[:, :, -1]).astype(np.uint8)
            for i in range(count - 2, -1, -1):
                mask[:, :, i] = mask[:, :, i] * occlusion
    
                occlusion = np.logical_and(occlusion, np.logical_not(mask[:, :, i]))
            labels = []
            labels = self.from_yaml_get_class(image_id)
            labels_form = []
            for i in range(len(labels)):
                if labels[i].find("tank") != -1:
                    # print "box"
                    labels_form.append("tank")
                elif labels[i].find("triangle")!=-1:
                    #print "column"
                    labels_form.append("triangle")
                elif labels[i].find("white")!=-1:
                    #print "package"
                    labels_form.append("white")
            class_ids = np.array([self.class_names.index(s) for s in labels_form])
            return mask, class_ids.astype(np.int32)
    
    def get_ax(rows=1, cols=1, size=8):
        """Return a Matplotlib Axes array to be used in
        all visualizations in the notebook. Provide a
        central point to control graph sizes.
    
        Change the default size attribute to control the size
        of rendered images
        """
        _, ax = plt.subplots(rows, cols, figsize=(size * cols, size * rows))
        return ax
    
    #基础设置
    dataset_root_path="train_data/"
    img_floder = dataset_root_path + "pic"
    mask_floder = dataset_root_path + "cv2_mask"
    #yaml_floder = dataset_root_path
    imglist = os.listdir(img_floder)
    count = len(imglist)
    
    #train与val数据集准备
    dataset_train = DrugDataset()
    dataset_train.load_shapes(count, img_floder, mask_floder, imglist,dataset_root_path)
    dataset_train.prepare()
    
    #print("dataset_train-->",dataset_train._image_ids)
    
    dataset_val = DrugDataset()
    dataset_val.load_shapes(7, img_floder, mask_floder, imglist,dataset_root_path)
    dataset_val.prepare()
    
    #print("dataset_val-->",dataset_val._image_ids)
    
    # Load and display random samples
    #image_ids = np.random.choice(dataset_train.image_ids, 4)
    #for image_id in image_ids:
    #    image = dataset_train.load_image(image_id)
    #    mask, class_ids = dataset_train.load_mask(image_id)
    #    visualize.display_top_masks(image, mask, class_ids, dataset_train.class_names)
    
    # Create model in training mode
    model = modellib.MaskRCNN(mode="training", config=config,
                              model_dir=MODEL_DIR)
    
    # Which weights to start with?
    init_with = "coco"  # imagenet, coco, or last
    
    if init_with == "imagenet":
        model.load_weights(model.get_imagenet_weights(), by_name=True)
    elif init_with == "coco":
        # Load weights trained on MS COCO, but skip layers that
        # are different due to the different number of classes
        # See README for instructions to download the COCO weights
        model.load_weights(COCO_MODEL_PATH, by_name=True,
                           exclude=["mrcnn_class_logits", "mrcnn_bbox_fc",
                                    "mrcnn_bbox", "mrcnn_mask"])
    elif init_with == "last":
        # Load the last model you trained and continue training
        model.load_weights(model.find_last()[1], by_name=True)
    
    # Train the head branches
    # Passing layers="heads" freezes all layers except the head
    # layers. You can also pass a regular expression to select
    # which layers to train by name pattern.
    model.train(dataset_train, dataset_val,
                learning_rate=config.LEARNING_RATE,
                epochs=20,
                layers='heads')
    
    
    
    # Fine tune all layers
    # Passing layers="all" trains all layers. You can also
    # pass a regular expression to select which layers to
    # train by name pattern.
    model.train(dataset_train, dataset_val,
                learning_rate=config.LEARNING_RATE / 10,
                epochs=40,
                layers="all")
    

    这里写图片描述

    关于训练过程的参数设置,可在config.py文件中修改,根据自己的要求啦~官方也给出了修改建议:https://github.com/matterport/Mask_RCNN/wiki

    可修改的主要有:

    BACKBONE = “resnet50” ;这个是迁移学习调用的模型,分为resnet101和resnet50,电脑性能不是特别好的话,建议选择resnet50,这样网络更小,训练的更快。

    model.train(…, layers=‘heads’, …) # Train heads branches (least memory)
    model.train(…, layers=‘3+’, …) # Train resnet stage 3 and up
    model.train(…, layers=‘4+’, …) # Train resnet stage 4 and up
    model.train(…, layers=‘all’, …) # Train all layers (most memory)#这里是选择训练的层数,根据自己的要求选择

    IMAGE_MIN_DIM = 800
    IMAGE_MAX_DIM = 1024#设置训练时的图像大小,最终以IMAGE_MAX_DIM为准,如果电脑性能不是太好,建议调小

    GPU_COUNT = 1
    IMAGES_PER_GPU = 2#这个是对GPU的设置,如果显存不够,建议把2调成1(虽然batch_size为1并不利于收敛)

    TRAIN_ROIS_PER_IMAGE = 200;可根据自己数据集的真实情况来设定

    MAX_GT_INSTANCES = 100;设置图像中最多可检测出来的物体数量

    数据集按照上述格式建立,然后配置好路径即可训练,在windows训练的时候有个问题,就是会出现训练时一直卡在epoch1,这个问题是因为keras在低版本中不支持多线程(在windows上),推荐keras2.1.6,这个亲测可以~

    训练的模型会保存在logs文件夹下,.h5格式,训练好后直接调用即可

    测试模型的代码

    # -*- coding: utf-8 -*-
    import os
    import sys
    import random
    import math
    import numpy as np
    import skimage.io
    import matplotlib
    import matplotlib.pyplot as plt
    import cv2
    import time
    from mrcnn.config import Config
    from datetime import datetime 
    # Root directory of the project
    ROOT_DIR = os.getcwd()
    
    # 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
    from samples.coco import coco
    
    
    # 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(MODEL_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)
        print("cuiwei***********************")
    
    # Directory of images to run detection on
    IMAGE_DIR = os.path.join(ROOT_DIR, "images")
    
    class ShapesConfig(Config):
        """Configuration for training on the toy shapes dataset.
        Derives from the base Config class and overrides values specific
        to the toy shapes dataset.
        """
        # Give the configuration a recognizable name
        NAME = "shapes"
    
        # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
        # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
        GPU_COUNT = 1
        IMAGES_PER_GPU = 1
    
        # Number of classes (including background)
        NUM_CLASSES = 1 + 3  # background + 3 shapes
    
        # Use small images for faster training. Set the limits of the small side
        # the large side, and that determines the image shape.
        IMAGE_MIN_DIM = 320
        IMAGE_MAX_DIM = 384
    
        # Use smaller anchors because our image and objects are small
        RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6)  # anchor side in pixels
    
        # Reduce training ROIs per image because the images are small and have
        # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
        TRAIN_ROIS_PER_IMAGE =100
    
        # Use a small epoch since the data is simple
        STEPS_PER_EPOCH = 100
    
        # use small validation steps since the epoch is small
        VALIDATION_STEPS = 50
    
    #import train_tongue
    #class InferenceConfig(coco.CocoConfig):
    class InferenceConfig(ShapesConfig):
        # 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()
    
    model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
    
    
    # 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)
    
    # 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', 'tank','triangle','white']
    # 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)))
    
    a=datetime.now() 
    # Run detection
    results = model.detect([image], verbose=1)
    b=datetime.now() 
    # Visualize results
    print("shijian",(b-a).seconds)
    r = results[0]
    visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
                                class_names, r['scores'])
    
    

    这里写图片描述
    这里写图片描述
    当然,这里由于训练数据太少,效果不是特别好~~~工业上的图像不是太好获取。。。
    那么如何把定位坐标和分割像素位置输出呢?其实都在visualize.py文件中,就是里面的display_instances函数。
    这里写图片描述
    这里写图片描述
    最后的输出结果

    其中,mask输出box区域内的每个像素为true还是false,依次遍历box里的行和列。
    最后,该工程的源代码地址为:https://download.csdn.net/download/qq_29462849/10540423,其中train_test为训练代码,test_model为测试代码,配置好路径,即可直接运行~~~

    最后欢迎加入3D视觉工坊,一起交流学习~

    在这里插入图片描述

    展开全文
  • mask rcnn

    2017-11-10 16:19:00
    Mask RCNN Mask RCNN 中主要改进是在faster rcnn中box regression 的branch 上加入mask prediction branch,能够得到点到点的预测。 主要特点为: mask branch 是一个FCN结构,对每个ROI region 产生k * m*m 的...

    Mask RCNN

    Mask RCNN 中主要改进是在faster rcnn中box regression 的branch 上加入mask prediction branch,能够得到点到点的预测。

    主要特点为: 

    • mask branch 是一个FCN结构,对每个ROI region  产生k * m*m 的mask 结果,k 为分类类别数。与FCN最大的不同是对分类和分割解耦。假设groundtruth 中目标属于类别k,则损失只和第k个mask 有关,其它mask 不参与损失的计算。每个mask 计算二分类的交叉熵损失(属于此类别或不属于),而不像FCN中计算每个点的softmax 和多分类的交叉熵损失。
    • ROIAlign: 对于faster rcnn 中的ROI Pooling,其在生成feature map 多次取整,因此在进行点到点的预测时,会有较大的偏差,在mask rcnn 中采用RoIAlign 层,将ROI Pooling 时对应的[x/16] 转换为x/16, 不进行取整,采用双线性插值使得准确计算每个ROI bin是的位置,保留非整数。

     

    转载于:https://www.cnblogs.com/fanhaha/p/7815242.html

    展开全文
  • Mask RCNN:Pytorch实现 使用Pytorch框架屏蔽RCNN实现。 banchmark: : 要求 Python> = 3.6。 PyTorch> = 1.5,并且Torchvision与PyTorch安装匹配。 执照 该存储库是根据MIT许可发布的。
  • Mask RCNN是大神Kaiming He的一大神作。 1、概述 Mask RCNN主要是再Faster RCNN上进行了一些调整(将RoIpooling层替换为了RoIAlign层),并且在RoIAlign后增加了一个进行instance segmentation的分支。 图片来源...

    Mask RCNN是大神Kaiming He的一大神作。

    1、概述

    Mask RCNN主要是再Faster RCNN上进行了一些调整(将RoIpooling层替换为了RoIAlign层),并且在RoIAlign后增加了一个进行instance segmentation的分支。

    上图展示了一个Mask RCNN的网络结构,用RoIAlign来代替RoIpooling部分,并且在分类与回归中添加了并列的分支FCN(mask层)

    2、loss function

    训练中,文章定义了多个任务的损失是对每一个RoI有L=L_{cls}+L_{reg}+L_{mask},其中的前两个损失是同faster RCNN中一样的定义,而第三个损失L_{mask}是mask层的损失计算。mask对应的每个RoI的输出维度是K*m^2,表示K个类别共有K个mxm的二进制掩码【论文中m*m对应池化分辨率7*7,通过对每个class对应一个mask可以有效地避免同类竞争】,这里使用的是per-pixel sigmoid【在论文中有与per-pixel softmax进行对比】,将损失函数定义为L_mask average binary cross-entropy,loss只定义在有对应gt的mask上,其他mask不对loss有贡献值。

    3、RoIAlign【重点推荐:一篇不错的文

    论文比较主要的地方是用RoIAlign来代替RoIpooling,因为原来的faster RCNN是无需做实例分割的,而实例分割是需要在pixel级别上有较高的精确度,但是因为RoIpooling的量化操作,使其对实力分割上的一个精度会比较低,因此作者就提出了使用RoIAlign来代替RoIpooling。

    • RoIpooling的操作主要是为了将不同尺寸的feature map操作成尺寸一样大小的feature。
    • RoIAlign没有像RoIpooling那样做量化操作【in paper, use x/16 instead of round(x/16)】,并且使用了双线性插值to compute the exact values of the input features at four regularly sampled locations in each RoI bin, and aggregate the result(using max or average)【具体细节等看完代码吧】

    一张来自上面的链接博文的比较好的图。【理解:RoIAlign的RoI的边界无需量化取整,而是如图中RoIAlign部分,将得到的RoIAlign,框的边界仍然取浮点数,此时,在每个bin(最终需要得到的尺寸的规模为t*t,那么有t*t个bins)中取样四个点【平均取的四个点?】】,四个点的值由邻近的feature map的pixel值通过双线性插值法来取得,最后将这四个采样点的值进行max或average来作为这个bin的值,最终可得到尺寸大小一样的RoI所对应的更加精确的feature map区域值。   第三种方法是使用了积分的方法,链接博文中说会更加精确,但是会比较耗时。】

    4、结果对比

    5、Mask RCNN扩展——

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 使用TensorFlow和Keras从零开始构建maskrcnn 在TensorFlow 2.4.1中进行了测试说明: : 1.文件: GenerateToyDataset_fromscratch.ipynb:使用掩码和LIDC-IDRI数据集生成玩具数据集的脚本。 ./masks/:包含两个...
  • Chainer-Maskrcnn 原始纸 遮罩R-CNN 轻头R-CNN: : 当前状态 使用LightHead架构 很好的例子:) 这里有许多结果 _ 功能金字塔网络 面罩的准确性看起来比上面更好。 关键点 120000 iter受过训练 待办事项 我们目前...
  • 大名鼎鼎的 Mask RCNN 一举夺得 ICCV2017 Best Paper,名声大造。Mask RCNN 是何恺明基于以往的 Faster RCNN 架构提出的新的卷积网络,实现高效地检测图中的物体,并同时生成一张高质量的每个个体的分割掩码,即有效...
  • Mask RCNN】论文详解(真的很详细)

    万次阅读 多人点赞 2018-10-18 00:42:14
    本文主要是针对论文的详细解析,选出文章各部分的关键点,方便阅读立即。 目录: 摘要: 1、Introduction ...3、Mask R-CNN 3.1 Implementation Details 4、Experiments: Instance Segmentation 4...
  • Mask RCNN 实战(一)--代码详细解析

    万次阅读 多人点赞 2018-04-25 21:51:24
    Mask RCNN:(大家有疑问的请在评论区留言) 如果对原理不了解的话,可以花十分钟先看一下我的这篇博文,在来进行实战演练,这篇博文将是让大家对mask rcnn 进行一个入门,我在后面的博文中会介绍mask rcnn 如何用于...
  • 2.3 配置maskrcnn-benchmark maskrcnn-benchmark是facebook research开源的目标检测和实例分割的算法仓库,可以实现的模型有Faster RCNN,Mask RCNN,RetinaNet等。 1. 环境要求 PyTorch...
  • 大名鼎鼎的 Mask RCNN 一举夺得 ICCV2017 Best Paper,名声大造。Mask RCNN 是何恺明基于以往的 Faster RCNN 架构提出的新的卷积网络,实现高...
  • 分段-unet-maskrcnn 使用Unet或Mask RCNN进行卫星图像分割的代码,并比较这两种方法。 请在博客文章“ 查看更多详细信息 开始吧 :使用翻转(镜像效果),rotate90,上下翻转,左右翻转来增强数据。 数据 mask...
  • 大家好,这是我的第一篇博客。作为深度学习的初学者,从实战的角度,详细介绍基于maskrcnn-benchmark框架下,使用Maskrcnn网络训练自己的数据集的过程。这其中,踩的坑不少,但也受益匪浅。
  • 原标题:1小时上手MaskRCNN·Keras开源实战 | 深度应用作者 | 小宋是呢来源 | CSDN博客0. 前言介绍开源地址:https://github.com/matterport/Mask_RCNN个人主页:http://www.yansongsong.cn/MaskRCNN 是何恺明基于...
  • mask rcnn解读

    万次阅读 多人点赞 2017-11-21 00:08:52
    上一篇中介绍faster rcnn,这次mask 基本在上次的基础上加了点代码,参考和引用1. mask rcnn slides 2. kaiming he maskrcnn 3. Ardian Umam mask rcnn,欢迎fork简版mask rcnn。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,001
精华内容 4,800
关键字:

maskrcnn