使用自定义数据集

本文档解释了数据集API (DatasetCatalog, MetadataCatalog) 的工作原理,以及如何使用它们添加自定义数据集。

detectron2中内置支持的数据集列在内置数据集中。 如果您想使用自定义数据集,同时复用detectron2的数据加载器, 您需要:

  1. 注册你的数据集(即告诉detectron2如何获取你的数据集)。

  2. 可选地,注册元数据为您的数据集。

接下来,我们将详细解释上述两个概念。

Colab教程提供了一个如何注册和训练自定义格式数据集的实时示例。

注册数据集

为了让detectron2知道如何获取名为"my_dataset"的数据集,用户需要实现一个返回数据集中项目的函数,然后告知detectron2这个函数:

def my_dataset_function():
  ...
  return list[dict] in the following format

from detectron2.data import DatasetCatalog
DatasetCatalog.register("my_dataset", my_dataset_function)
# later, to access the data:
data: List[Dict] = DatasetCatalog.get("my_dataset")

这段代码片段将一个名为"my_dataset"的数据集与一个返回数据的函数关联起来。 该函数在多次调用时必须返回相同的数据(顺序也需一致)。 注册信息在进程退出前一直保持有效。

该函数可以执行任意操作,并应以list[dict]格式返回数据,其中每个字典需符合以下任一格式:

  1. Detectron2的标准数据集字典,如下所述。这将使其能够与detectron2中的许多其他内置功能配合使用,因此在满足需求时建议使用它。

  2. 任何自定义格式。你也可以返回任意自定义格式的字典,例如为新的任务添加额外的键。然后你还需要在下游正确处理它们。更多详情请参阅下文。

标准数据集字典

对于标准任务 (实例检测、实例/语义/全景分割、关键点检测), 我们将原始数据集加载到list[dict]中,其规范与COCO标注类似。 这是我们表示数据集的标准方式。

每个字典包含一张图像的信息。 该字典可能包含以下字段, 具体所需字段取决于数据加载器或任务需求(详见下文)。

任务

字段

通用

file_name, height, width, image_id

实例检测/分割

标注

语义分割

sem_seg_file_name

全景分割

pan_seg_file_name, segments_info

  • file_name: 图像文件的完整路径。

  • height, width: 整数。图像的形状。

  • image_id (str or int): 用于标识该图像的唯一ID。许多评估器需要使用此ID来识别图像,但数据集可能会将其用于不同目的。

  • annotations (list[dict]): 这是实例检测/分割或关键点检测任务所需的字段。 每个字典对应图像中一个实例的标注信息, 可能包含以下键值:

    • bbox (list[float], required): 表示实例边界框的4个数字组成的列表。

    • bbox_mode (int, 必填): 边界框的格式。它必须是 structures.BoxMode的成员。 当前支持: BoxMode.XYXY_ABS, BoxMode.XYWH_ABS.

    • category_id (int, 必填): 一个范围在[0, num_categories-1]之间的整数,表示类别标签。 如果适用的话,num_categories这个值被保留用来表示"背景"类别。

    • segmentation (list[list[float]] or dict): 实例的分割掩码。

      • 如果是 list[list[float]],则表示一组多边形列表,每个多边形对应物体的一个连通区域。每个 list[float] 是一个简单多边形,格式为 [x1, y1, ..., xn, yn] (n≥3)。X和Y值是以像素为单位的绝对坐标。

      • 如果是dict类型,则表示COCO压缩RLE格式的逐像素分割掩码。 该字典应包含"size"和"counts"两个键。您可以通过pycocotools.mask.encode(np.asarray(mask, order="F"))将0和1组成的uint8分割掩码转换为这种字典格式。 如果使用默认数据加载器处理此类格式,必须将cfg.INPUT.MASK_FORMAT设置为bitmask

    • keypoints (list[float]): 格式为[x1, y1, v1,…, xn, yn, vn]。 v[i]表示该关键点的可见性n必须等于关键点类别的数量。 X和Y是绝对实值坐标,范围在[0, W或H]之间。

      (注意COCO格式中的关键点坐标是整数,范围在[0, W-1或H-1]之间,这与我们的标准格式不同。 Detectron2会给COCO关键点坐标加0.5,将其从离散像素索引转换为浮点坐标。)

    • iscrowd: 0 (默认) 或 1。表示该实例是否被标记为COCO的"人群区域"。如果不了解该字段含义,请不要包含此字段。

    如果annotations是一个空列表,表示该图像被标记为没有对象。 默认情况下,这类图像会从训练集中移除, 但可以通过设置DATALOADER.FILTER_EMPTY_ANNOTATIONS来包含它们。

  • sem_seg_file_name (str): 语义分割标注文件的完整路径。 该文件应为灰度图像,其像素值为整数标签。

  • pan_seg_file_name (str): 全景分割标注文件的完整路径。 该文件应为RGB图像,其像素值是使用 panopticapi.utils.id2rgb函数编码的整数ID。 这些ID由segments_info定义。 如果某个ID未出现在segments_info中,则该像素被视为未标记, 通常在训练和评估过程中会被忽略。

  • segments_info (list[dict]): 定义全景分割标注中每个ID的含义。 每个字典包含以下键:

    • id (int): 出现在真实标注图像中的整数。

    • category_id (int): 表示类别标签的整数,范围在[0, num_categories-1]之间。

    • iscrowd: 0 (默认) 或 1. 表示该实例是否被标记为COCO的"人群区域"。

