MMDetection 是商湯和港中文大學針對物件偵測推出的一個開源工具箱,它基於 PyTorch 實現了大量的物件偵測算法,目前支援了 11 種 Backbone、56 種物件偵測算法:
- Backbone: VGG、ResNet、Swin 等
- Anchor-based: R-CNN 系列、YOLOv3、SSD、RetinaNet 等
- Anchor-free: FCOS、ATSS、YOLOX 等
- Transformer: DETR 等
這個工具箱把資料集建構、模型搭建、訓練策略等過程都封裝成了模塊,通過模塊調用的方式,能夠以很少的代碼量實現一個新算法,大大提高了代碼複用率。
安裝 MMDetection
推薦使用 MIM 來安裝 MMDetection,:
$ pip install openmim
$ mim install mmdet
$ git clone https://github.com/open-mmlab/mmdetection.git
$ cd mmdetection
MIM 能夠自動的安裝 OpenMMLab 的項目以及對應的依賴包。
驗證
為了驗證是否正確安裝了 MMDetection 和所需的環境,我們可以運行範例的 Python 代碼來初始化偵測器並推理一個影像:
Config 解說
作者為了可以提高代碼複用率,所以 config 支持繼承的操作,通過 _base_ 變量來實現,_base_ 是一個 list 類型變量,裡面存放的是要繼承配置文件的路徑,任何配置文件往上追朔都會繼承以下四種類型的文件:
- 模型(models)
- 資料集 (datasets)
- 訓練策略(schedules)
- 運行時的默認配置 (default_runtime)
配置文件名稱的命名風格如下:
{model}_{backbone}_{neck}_{schedule}_{dataset}
- {model}: model 種類,例如:faster_rcnn, mask_rcnn 等。
- {backbone}:Backbone 種類,例如:r50 (ResNet-50), x101 (ResNeXt-101) 等。
- {neck}:Neck 種類,例如:fpn, pafpn, nasfpn, c4 等。
- {schedule}: 訓練方案,選項是 1x、 2x、 20e 等。1x 和 2x 分別代表 12 epoch 和 24 epoch,20e 在級聯 (Cascaded) 模型中使用,表示 20 epoch。
{dataset}:資料集,例如:coco、 cityscapes、 voc_0712、 wider_face 等。
這邊看一下基本的 faster_rcnn_r50_fpn_1x_coco.py 長怎樣:
_base_ = [
'../_base_/models/faster_rcnn_r50_fpn.py', # models
'../_base_/datasets/coco_detection.py', # datasets
'../_base_/schedules/schedule_1x.py', # schedules
'../_base_/default_runtime.py' # default_runtime
]
我們將 faster_rcnn_r50_fpn_1x_coco.py 裡面的 Models, Datasets, schedules, default_runtime 的配置文件給各位看一下:
Models 配置文件
這邊只寫出文件重點,如果想看詳細配置可以看 faster_rcnn_r50_fpn.py,
model = dict(
type='FasterRCNN', # 偵測模型名稱
backbone=dict(type='ResNet', ...), # Backbone
neck=dict(type='FPN', ...), # Neck
roi_head=dict(
type='StandardRoIHead', # Head
...,
loss_cls=dict(type='CrossEntropyLoss', ...), # 分類損失函數
loss_bbox=dict(type='L1Loss', ...) # 迴歸損失函數
),
train_cfg=dict(
assigner=dict(...), # BBox Assigner
sampler=dict(...), # BBox Sampler
...
),
test_cfg=dict(
nms=dict(...), # NMS後處理
...
)
)
Datasets 配置文件
這邊只寫出文件重點,如果想看詳細配置可以看 coco_detection.py,
dataset_type = 'CocoDataset' # 資料集名稱
data_root = 'data/coco/' # 資料集根目錄
img_norm_cfg = dict(...) # 影像標準化
train_pipeline = [...] # 訓練資料處理Pipeline
test_pipeline = [...] # 測試資料處理Pipeline
data = dict(
samples_per_gpu=2, # 每張GPU上的 batch_size
workers_per_gpu=2, # GPU數量
train=dict( # 訓練集配置
type=dataset_type,
ann_file='...', # 標註資料集
img_prefix='...', # 影像位置前綴
pipeline=train_pipeline), # 訓練資料處理Pipeline
val=dict(...), # 驗證集配置
test=dict(...), # 測試集配置
evaluation = dict(interval=1, metric='bbox')
Schedules 配置文件
這邊只寫出文件重點,如果想看詳細配置可以看 sehedules_1x.py ,
optimizer = dict(type='SGD', ...) # 學習優化器
optimizer_config = dict(...)
lr_config = dict(...) # 學習率策略
runner = dict( # 跑12個epochs
type='EpochBasedRunner',
max_epochs=12)
default_runtime 配置文件
這邊只寫出文件重點,如果想看詳細配置可以看 default_runtime.py,
checkpoint_config = dict(interval=1) # checkpoint 的保存間隔
log_config = dict(
interval=50, # 印出 log 的間隔
hooks=[dict(...)]) # 記錄 log 的記錄器
dist_params = dict(backend='nccl') # 設置分佈式訓練的參數
log_level = 'INFO' # log 的級別
load_from = None # 加載預訓練模型
resume_from = None # 從 checkpoint 恢復訓練
workflow = [('train', 1)] # runner 的工作流程
work_dir = '...' # checkpoint 的保存路徑
如果想改一點配置內容,例如想將原本的 l1loss 改成用 iou loss,那可以先繼承 faster_rcnn_r50_fpn_1x_coco.py 後,再去改動 model 中 loss 的部份,例如 faster_rcnn_r50_fpn_iou_1x_coco.py:
_base_ = './faster_rcnn_r50_fpn_1x_coco.py'
model = dict(
roi_head=dict(
bbox_head=dict(
reg_decoded_bbox=True,
loss_bbox=dict(type='IoULoss', loss_weight=10.0))))
由於多層的繼承和模塊化可能會很難看到 config 的全貌,這邊提供了方便的工具可以檢查配置文件,可以使用 print_config.py 將整個架構印出來,並輸出成 config.txt 檔:
# python tools/misc/print_config.py $CONFIG_FILE_PATH
$ python tools/misc/print_config.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py > config.txt
訓練自己的資料集
官方提供 COCO 格式來訓練,那我們來教如何訓練自己的資料集。
1.標記資料
可以先使用 label 工具來進行 label,推薦使用 labelimg。
- windows 用戶:可以直接去下載編譯好的版本 labelimg
- mac 用戶:使用 pip install labelimg 安裝,再用 labelimg 指令打開程式
使用 Open Dir 讀進自己的資料集,label 完後存成 PascalVOC 格式方便做之後的處理
存成 PascalVOC 格式可以得到對應的 xml 檔案
2.轉換成 COCO 格式
我們需要將標記好的 xml 檔資料轉換成 COCO 的格式,先將標記好的資料放在 mmdetection/datasets 裡,裡面要包含訓練的影像 (jpg) 和對應的標註 (xml),這邊提供我標記好的汽車檔案,接著我們使用 train_val_data_split_coco.py 來生成對應的資料夾結構和切分資料集,這邊設置的比例為 9:1,大家也可自行調整
$ cd mmdetection/datasets
$ wget https://github.com/d246810g2000/mmdetection/blob/main/data.zip?raw=true -O data.zip
$ unzip data.zip
$ wget https://raw.githubusercontent.com/d246810g2000/mmdetection/main/train_val_data_split_coco.py
$ python train_val_data_split_coco.py
執行完後會得到指定的資料夾結構和對應的 instances_train2017.json 和 instances_val2017.json 檔
- annotations 放對應的 instances_train2017.json 和 instances_val2017.json 檔
- train2017 放訓練集影像
- val2017 放驗證集影像
3. 修改配置文件
我們選擇用 faster_rcnn 來示範,首先 _base_ 先繼承 ‘./faster_rcnn_r50_fpn_1x_coco.py’,接著再給裡面類別的部分,這邊只有一個類別,所以我們將 80 改成 1,以下為實際範例:
這邊有提供貼心的工具去可視化你的標註結果,如果有成功畫出來就代表是可以訓練的,我把它放在 vis_gt 這個資料夾中:
$ python tools/misc/browse_dataset.py --output-dir vis_gt configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco_car.py
4. 開始訓練
由於車子的資料太少,訓練效果不易見,這邊我使用貓狗資料集來訓練,公開資料集在此:https://public.roboflow.com/object-detection/oxford-pets/2
單 GPU 訓練:
$ python ./tools/train.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco_pet.py
多 GPU 訓練:
$ ./tools/dist_train.sh configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco_pet.py
訓練歷史分析:
$ python ./tools/analysis_tools/analyze_logs.py plot_curve work_dirs/faster_rcnn_r50_fpn_1x_coco_pet/20220122_170738.log.json --out vis_log --keys bbox_mAP
5. 模型測試
$ python ./tools/test.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco_pet.py work_dirs/faster_rcnn_r50_fpn_1x_coco_pet/latest.pth --eval bbox
6. 模型推理
command line 使用:
$ python demo/image_demo.py demo/cat.jpg configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco_pet.py work_dirs/faster_rcnn_r50_fpn_1x_coco_pet/latest.pth
還有高層 python API 的使用: