[TOC]
# 安裝環境
> 官網: https://mmdetection.readthedocs.io/zh-cn/v3.2.0/get_started.html
> 中文教學: https://blog.csdn.net/qq_16137569/article/details/121316235
> * mmdetection 3.2.0
> * mmengine 0.10.1
> * mmcv 2.1.0
> * pytorch 1.8.0
> * cuda 11.1
# Open-mmlab簡介
主要是目前常見的所有模型集合的工具包,使用者只需要修改幾行參數檔即可開始訓練模型或是測試模型。其中包含許多常見的物件檢測或是其他task的模型,如常見的Yolo系列、RCNN系列等。

目前共有以下的Libraries可使用,每個library下都有包含需多常見的Model可使用。
使用者也可以根據需求去更改模型中特定的module或是其他參數

# mmdetction整體架構

# 支持的Backbone、Neck、Loss
| Backbones | Necks | Loss |
|:-----------------:|:-----------------:|:------------------------:|
| CspDarknet | Bfp | VarifocalLoss |
| Cspnet | ChannelMapper | AeLoss |
| Darknet | CspnetPafpn | BalancedL1Loss |
| DetectorsResnet | CtResnetNeck | CrossEntropyLoss |
| DetectorsResnext| DilatedEncoder | DdqDeterAuxLoss |
| Efficientnet | Dyhead | DiceLoss |
| Hourglass | Fpg | Eqlv2Loss |
| Hrnet | Fpn | FocalLoss |
| MobilenetV2 | FpnCarafe | GaussianFocalLoss |
| PVT | FpnDropblock | GfocalLoss |
| Regnet | Hrfpn | GhmLoss |
| Res2Net | NasFpn | IOULoss |
| Resnest | NasfcosFpn | KdLoss |
| Resnet | Pafpn | L2Loss |
| Resnext | Rfp | MarginLoss |
| SAMBackbone | SsdNeck | MseLoss |
| SsdVgg | Ssh | MultiposCrossEntropyLoss|
| Swin | YoloNeck | PisaLoss |
| TridentResnet | YoloxPafpn | SeesawLoss |
| | | SmoothL1Loss |
| | | TripletLoss |
# 支持的Augmentation
* Resize
* RandomFlip
* RandomCrop
* PhotoMetricDistortion
* MinIoURandomCrop
* Mosaic
* MixUp
* CopyPaste
# 可用模型
1. [MMDetection](https://github.com/open-mmlab/mmdetection)
2. [MMSegmentation](https://github.com/open-mmlab/mmsegmentation)
3. [MMYOLO](https://github.com/open-mmlab/mmyolo)
# mmdetection的優缺點
:::success
優點:
1. 能夠用非常簡單的方式客制化模型,如更改訓練參數、module更改、資料處理流程、優化器更改、訓練流程、Confusion Matrix生成
2. 支援多GPU同時訓練、分散式訓練
3. 多種分析工具可直接使用,如自動檢驗資料集、各種評估指標分析、模型複雜度、模型參數量等
4. 只需要一行指令即可開始training和testing
5. 支援轉換到onnx或是TensorRT
:::
:::danger
缺點:
1. 要添加自訂的model需要follow預定的格式和方法,成本較高
2. 版本間差異大
3. Augmentation支援不多,需要自己手動添加
:::
# 使用教學
## Config命名規則
```
{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 等。
## 參數檔設置
在mmdetection或是其他的library中,都是使用config檔去training或是testing。
下面以Cascade-Mask-Rcnn的config檔來做介紹:
```python=
# 繼承其他的config,可以增加程式的使用率
_base_ = [
'../_base_/models/cascade-mask-rcnn_r50_fpn.py', # model
'../_base_/datasets/coco_instance.py', # 用哪一種資料預處理方式
'../_base_/schedules/schedule_2x.py', # 用哪一種訓練流程
'../_base_/default_runtime.py'
]
```
我們是從**cascade-mask-rcnn_r50_fpn**去進行更改的,所以下面主要是針對想客制化的地方去做更改 (像是class的數量、損失函數等)
```python=
model = dict(
type='CascadeRCNN',
###### Backbone ######
backbone=dict(
type='ResNet',
depth=50
),
###### Neck ######
neck=dict(
type='FPN'
),
####### Head ######
roi_head=dict(
type='CascadeRoIHead',
bbox_head=[
dict(
type='Shared2FCBBoxHead',
num_classes=16, # 類別數量
loss_bbox=dict(type='L1Loss', loss_weight=1.0) # bbox的損失函數
),
dict(
type='Shared2FCBBoxHead',
num_classes=16,
loss_bbox=dict(type='L1Loss', loss_weight=1.0)
),
dict(
type='Shared2FCBBoxHead',
num_classes=16,
loss_bbox=dict(type='L1Loss', loss_weight=1.0)
)
],
mask_head=dict(
type='FCNMaskHead',
num_classes=16
)
)
)
```
DataLoader也可以利用Config檔去做設定
```python=
####### 訓練集的dataloader #######
train_dataloader = dict(
batch_size=2, # 一個GPU的batchsize
num_workers=2,
dataset=dict(
type=dataset_type,
data_root=data_root,
metainfo=dict(classes=classes),
)
)
####### 測試集的dataloader #######
test_dataloader = dict(
batch_size=1,
num_workers=2,
dataset=dict(
type=dataset_type,
data_root=data_root,
metainfo=dict(classes=classes),
),
)
```
## Training
### 單GPU訓練
```bash
python tools/train.py \
${CONFIG_FILE} \
```
### 多GPU訓練
```bash
bash ./tools/dist_train.sh \
${CONFIG_FILE} \
${GPU_NUM} \
```
## Testing
### 1. 只有評估數據
```bash
python tools/test.py \
${CONFIG} \
${WEIGHT}
```
### 2. 預測結果可視化(不含label)
```bash
python demo/image_demo.py \
${IMAGE or DIR} \
${CONFIG} \
--weight ${WEIGHT} \
--out-dir ${OUTPUT DIR} \
--show # 是否要顯示結果
```
如果遇到
```unknown argument {'sam_entities'} for `preprocess`, `forward`, `visualize` and `postprocess```
的錯誤,可以開啟這個```image_demo.py```並註解掉第95行左右的code
```python=
# parser.add_argument(
# '--sam-entities',
# '-c',
# action='store_true',
# help='Whether to customize entity names? '
# 'If so, the input text should be '
# '"cls_name1 . cls_name2 . cls_name3 ." format')
```
### 3. 預測結果可視化(含label)
```bash
python tools/test.py \
${CONFIG} \
${WEIGHT} \
--show-dir ${OUTPUT DIR} \ # 會存在 work_dir/timestamp/show_dir下
--show # 是否要顯示結果
```
### 4. 計算fps
```bash
python tools/analysis_tools/benchmark.py \
${CONFIG} \
--checkpoint ${WEIGHT} \
--task inference # 有三個可以選['inference', 'dataloader', 'dataset']
--dataset-type val # 有三個可以選['train', 'val', 'test']
--log-interval 20 # 預設是50,但是這樣執行會有錯誤
```
## Inference
```python=
from mmdet.apis import DetInferencer
# Initialize the DetInferencer
inferencer = DetInferencer(model='path/to/config.py', weights='path/to/weight.pth')
# Perform inference
inferencer('demo/demo.jpg', show=True)
```

## 建構自己的模型
在建立自己的模型前,一定要先建構Backbone和Head,
## Backbone
在```mmdet/models/backbones/```創建一個SAMBackbone.py
```python=
import torch.nn as nn
from mmdet.registry import MODELS
from mmcv.cnn import ConvModule
@MODELS.register_module()
class SAMBackbone(nn.Module):
def __init__(self):
super().__init__()
def forward(self, inputs):
pass
```
建立好了之後要到```mmdet/models/backbones/__init__.py```底下新增
```python=
from .SAMBackbone import SAMBackbone
```
## Head
在```mmdet/models/seg_heads/```創建一個SAMHead.py
```python=
from torch import Tensor
from mmdet.registry import MODELS
@MODELS.register_module()
class SAMHead(BaseSemanticHead):
def __init__(self,
num_classes: int,
in_channel: int,
img_size: list) -> None:
super().__init__()
self.img_size = img_size
def forward(self, x: Union[Tensor, Tuple[Tensor]]) -> Dict[str, Tensor]:
pass
def loss(self, x: Union[Tensor, Tuple[Tensor]],
batch_data_samples: SampleList) -> Dict[str, Tensor]:
pass
```
建立好了之後要到```mmdet/models/seg_heads/__init__.py```底下新增
```python=
from .SAMHead import SAMHead
```