注意

PanopticFPN模型并未采用此处定义的全景分割格式,而是结合了实例分割和语义分割的数据格式。关于COCO数据集的说明,请参阅Use Builtin Datasets

Fast R-CNN(使用预计算提案)模型如今很少使用。 要训练Fast R-CNN模型,需要以下额外键值:

  • proposal_boxes (数组): 一个形状为(K, 4)的2D numpy数组,表示该图像的K个预计算候选框。

  • proposal_objectness_logits (数组): 形状为(K,)的numpy数组,对应'proposal_boxes'中提案的目标性对数。

  • proposal_bbox_mode (int): 预计算提案边界框的格式。 它必须是 structures.BoxMode的成员。 默认为 BoxMode.XYXY_ABS

新任务的自定义数据集字典

在数据集函数返回的list[dict]中,字典还可以包含任意自定义数据。 这对于需要标准数据集字典未涵盖额外信息的新任务非常有用。在这种情况下,您需要确保下游代码能正确处理您的数据。 通常这需要为数据加载器编写一个新的mapper(参见Use Custom Dataloaders)。

在设计自定义格式时,请注意所有字典都存储在内存中(有时会被序列化并存在多个副本)。为了节省内存,每个字典应包含少量但足够的信息来描述每个样本,例如文件名和标注。完整样本的加载通常发生在数据加载器中。

对于整个数据集共享的属性,请使用Metadata(见下文)。 为避免额外内存消耗,不要在每个样本中保存此类信息。

数据集的“元数据”

每个数据集都关联着一些元数据,可通过MetadataCatalog.get(dataset_name).some_metadata访问。 元数据是一个键值映射,包含整个数据集共享的信息,通常用于解释数据集中的内容,例如: 类别名称、类别颜色、文件根目录等。 这些信息对于数据增强、评估、可视化、日志记录等非常有用。 元数据的结构取决于相应下游代码的需求。

如果您通过DatasetCatalog.register注册了一个新数据集,您可能还需要通过MetadataCatalog.get(dataset_name).some_key = some_value添加其对应的元数据,以启用任何需要元数据的功能。您可以这样做(以元数据键"thing_classes"为例):

from detectron2.data import MetadataCatalog
MetadataCatalog.get("my_dataset").thing_classes = ["person", "dog"]

