Detectron2 官方文档详细解读 (上)

Detectron2解读全部文章链接:

  1. Facebook计算机视觉开源框架Detectron2学习笔记 — 从demo到训练自己的模型

  2. Detectron2 “快速开始” Detection Tutorial Colab Notebook 详细解读

  3. Detectron2 官方文档详细解读 (上)

  4. Detectron2 官方文档详细解读(下)

  5. Detectron2 代码解读(1)如何构建模型

  6. Pytorch 基于 Detectron2 从零实现 Unet

Detectron2 官方文档阅读(上)

链接:https://detectron2.readthedocs.io/en/latest/tutorials/getting_started.html

1. 安装

需求:

  • Linux 或 macOS,Python >= 3.6
  • PyTorch >= 1.6 以及对应版本的 torchvision
  • Opencv(可选),demo以及可视化输出需要
  • gcc & g++ >= 5.4,ninja(可选)

具体安装部分略,请查看官方文档

2. 快速开始

这部分简单介绍detectron2的一些内置命令行工具。

使用预训练的模型

(1) 从 model zoo 中选择一个模型和对应的config,比如:mask_rcnn_R_50_FPN_3x.yaml

(2) 我们提供了一个 demo.py 可以快速运行 demo。

cd demo/
python demo.py --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml --input input1.jpg input2.jpg [--other-options] --opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl

这个命令会快速加载训练好的模型并且在选择的图片上进行推理,随后会通过opencv窗口显示。

demo.py的各种命令具体查看 demo.py -h,包括在摄像头上运行,测试视频,或者在cpu上运算等。

在命令行中进行训练和评测

我们提供了两种快速训练的工具:“tools/plain_train_net.py” 以及 “tools/train_net.py”,如果你需要自己的训练工具可以参考这两个文件。

"plain_train_net"相比"train_net"更为简单,但是少了一些自定义的参数。如果要使用 train_net.py 进行训练,你需要首先按照 datasets/README.md 里面的要求摆放好数据集,然后运行:

cd tools/
./train_net.py --num-gpus 8 --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml

config 中默认在 8 张显卡上进行训练,你可以自定义一些参数,比如:

./train_net.py \
  --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
  --num-gpus 1 SOLVER.IMS_PER_BATCH 2 SOLVER.BASE_LR 0.0025

训练好之后,如果需要评测模型,可以使用

./train_net.py \
  --config-file ../configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
  --eval-only MODEL.WEIGHTS /path/to/checkpoint_file

其他功能具体查看 ./train_net.py -h

3. 使用内置的数据集

可以通过访问 DatasetCatalog 来访问具体数据,以及 MetadataCatalog 来访问 metadata(类别等等)。这一部分会细致讲解 DatasetCatalog 和 MetadataCatalog。

Detectron2 支持内置的一些数据集。这些数据集需要被存放在被环境变量 DETECTRON2_DATASET 指定的位置。在这个位置下,Detectron2 会寻找具有支持的格式的数据集:

$DETECTRON2_DATASETS/
	coco/
	lvis/
	cityscapes/
	VOC2007/
	VOC2012/

你可以通过 export DETECTRON2_DATASETS=/path/to/datasets 来修改这个位置,如果没有设定的话,数据集默认存放在 ./datasets 文件夹中。model zoo 中有已经配置好的模型来使用这些数据集。

具体coco/lvis/cityscapes/voc数据集格式请查看 datasets/README.md

4. 扩展 Detectron2

做研究意味着你需要使用新的方法, 这意味着在 Detectron2 的代码中需要提供更多的抽象。一方面,对于研究人员来说,我们需要提供更多抽象来保证新方法可以顺利实施,另一方面,我们需要用户可以简便的使用一些传统的的模型,而不需要在意一些研究人员需要在意的东西。根据这个理念,Detectron2 提供了如下两种模式:

  1. 需要 config 参数设定的函数和类。这些函数和类有一个默认的运行模式,它们会从config中寻找必须的参数。用户只需要修改 config 即可操控这些函数和类,而不需要在意各种传参和调用模式。
  2. 需要传入很直观的参数的函数和类。这些部分是整个 Detectron2 系统的根本,这些需要用户去明白每个参数的具体含义,这一部分就需要费一些精力去研究它们如何拼接成整个系统。但是每个组件可以很灵活地拼接成一个整体。当你的需求不被”传统方法“支持时,你可以参考这些已经定义好的组件。
  3. 有一些函数和类需要 @configurable 修饰器。这些部分同时可以根据 config 运行也可以传参运行。这些目前正在试验中。

