【问题标题】:Mask R-CNN for object detection and segmentation [Train for a custom dataset]用于对象检测和分割的 Mask R-CNN [训练自定义数据集]
【发布时间】:2018-09-15 23:46:35
【问题描述】:

我正在研究“Mask R-CNN 用于对象检测和分割”。所以我阅读了原始研究论文,其中介绍了Mask R-CNN 用于对象检测,并且我发现很少有Mask R-CNNherehere 的实现(由 Facebook AI 研究团队称为检测器)。但他们都使用 coco 数据集进行测试。

但是对于使用具有大量图像的自定义数据集进行上述实现的训练,我有点困惑,并且对于每个图像,都有一个掩码图像子集用于标记相应图像中的对象。

因此,如果有人可以为此任务发布有用的资源或代码示例,我很高兴。

注意:我的数据集具有以下结构,

它由大量图像组成,对于每张图像,都有 是单独的图像文件,将对象突出显示为 黑色图像。

这是一个示例图像和它的面具:

图片;

口罩;

【问题讨论】:

    标签: python machine-learning computer-vision object-detection semantic-segmentation


    【解决方案1】:

    我已经训练了 https://github.com/matterport/Mask_RCNN 的实例分割模型,以便在我的数据集上运行。

    我的假设是您已完成所有基本设置,并且模型已经使用默认数据集(在 repo 中提供)运行,现在您希望它为自定义数据集运行。

    以下是步骤

    1. 您需要拥有所有注释。
    2. 所有这些都需要转换为 VGG 多边形模式(是的,我的意思是多边形,即使您需要绑定框)。我在这个答案的末尾添加了一个示例 VGG 多边形格式。
    3. 您需要将自定义数据集划分为训练、测试和验证
    4. 默认情况下,注解在单个数据集文件夹中使用文件名via_region_data.json 进行查看。例如,对于训练图像,它会查看train\via_region_data.json。您也可以根据需要进行更改。
    5. 在 Samples 文件夹中,您可以找到 Balloon、Nucleus、Shapes 等文件夹。复制其中一个文件夹。最好是气球。我们现在将尝试为我们的自定义数据集修改这个新文件夹。
    6. 在复制的文件夹中,您将有一个.py 文件(对于气球,它将是气球.py),更改以下变量
      • ROOT_DIR : 克隆项目的绝对路径
      • DEFAULT_LOGS_DIR :这个文件夹会变大,所以相应地改变这个路径(如果你在低磁盘存储虚拟机中运行你的代码)。它还将存储.h5 文件。它将在日志文件夹中创建子文件夹,并附加时间戳。
      • .h5 文件大约为每个 epoch 200 - 300 MB。但是猜猜这个日志目录与 Tensorboard 兼容。您可以在运行 tensorboard 时将带时间戳的子文件夹作为 --logdir 参数传递。
    7. 这个.py 文件也有两个类——一个类后缀为Config,另一个类后缀为Dataset
    8. 在 Config 类中覆盖所需的内容,例如
      • NAME :您的项目的名称。
      • NUM_CLASSES : 它应该比你的标签类多一个,因为背景也被认为是一个标签
      • DETECTION_MIN_CONFIDENCE :默认为 0.9(如果您的训练图像质量不是很高或您没有太多训练数据,则将其减小)
      • STEPS_PER_EPOCH
    9. 在 Dataset 类中重写以下方法。所有这些功能都已经很好地注释了,因此您可以按照 cmets 根据您的需要进行覆盖。
      • load_(name_of_the_sample_project) 例如 load_balloon
      • load_mask(请参阅答案的最后一个示例)
      • 图像参考
    10. train 函数(在 Dataset 类之外):如果您必须更改 epoch 数或学习率等

    您现在可以直接从终端运行它

    python samples\your_folder_name\your_python_file_name.py train --dataset="location_of_custom_dataset" --weights=coco
    

    有关上述行的命令行参数的完整信息,您可以在此 .py 文件的顶部将其作为注释查看。

    这些是我能记得的事情,我想添加更多我记得的步骤。如果您卡在任何特定步骤,也许您可​​以告诉我,我会详细说明该特定步骤。

    VGG 多边形架构

    宽度和高度是可选的

    [{
        "filename": "000dfce9-f14c-4a25-89b6-226316f557f3.jpeg",
        "regions": {
            "0": {
                "region_attributes": {
                    "object_name": "Cat"
                },
                "shape_attributes": {
                    "all_points_x": [75.30864197530865, 80.0925925925926, 80.0925925925926, 75.30864197530865],
                    "all_points_y": [11.672189112257607, 11.672189112257607, 17.72093488703078, 17.72093488703078],
                    "name": "polygon"
                }
            },
            "1": {
                "region_attributes": {
                    "object_name": "Cat"
                },
                "shape_attributes": {
                    "all_points_x": [80.40123456790124, 84.64506172839506, 84.64506172839506, 80.40123456790124],
                    "all_points_y": [8.114103362391036, 8.114103362391036, 12.205901974737595, 12.205901974737595],
                    "name": "polygon"
                }
            }
        },
        "width": 504,
        "height": 495
    }]
    

    示例 load_mask 函数

    def load_mask(self, image_id):
        """Generate instance masks for an image.
        Returns:
        masks: A bool array of shape [height, width, instance count] with
            one mask per instance.
        class_ids: a 1D array of class IDs of the instance masks.
        """
        # If not your dataset image, delegate to parent class.
        image_info = self.image_info[image_id]
        if image_info["source"] != "name_of_your_project":   //change your project name
            return super(self.__class__, self).load_mask(image_id)
    
        # Convert polygons to a bitmap mask of shape
        # [height, width, instance_count]
        info = self.image_info[image_id]
        mask = np.zeros([info["height"], info["width"], len(info["polygons"])], dtype=np.uint8)
        class_id =  np.zeros([mask.shape[-1]], dtype=np.int32)
    
        for i, p in enumerate(info["polygons"]):
            # Get indexes of pixels inside the polygon and set them to 1
            rr, cc = skimage.draw.polygon(p['all_points_y'], p['all_points_x'])
            # print(rr.shape, cc.shape, i, np.ones([mask.shape[-1]], dtype=np.int32).shape, info['classes'][i])
    
            class_id[i] = self.class_dict[info['classes'][i]]
            mask[rr, cc, i] = 1
    
    
        # Return mask, and array of class IDs of each instance. Since we have
        # one class ID only, we return an array of 1s
        return mask.astype(np.bool), class_id
    

    【讨论】:

    • 我一直在尝试按照您的步骤进行操作。我的困惑是在Dataset 类中重新分级load_mask()。已经提到需要根据数据集编写自己的掩码。我想知道编写掩码我们的特定数据集需要什么样的逻辑或步骤?
    • @BhabaniMohapatra 我已将 Dataset 类中的 load_mask 函数添加为示例...
    • 很有帮助。关于load_mask() 的一个理论问题,通常除了转换多边形(我已经使用 VGG 注释器工具注释并将其保存为 json 格式)以掩盖它遵循的其他实现?
    • 让我们以 COCO 数据集及其注释为例。我们通常在那里提取多边形并从中生成二进制掩码,然后转换为 COCO 多边形格式(因为用于 COCO 分割的 json 文件有点不同)。在我看来,这里没有实现,而是我们直接注释和保存多边形(上面的 load_mask() 函数很有用)。只是消除我的疑虑。谢谢
    【解决方案2】:

    所以首先,您需要提取每个图像的边界框。该任务必须手动完成,或者您可以使用OpenCV等工具


    编辑打开的简历

    同样对于白色部分,您必须使用您选择的任何工具来做最好的技术,我会用 OpenCV 来做。代码可能非常具体,因为可以使用不同的技术来处理它。没有其他方法,因为您没有注释,只有掩码。


    现在您已经获得了格式(x、y、宽度、高度)的图像和框。

    Detectron 具有 JSON 文件格式,例如: https://pastebin.com/ewaaC5Bm

    现在,您可以使用 images 值创建类似的 JSON,因为您已经获得了该信息。

    由于我们没有任何细分(在您的示例中),让我们澄清一下annotations 所采用的参数:

    • category_id:这是类别的 ID。您可以在pastebin 中看到我展示的唯一类别有id = 32。您需要根据数据集添加更多类别。

    • bbox:这就是我们上面讲的那个盒子:[x, y, width, height]

    现在对于iscrowdareasegmentation,我们显然可以采取两种方法:thisthis

    这样分割将不会被考虑(或将被考虑但被忽略)。

    祝你好运。

    【讨论】:

    • 非常感谢您的回答,非常有用,但是我也需要Instance segmentation,请问您可以改进您的回答吗??
    • 发布您的图片示例
    • 我发布了一个示例图片,请检查
    【解决方案3】:

    对于图像分割任务,有两种方法可以为训练代码提供掩码图像。

    1. 整个图像的蒙版图像。
    2. 图像中每个对象的遮罩图像。

    在 Mask R-CNN 中,你必须遵循 2。

    我们的 Mac OS X 应用程序 RectLabel 可以导出两个蒙版图像。

    1. 颜色表对应对象类id的索引彩色图像。

    2. 每个对象的灰度图像,由 0:background 和 255:foreground 组成。

    我们提供 python 代码示例,说明如何加载掩码图像并设置为掩码 R-CNN 代码的 TFRecord 文件。

    COCO JSON 文件到带有掩码图像的 TFRecord

    https://github.com/ryouchinsa/Rectlabel-support/blob/master/rectlabel_create_coco_tf_record.py

    python object_detection/dataset_tools/rectlabel_create_coco_tf_record.py \
    --train_image_dir="${TRAIN_IMAGE_DIR}" \
    --val_image_dir="${VAL_IMAGE_DIR}" \
    --train_annotations_file="${TRAIN_ANNOTATIONS_FILE}" \
    --val_annotations_file="${VAL_ANNOTATIONS_FILE}" \
    --output_dir="${OUTPUT_DIR}" \
    --include_masks
    

    PASCAL VOC XML 文件到带有蒙版图像的 TFRecord

    https://github.com/ryouchinsa/Rectlabel-support/blob/master/rectlabel_create_pascal_tf_record.py

    python object_detection/dataset_tools/rectlabel_create_pascal_tf_record.py \
    --images_dir="${IMAGES_DIR}" \
    --label_map_path="${LABEL_MAP_PATH}" \
    --output_path="${OUTPUT_PATH}" \
    --include_masks
    

    我们希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-18
      • 1970-01-01
      • 1970-01-01
      • 2021-08-11
      • 2021-06-09
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      相关资源
      最近更新 更多