概述
Detectron2解读全部文章链接:
-
Facebook计算机视觉开源框架Detectron2学习笔记 — 从demo到训练自己的模型
-
Detectron2 “快速开始” Detection Tutorial Colab Notebook 详细解读
-
Detectron2 官方文档详细解读 (上)
-
Detectron2 官方文档详细解读(下)
-
Detectron2 代码解读(1)如何构建模型
-
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 提供了如下两种模式:
- 需要 config 参数设定的函数和类。这些函数和类有一个默认的运行模式,它们会从config中寻找必须的参数。用户只需要修改 config 即可操控这些函数和类,而不需要在意各种传参和调用模式。
- 需要传入很直观的参数的函数和类。这些部分是整个 Detectron2 系统的根本,这些需要用户去明白每个参数的具体含义,这一部分就需要费一些精力去研究它们如何拼接成整个系统。但是每个组件可以很灵活地拼接成一个整体。当你的需求不被”传统方法“支持时,你可以参考这些已经定义好的组件。
- 有一些函数和类需要 @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 文档便可以满足需求,但是如果你需要更多自定义的方面去满足特殊的需求,你可以参考以下部分:
- 使用自定义数据集,请参考 (5)
- 使用自定义的 Data Loader,参考 Use Custom Data Loaders
- 使用自定义的额模型,参考 Use Models,Write Models
- 使用自定义的训练模式,参考 training
5. 使用自定义的数据集
这个部分具体介绍了 DatasetCatalog 以及 MetadataCatalog 的运作方式,之后你可以通过它们自定义数据集。
我们准备了内置的数据集,如果你需要使用自己的数据集,但是使用 Detectron2 的 data loader,你需要
- 注册你自己的数据集 (告诉Detectron2怎么找到你的数据集)
- (可选)你也可以注册 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 必须具有如下格式:
- Detectron2 的标准数据字典(下面会介绍)。使用这种格式的话,你的数据集将会支持很多 Detectron2 内置的操作,如果没有其他需求推荐使用这种格式。
- 任何自定义的格式,比如对于新的任务,你要求数据具有额外的信息。但是在随后的运行中你需要逐一处理可能出现的问题。
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 对象,以下解释这两个函数如何运作:
- 首先它会获得注册过的数据集名称,比如 coco_2017_train,然后加载前面提到的 list[dict]。这些 list[dict] 暂时还不能被模型使用(因为此刻图片还没被加载到内存中,还有一些数据加强工作需要进行,等等)。
- 每一个 list[dict] 中的字典会被一个 mapper 映射到模型可接受的格式。
- 用户可以通过调整 build_detection_train_loader 的参数自定义这个 mapper。默认情况下是 DefaultMapper。
- Mapper的输出格式可以是任意的,只要它可以被模型处理,DefaultMapper 的输出格式在 Use Models 部分可以查看。
- Mapper 的作用是把读取的 list[dict] 格式数据处理为模型需要的格式(比如,读取图片,进行数据增强,转换为 Tensor,等等)。如果你需要一些自定义的处理,你可以自定义一个 Mapper
- Mapper 的输出是 batched (一个 batch 中所有内容被放入一个 list 里)。
- 这个 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。
最后
以上就是发嗲秋天为你收集整理的Detectron2 官方文档详细解读 (上)Detectron2 官方文档阅读(上)的全部内容,希望文章能够帮你解决Detectron2 官方文档详细解读 (上)Detectron2 官方文档阅读(上)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复