举个例子,如果你需要创建一个 Mask R-CNN 模型,你可以通过如下几种方式:

(1) 单纯使用 config:

# 加载对应的 config 文件,随后执行
model = build_model(cfg)

(2) 你也可以混合使用 config 和一些传参:

model = GeneralizedRCNN(
	cfg,
    roi_heads=StandardROIHeads(cfg, batch_size_per_image=666),
    pixel_std=[57.0, 57.0, 57.0]
)

(3) 或者完整使用传参功能:

(太长了。。这里不放了,需要看的话可以去官方文档)

总的来说,如果你仅仅需要使用一些传统模型,去看 Beginner’s Tutorial 文档便可以满足需求,但是如果你需要更多自定义的方面去满足特殊的需求,你可以参考以下部分:

  1. 使用自定义数据集,请参考 (5)
  2. 使用自定义的 Data Loader,参考 Use Custom Data Loaders
  3. 使用自定义的额模型,参考 Use Models,Write Models
  4. 使用自定义的训练模式,参考 training

5. 使用自定义的数据集

这个部分具体介绍了 DatasetCatalog 以及 MetadataCatalog 的运作方式,之后你可以通过它们自定义数据集。

我们准备了内置的数据集,如果你需要使用自己的数据集,但是使用 Detectron2 的 data loader,你需要

  1. 注册你自己的数据集 (告诉Detectron2怎么找到你的数据集)
  2. (可选)你也可以注册 metadata

注册数据集

为了让 Detectron2 知道如何使用你的数据集,你需要自己创建一个函数,并且返回你数据集中的每一个物体。随后你需要把这个函数交给 Detectron2。

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

from detectron2.data import DatasetCatalog
DatasetCatalog.register("my_dataset", my_dataset_function)
# 随后,如果你需要访问你的数据集
data: List[Dict] = DatasetCatalog.get("my_dataset")

my_dataset_function() 函数返回了你的数据集(比如叫my_dataset)中的数据。这个函数无论被调用多少次,必须返回同一批数据。这个注册在进程结束之前一直有效。

这个函数在经过任意处理后必须以 list[dict] 格式返回数据,每个 dict 必须具有如下格式:

  1. Detectron2 的标准数据字典(下面会介绍)。使用这种格式的话,你的数据集将会支持很多 Detectron2 内置的操作,如果没有其他需求推荐使用这种格式。
  2. 任何自定义的格式,比如对于新的任务,你要求数据具有额外的信息。但是在随后的运行中你需要逐一处理可能出现的问题。

Detectron2 的标准数据字典格式

对于一些传统任务 (目标检测,实例/全景/语义分割,关键点检测),你可以把你的数据集加载成 list[dist] 的形式,和 COCO 格式非常像。

每个字典含有一张图片的信息,这个字典需要有如下内容,需要的内容因任务而异:

