Mask R-CNN 用于对象检测和分割 [Train for a custom dataset]

Mask R-CNN for object detection and segmentation [Train for a custom dataset]

我正在研究“Mask R-CNN 用于对象检测和分割”。因此,我阅读了介绍 Mask R-CNN 用于对象检测的原始研究论文,而且我发现很少有 Mask R-CNNhere and here 的实现(由 Facebook AI 研究团队称为 detectron)。但是他们都用coco数据集做测试

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

因此,如果有人可以 post 对这项任务有用的资源或代码示例,我将非常高兴。

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

It consists with a large number of images and for each image, there are separate image files highlighting the object as a white patch in a black image.

这是一个示例图像及其蒙版:

图片;

口罩;

所以首先,你需要提取每个图像的边界框。该任务必须手动完成,或者您可以使用 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 我们显然可以采用两种方法:this or this.

这样就不会考虑分段(或者会考虑但忽略)。

祝你好运。

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

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

步骤如下

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

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

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

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

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

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

我们的 Mac OS X app RectLabel 可以导出两个蒙版图像。

  1. 颜色table对应对象classid的索引彩色图像。

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

我们提供 python 代码示例,说明如何加载掩码图像并设置为 Mask 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

我们希望这会有所帮助。