一、环境配置
- Python 3.8
- CUDA 11.3
- cudnn 8.4.1.50
- PyTorch 1.12.0
- mmcv -full 1.6.0
- mmdetection 2.25.0
创建虚拟环境
conda create -n mmdet python=3.8 -y
conda activate mmdet
安装PyTorch
conda install pytorch torchvision torchaudio cudatoolkit=11.6 -c pytorch -c conda-forge
安装Pycocotools
pip install pycocotools-windows -i https://pypi.tuna.tsinghua.edu.cn/simple
安装mmcv
pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.12.0/index.html
安装git
conda install git
安装mmdetection
git clone https://github.com/open-mmlab/mmdetection.git
cd mmdetection
pip install -r requirements.txt
pip install -v -e .
测试
# single-gpu testing
python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [--out ${RESULT_FILE}] [--eval ${EVAL_METRICS}] [--show]
# multi-gpu testing
./tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} [--out ${RESULT_FILE}] [--eval ${EVAL_METRICS}]
二、自定义数据集
使用labelme制作自定义数据集
pip install labelme
labelme
划分训练集和验证集
# coding: utf-8
import os
import random
def create_txt(root, year, trainval_percent, train_percent):
xml_file_path = os.path.join(root, 'VOC%s' % year, 'annotations')
txt_save_path = os.path.join(root, 'VOC%s' % year, 'ImageSets/Main')
total_xml = os.listdir(xml_file_path)
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)
ftrainval = open(os.path.join(txt_save_path, 'trainval.txt'), 'w')
ftest = open(os.path.join(txt_save_path, 'test.txt'), 'w')
ftrain = open(os.path.join(txt_save_path, 'train.txt'), 'w')
fval = open(os.path.join(txt_save_path, 'val.txt'), 'w')
for i in list:
name = total_xml[i][:-4] + '\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
if __name__ == '__main__':
root_dir = '../'
year = '2007'
trainval_percent = 1
train_percent = 0.95
create_txt(root=root_dir, year='2007', trainval_percent=1, train_percent=0.95)
JSON文件批量转换
python ./labelme2xx.py {标注文件目录} {数据集保存目录} --labels labels.txt
# Convert to VOC-format Dataset
python ./labelme2voc.py data_annotated data_dataset_voc --labels labels.txt
# - data_dataset_voc/JPEGImages
# - data_dataset_voc/SegmentationClass
# - data_dataset_voc/SegmentationClassVisualization
# - data_dataset_voc/SegmentationObject
# - data_dataset_voc/SegmentationObjectVisualization
# Convert to coco-format Dataset
python ./labelme2coco.py data_annotated data_dataset_coco --labels labels.txt
# It generates:
# - data_dataset_coco/JPEGImages
# - data_dataset_coco/annotations.json
mmdetection
├── mmdet
├── tools
├── configs
├── data
│ ├── coco
│ │ ├── annotations
│ │ │ ├──instances_train.json
│ │ │ ├──instances_val.json
│ │ │ ├──instances_test.json
│ │ ├── train2017
│ │ ├── val2017
│ │ ├── test2017
│ ├── VOCdevkit
│ │ ├── VOC2017
│ │ │ ├──Annotations
│ │ │ ├──JPEGImages
│ │ │ ├──ImageSets
│ │ │ │ ├──Main
│ │ │ │ │ ├──train.txt
│ │ │ │ │ ├──valid.txt
│ │ ├── VOC2012
三、模型训练
项目构成
├── checkpoints
├── configs
├── demo
├── docker
├── docs
├── mmdet
├── mmdet.egg-info
├── requirements
├── resources
├── src
├── setup.py
├── tests
├── tools
├── work_dirs
├── README.md
└── requirements.txt
修改模型配置文件
自定义数据集类别mmdet/datasets/coco.py
将CLASSES对应的元组内容修改为自己数据集的类别,注意要和annotations文件夹中的类别顺序一致,两类之间的 “,”不可忘。
class CocoDataset(CustomDataset):
CLASSES = (
'A', 'B'
)
PALETTE = [
(220, 20, 60), (119, 11, 32)
]
自定义数据集的类别名称mmdet/core/evaluation/class_name.py
将其改为自定义数据集的类别名称,注意要和annotations文件夹中的类别顺序一致(影响测试时显示的名称)
class coco_classes():
return [
'A', 'B'
]
自定义数据集的类别数configs/_base_/models/faster_rcnn_r50_fpn.py
num_classes=80, # 实际类别数,2.0 版本无需+1
自定义数据集路径,名称,批大小configs/_base_/datasets/coco_instance.py
data = dict(
samples_per_gpu=2,
workers_per_gpu=2,
train=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_train2017.json',
img_prefix=data_root + 'train2017/',
pipeline=train_pipeline),
val=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline),
test=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline))
自定义学习策略configs/_base_/schedules/schedules_1x.py
lr = (gpu_num * samples_per_gpu) / 16 * 0.02
自定义日志信息configs/_base_/default_runtime.py
模型训练
python tools/train.py <CONFIG_FILE> --gpus <GPU_NUM> --work_dir <WORK_DIR>
CUDA_VISIBLE_DEVICES: 指定本次训练可以使用的GPU设备编号
CONFIG_FILE: 配置文件
GPU_NUM: 训练使用的GPU数量
WORK_DIR: 日志和模型文件存放目录
python tools/train.py configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py
模型评估
# single-gpu testing
python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [--out ${RESULT_FILE}] [--eval ${EVAL_METRICS}] [--show]
python tools/test.py configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py work_dirs/mask_rcnn_r50_fpn_1x_coco/latest.pth --eval bbox --show
出现问题
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.000
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.000
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.000
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.000
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.000
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.000
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.000
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.000
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = -1.000
解决办法:调整学习率(通常是减小)