以下是detectron2内置功能所使用的元数据键列表。如果您添加的自定义数据集缺少这些元数据,某些功能可能无法使用:

  • thing_classes (list[str]): 被所有实例检测/分割任务使用。 一个包含每个实例/物体类别名称的列表。 如果你加载COCO格式的数据集,它会被load_coco_json函数自动设置。

  • thing_colors (list[tuple(r, g, b)]): 为每个物体类别预定义的颜色值(范围[0, 255])。 用于可视化。如果未提供,将使用随机颜色。

  • stuff_classes (list[str]): 用于语义分割和全景分割任务。每个物品类别的名称列表。

  • stuff_colors (list[tuple(r, g, b)]): 为每个物品类别预定义的颜色值(范围[0, 255])。 用于可视化展示。如果未提供,则使用随机颜色。

  • ignore_label (int): 用于语义分割和全景分割任务。在评估时应忽略带有此类别标签的真实标注中的像素。通常这些是"未标注"的像素。

  • keypoint_names (list[str]): 用于关键点检测。每个关键点名称的列表。

  • keypoint_flip_map (list[tuple[str]]): 用于关键点检测。一个名称对的列表,其中每对代表在图像水平翻转增强时需要同步翻转的两个关键点。

  • keypoint_connection_rules: list[tuple(str, str, (r, g, b))]。每个元组指定一对需要连接的关键点,以及在可视化时用于连接线的颜色(取值范围[0, 255])。

某些数据集评估特有的额外元数据(例如COCO):

  • thing_dataset_id_to_contiguous_id (dict[int->int]): 用于COCO格式的所有实例检测/分割任务。 一个从数据集中实例类别ID到连续ID(范围[0, #class))的映射。 该映射将由函数load_coco_json自动设置。

  • stuff_dataset_id_to_contiguous_id (dict[int->int]): 用于生成语义/全景分割预测json文件时使用。 一个从数据集中语义分割类别ID到[0, num_categories)范围内连续ID的映射。仅用于评估目的。

  • json_file: COCO标注的json文件。用于COCO格式数据集的COCO评估。

  • panoptic_root, panoptic_json: 用于COCO格式的全景分割评估。

  • evaluator_type: 内置主训练脚本用于选择评估器的参数。在新的训练脚本中不要使用它。 你可以直接在主脚本中为你的数据集提供DatasetEvaluator

注意

在识别任务中,我们有时会用"thing"(物体)指代实例级任务,用"stuff"(材质)指代语义分割任务。全景分割任务中会同时用到这两个概念。关于"thing"和"stuff"概念的背景知识,请参阅On Seeing Stuff: The Perception of Materials by Humans and Machines

注册COCO格式数据集

如果你的实例级(检测、分割、关键点)数据集已经是COCO格式的json文件,可以通过以下方式轻松注册数据集及其关联元数据:

from detectron2.data.datasets import register_coco_instances
register_coco_instances("my_dataset", {}, "json_annotation.json", "path/to/image/dir")

如果你的数据集是COCO格式但需要进一步处理,或者包含额外的自定义实例级注释,load_coco_json函数可能会很有用。

为新数据集更新配置

注册数据集后,您可以在cfg.DATASETS.{TRAIN,TEST}中使用数据集的名称(例如上例中的"my_dataset")。

要训练或评估新数据集,您可能还需要修改其他配置:

  • MODEL.ROI_HEADS.NUM_CLASSESMODEL.RETINANET.NUM_CLASSES 分别表示 R-CNN 和 RetinaNet 模型中的物体类别数量。

  • MODEL.ROI_KEYPOINT_HEAD.NUM_KEYPOINTS 设置关键点R-CNN的关键点数量。 您还需要通过TEST.KEYPOINT_OKS_SIGMAS设置关键点OKS用于评估。

  • MODEL.SEM_SEG_HEAD.NUM_CLASSES 设置语义FPN和全景FPN的物体类别数量。

  • TEST.DETECTIONS_PER_IMAGE 控制要检测的最大对象数量。 如果测试图像可能包含超过100个对象,请将其设置为更大的数值。

  • 如果您正在训练Fast R-CNN(使用预计算提案),DATASETS.PROPOSAL_FILES_{TRAIN,TEST}需要与数据集匹配。提案文件的格式记录在此处

新模型 (例如 TensorMask, PointRend) 通常也有自己类似的配置需要修改。

提示

在更改类别数量后,预训练模型中的某些层将变得不兼容,因此无法加载到新模型中。这是预期行为,加载此类预训练模型会产生关于这些层的警告。