任务包含的信息
通用file_name, height, width, image_id
目标检测/实例分割annotations
语义分割sem_seg_file_name
全景分割pan_seg_file_name, segments_info
  • file_name: 图片的完整路径
  • height, width (int): 图片的宽和高
  • image_id (int or str): 一个独特的id对应每一张图片,Evaluators需要通过image_id来确定是哪张图。
  • annotations (list[dict]): 在目标检测/分割/或者关键点检测任务中需要。每个字典对应了图片中的一个物体,这个子字典需要有这些内容:
    • bbox (list[float], 必须):一个有4个浮点数的list
    • bbox_mode (int, 必须):整数,代表了每个bounding box的数据存储模式(xyxy 或者 xywh),它必须是 structure.BoxMode 中的成员,现在支持 BoxMode. XYXY_ABS, BoxMode. XYWH_ABS
    • category_id (int, 必须):整数,这个 int 在 [0,类别数 - 1] 的范围内,代表了物体属于哪类。
    • segmentation (list[list[float]] or dict):存储了分割需要的mask
      • 如果是 list[list[float]],那么它存储了一个多边形的 list,每个代表物体的一个联通区域,每个多边形的格式是 [x1, y1, …, xn, yn] (n >= 3). 这里 x 和 y 是像素的绝对坐标。
      • 如果是 dict,那么它对应了逐像素分割的类型,格式为 COCO 的 压缩RLE格式。这个字典需要有 “size” 和 “counts”。
    • keypoints:(list[float]),格式是 [x1, y1, v1, …, xn, yn, vn]. v[i] 是这个关键点的 visibility,n 等于关键点的类别数量。x 和 y 是绝对坐标。
    • iscrowd (0 (default) or 1):这个物体是不是 “Crowd region”,参见 COCO,如果你不知道这个是什么,不要加入这个。
  • sem_seg_file_name (str):语义分割 ground truth 文件的绝对路径,应该是一个单通道图,每个像素对应着不同类。
  • pan_seg_fil_name (str):全景分割 ground truth 文件的绝对路径,应该是一个三通道图,每个像素值的ids根据 panopticapi.utils.id2rgb 函数编码。这些ids在 segments_info 中定义。
  • segments_info (list[dict]):定义了每个全景分割的像素ids的定义,每个字典必须包含一下内容:
    • id (int):每个在gt中出现的id都要有
    • category_id (int):在范围 [0, 类别数 - 1],代表类别。
    • iscrowd (0 (default) or 1):同上。

Fast R-CNN 现在很少用了,这个需要首先获得由 Selective Search(选择性搜索)生成的先验框,如果你需要训练 Fast R-CNN,那么你还需要在字典中添加一些额外信息(具体看官方文档)。

对于新任务设计的自定义数据字典

在你的数据集函数返回的 list[dict] 中,dict可以是任何你自己定义的格式,但是你需要确保下游程序可以正确处理你的格式,这种情况你还需要额外写一个mapper,把你的格式和下游接口对应上,具体看官方文档(Use custom data loaders)。

对于一些每个数据都有的信息,使用 Metadata,为了节省内存,不要在每张图片内存储 Metadata。

数据集的 Metadata

每一个数据集都对应一个 metadata,这个 metadata 可以通过 MetadataCatalog.get(dataset_name).some_metadata 访问。Metadata 是一个包含了整个数据集的通用信息的 mapping,比如,类别名,类别的颜色,数据集的路径等等。Metadata 的结构和下游程序的需要有关。

如果你需要通过 DatasetCatalog.register 注册一个新的数据集,你可以同时使用:MetadataCatalog.get(dataset_name).some_key = some_value 把 Metadata 信息同时加入程序中。要使用任何需要 Metadata 的功能的话,你可以这样使用(比如你需要使用所有类别名):

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

如下是一些内置功能使用到的 metadata内容:

  • thing_classes (list[str]):在几乎所有任务中使用,你如果注册一个 COCO 格式的数据集,这部分会被 load_coco_json 函数自动添加。
  • thing_colors (list[tuple(r,g,b)]):对每个类别使用不同的颜色,如果未定义则随机。
  • stuff_classes (list[str]):语义分割和全景分割中使用。每个类别的名字。
  • stuff_colors (list[tuple(r,g,v)]):基本同上。
  • ignore_label (int):语义分割和全景分割中使用,被标记为这个类型的像素会被忽略。
  • keypoint_names (list[str]):关键点检测中的类别名。
  • keypoint_flip_map (list[tuple[str]]):关键点检测中使用,一对名称,每一对需要被反转如果图片反转。
  • keypoint_connection_rules (list[tuple(str,str,(r,g,b))]):略。。

还有一些额外的 metadata 是针对某个特定数据集的:

略。。

注册一个 COCO 格式的数据集

COCO 格式的数据集可以通过如下方式注册,这种方法也会自动注册 metadata。

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

