使用自定义数据集¶
本文档解释了数据集API (DatasetCatalog, MetadataCatalog) 的工作原理,以及如何使用它们添加自定义数据集。
detectron2中内置支持的数据集列在内置数据集中。 如果您想使用自定义数据集,同时复用detectron2的数据加载器, 您需要:
注册你的数据集(即告诉detectron2如何获取你的数据集)。
可选地,注册元数据为您的数据集。
接下来,我们将详细解释上述两个概念。
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]格式返回数据,其中每个字典需符合以下任一格式:
Detectron2的标准数据集字典,如下所述。这将使其能够与detectron2中的许多其他内置功能配合使用,因此在满足需求时建议使用它。
任何自定义格式。你也可以返回任意自定义格式的字典,例如为新的任务添加额外的键。然后你还需要在下游正确处理它们。更多详情请参阅下文。
标准数据集字典¶
对于标准任务
(实例检测、实例/语义/全景分割、关键点检测),
我们将原始数据集加载到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_CLASSES和MODEL.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) 通常也有自己类似的配置需要修改。
提示
在更改类别数量后,预训练模型中的某些层将变得不兼容,因此无法加载到新模型中。这是预期行为,加载此类预训练模型会产生关于这些层的警告。