如果你的数据集在 COCO 格式,但是需要更多处理,你可以查看 load_coco_json 的函数。

使用新数据集

一旦你注册完数据集,你就可以在 config 中使用你注册的名称了,比如 cfg.DATASETS.{TRAIN,TEST},MODEL.ROI_HEADS.NUM_CLASSES, … 等等。

6. Dataloader

Dataloader 负责把你数据集中的数据提供给模型,它需要接受原本格式的图像,然后把数据处理为模型需要的格式。

现有的 Dataloader 如何工作

Detectron2 已经内置了一个通用的 Data loader,你最好可以了解它的运行原理,以便之后需要自己重写 Data loader 时参考。

Detectron2 提供了两个函数:build_detection_train_loader 和 build_detection_test_loader,这两个函数根据 config 创建 data loader 对象,以下解释这两个函数如何运作:

  1. 首先它会获得注册过的数据集名称,比如 coco_2017_train,然后加载前面提到的 list[dict]。这些 list[dict] 暂时还不能被模型使用(因为此刻图片还没被加载到内存中,还有一些数据加强工作需要进行,等等)。
  2. 每一个 list[dict] 中的字典会被一个 mapper 映射到模型可接受的格式。
    • 用户可以通过调整 build_detection_train_loader 的参数自定义这个 mapper。默认情况下是 DefaultMapper。
    • Mapper的输出格式可以是任意的,只要它可以被模型处理,DefaultMapper 的输出格式在 Use Models 部分可以查看。
    • Mapper 的作用是把读取的 list[dict] 格式数据处理为模型需要的格式(比如,读取图片,进行数据增强,转换为 Tensor,等等)。如果你需要一些自定义的处理,你可以自定义一个 Mapper
  3. Mapper 的输出是 batched (一个 batch 中所有内容被放入一个 list 里)。
  4. 这个 batched data 就是 Mapper 的输出,它会被送进 model.forward()中。

自定义 Dataloader

如果你需要使其它的 mapper,你可以使用 build_detection_train_loader(mapper=…)。比如,你如果需要把所有训练图片缩放成固定大小,你可以:

import detectron2.data.transforms as T
from detectron2.data import DatasetMapper # DefaultMapper
# 自定义一个 DatasetMapper 对象并且让 Dataloader 使用这个 mapper
dataloader = build_detection_train_loader(cfg,
    mapper=DatasetMapper(cfg, is_train=True, augmentations=[
        T.Resize((800, 800))
    ]))

如果 DatasetMapper 创建时传进去的参数不足以满足你的需求,你可以写一个自己的 mapper 函数:

from detectron2.data import detection_utils as utils
# 作为例子,我们创建一个最简单的 mapper
def mapper(dataset_dict):
    dataset_dict = copy.deepcopy(dataset_dict)
    # 可以使用其他方式读图片
    image = utils.read_image(dataset_dict["file_name"], format="BGR")
    # 具体可以查看 Data Augmentation 部分查看更多数据增强
    auginput = T.AugInput(image)
    transform = T.Resize((800, 800))(auginput)
    # 得到输出的图片 Tensor
    image = torhc.from_numpy(auginput.image.transpose(2,0,1))
    # 得到输出的标注
    annos = [
        utils.transform_instance_annotations(annotation,[transform], image.shape[1:])
        for annotation in dataset_dict.pop("annotations")
    ]
    # 返回模型需要的格式
    return {"image":image, "instances": utils.annotations_to_instances(annos, image.shape[1:])} 

# 创建使用这个mapper的dataloader
dataloader = build_detection_train_loader(cfg, mapper=mapper)

如果更过分一点,现有的 Dataloader 也无法满足你的需求了(比如你需要不同的 batch 或者 采样逻辑),你可以重写一个 Dataloader 类。现有的 Dataloader 仅仅是一个迭代器。

使用自定义的 Dataloader

如果你使用 DefaultTrainer,你可以重写 build_train_loader 方法,具体查看 deeplab dataloder。

如果你需要自己的训练模式,你可以轻松使用 data loader。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值