一、安装 Detectron2
初次接触 Detectron2 的话,可能安装会遇到些坑,大家可以按下面的方式逐步安装,基本不会有什么问题。如果用到别的数据库的话,安装对应的api就可以。
# 使用 conda 创建虚拟环境
conda create -n detectron2 python=3.7
# 激活虚拟环境
conda activate detectron2
# 安装pytorch,注意对应的 cuda
conda install pytorch=1.6 torchvision cudatoolkit=10.2 -c pytorch
conda install opencv-python
pip install cython
# 安装cocopai
https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI/
make
python setup.py install --user
cd ../../
# 安装 DCNv2
git clone https://github.com/CharlesShang/DCNv2.git
cd DCNv2
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
./make.sh
# 克隆detectron2包,并安装
git clone https://github.com/facebookresearch/detectron2.git
python setup.py build develop
pip install -e .
二、软连接 coco 数据集
克隆下来的 detectron2 是下面的结构,为了不混淆,我自己命名成了 detectron2_test:
如果不想在 coco.py 中修改文件路径的话,可以把现有的 coco 数据集软连接到 detectron2_test/detectron2/data/datasets/
中即可:
$ cd detectron2_test/detectron2/data/datasets/
$ ln -s xxx/coco .
三、训练
$ pwd
detectron2_test
$ ./tools/train_net.py --config-file configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml
四、数据集相关参数
数据集的相关参数是模型训练的很重要的一部分,如果需要训练自己的数据集的话,需要在下面的三个文件中,修改成自己数据集中对应的类别个数、类别名称和 json 路径等。
# 1
detectron2_test/detectron2/data/datasets/coco.py
# 2
detectron2_test/detectron2/data/datasets/builtin.py
# 3
detectron2_test/detectron2/data/datasets/builtin_meta.py
coco 数据集介绍:
coco 数据集每个类别数量:
五、输出结果路径
detectron2_test/configs/defaults.py
六、COCO 数据集简介
COCO 数据集下载:
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
wget http://images.cocodataset.org/zips/test2017.zip
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip
coco 数据集的结构如下,共由5个关键字段构成,每个字段的内容如下面代码打印所示:
- info
- licenses
- images
- annotations
- categories
file = io.open('instances_val2017.json', 'r', encoding='utf-8')
content = json.load(file)
print(content.keys())
>>>
dict_keys(['info', 'licenses', 'images', 'annotations', 'categories'])
print(content['info'])
>>>
{'description': 'COCO 2017 Dataset', 'url': 'http://cocodataset.org', 'version': '1.0', 'year': 2017, 'contributor': 'COCO Consortium', 'date_created': '2017/09/01'}
print(content['licenses'])
>>>[
{'url': 'http://creativecommons.org/licenses/by-nc-sa/2.0/', 'id': 1, 'name': 'Attribution-NonCommercial-ShareAlike License'},
{'url': 'http://creativecommons.org/licenses/by-nc/2.0/', 'id': 2, 'name': 'Attribution-NonCommercial License'},
{'url': 'http://creativecommons.org/licenses/by-nc-nd/2.0/', 'id': 3, 'name': 'Attribution-NonCommercial-NoDerivs License'},
{'url': 'http://creativecommons.org/licenses/by/2.0/', 'id': 4, 'name': 'Attribution License'},
{'url': 'http://creativecommons.org/licenses/by-sa/2.0/', 'id': 5, 'name': 'Attribution-ShareAlike License'},
{'url': 'http://creativecommons.org/licenses/by-nd/2.0/', 'id': 6, 'name': 'Attribution-NoDerivs License'},
{'url': 'http://flickr.com/commons/usage/', 'id': 7, 'name': 'No known copyright restrictions'},
{'url': 'http://www.usa.gov/copyright.shtml', 'id': 8, 'name': 'United States Government Work'}]
print(content['images'])
>>>[
{'license': 1, 'file_name': '000000548246.jpg', 'coco_url': 'http://images.cocodataset.org/val2017/000000548246.jpg', 'height': 428, 'width': 640, 'date_captured': '2013-11-23 03:52:52', 'flickr_url': 'http://farm4.staticflickr.com/3115/2905881071_5b16058d7b_z.jpg', 'id': 548246}, ...]
print(content['annotations'][0]) # type = list, len(content['annotations'])=36781
>>>{
'segmentation': [[510.66, 423.01, 511.72, 420.03, 510.45, 416.0, 510.34, 413.02, 510.77, 410.26, 510.77, 407.5, 510.34, 405.16, 511.51, 402.83, 511.41, 400.49, 510.24, 398.16, 509.39, 397.31, 504.61, 399.22, 502.17, 399.64, 500.89, 401.66, 500.47, 402.08, 499.09, 401.87, 495.79, 401.98, 490.59, 401.77, 488.79, 401.77, 485.39, 398.58, 483.9, 397.31, 481.56, 396.35, 478.48, 395.93, 476.68, 396.03, 475.4, 396.77, 473.92, 398.79, 473.28, 399.96, 473.49, 401.87, 474.56, 403.47, 473.07, 405.59, 473.39, 407.71, 476.68, 409.41, 479.23, 409.73, 481.56, 410.69, 480.4, 411.85, 481.35, 414.93, 479.86, 418.65, 477.32, 420.03, 476.04, 422.58, 479.02, 422.58, 480.29, 423.01, 483.79, 419.93, 486.66, 416.21, 490.06, 415.57, 492.18, 416.85, 491.65, 420.24, 492.82, 422.9, 493.56, 424.39, 496.43, 424.6, 498.02, 423.01, 498.13, 421.31, 497.07, 420.03, 497.07, 415.15, 496.33, 414.51, 501.1, 411.96, 502.06, 411.32, 503.02, 415.04, 503.33, 418.12, 501.1, 420.24, 498.98, 421.63, 500.47, 424.39, 505.03, 423.32, 506.2, 421.31, 507.69, 419.5, 506.31, 423.32, 510.03, 423.01, 510.45, 423.01]],
'area': 702.1057499999998,
'iscrowd': 0,
'image_id': 289343,
'bbox': [473.07, 395.93, 38.65, 28.67],
'category_id': 18,
'id': 1768}
print(content['categories']) # len(content['categories']=80)
>>>[
{'supercategory': 'person', 'id': 1, 'name': 'person'},
{'supercategory': 'vehicle', 'id': 2, 'name': 'bicycle'},
{'supercategory': 'vehicle', 'id': 3, 'name': 'car'},
{'supercategory': 'vehicle', 'id': 4, 'name': 'motorcycle'},
{'supercategory': 'vehicle', 'id': 5, 'name': 'airplane'},
{'supercategory': 'vehicle', 'id': 6, 'name': 'bus'},
{'supercategory': 'vehicle', 'id': 7, 'name': 'train'},
{'supercategory': 'vehicle', 'id': 8, 'name': 'truck'},
{'supercategory': 'vehicle', 'id': 9, 'name': 'boat'},
{'supercategory': 'outdoor', 'id': 10, 'name': 'traffic light'},
{'supercategory': 'outdoor', 'id': 11, 'name': 'fire hydrant'},
{'supercategory': 'outdoor', 'id': 13, 'name': 'stop sign'},
{'supercategory': 'outdoor', 'id': 14, 'name': 'parking meter'},
{'supercategory': 'outdoor', 'id': 15, 'name': 'bench'},
{'supercategory': 'animal', 'id': 16, 'name': 'bird'},
{'supercategory': 'animal', 'id': 17, 'name': 'cat'},
{'supercategory': 'animal', 'id': 18, 'name': 'dog'},
{'supercategory': 'animal', 'id': 19, 'name': 'horse'},
{'supercategory': 'animal', 'id': 20, 'name': 'sheep'},
{'supercategory': 'animal', 'id': 21, 'name': 'cow'},
{'supercategory': 'animal', 'id': 22, 'name': 'elephant'},
{'supercategory': 'animal', 'id': 23, 'name': 'bear'},
{'supercategory': 'animal', 'id': 24, 'name': 'zebra'},
{'supercategory': 'animal', 'id': 25, 'name': 'giraffe'},
{'supercategory': 'accessory', 'id': 27, 'name': 'backpack'},
{'supercategory': 'accessory', 'id': 28, 'name': 'umbrella'},
{'supercategory': 'accessory', 'id': 31, 'name': 'handbag'},
{'supercategory': 'accessory', 'id': 32, 'name': 'tie'},
{'supercategory': 'accessory', 'id': 33, 'name': 'suitcase'},
{'supercategory': 'sports', 'id': 34, 'name': 'frisbee'},
{'supercategory': 'sports', 'id': 35, 'name': 'skis'},
{'supercategory': 'sports', 'id': 36, 'name': 'snowboard'},
{'supercategory': 'sports', 'id': 37, 'name': 'sports ball'},
{'supercategory': 'sports', 'id': 38, 'name': 'kite'},
{'supercategory': 'sports', 'id': 39, 'name': 'baseball bat'},
{'supercategory': 'sports', 'id': 40, 'name': 'baseball glove'},
{'supercategory': 'sports', 'id': 41, 'name': 'skateboard'},
{'supercategory': 'sports', 'id': 42, 'name': 'surfboard'},
{'supercategory': 'sports', 'id': 43, 'name': 'tennis racket'},
{'supercategory': 'kitchen', 'id': 44, 'name': 'bottle'},
{'supercategory': 'kitchen', 'id': 46, 'name': 'wine glass'},
{'supercategory': 'kitchen', 'id': 47, 'name': 'cup'},
{'supercategory': 'kitchen', 'id': 48, 'name': 'fork'},
{'supercategory': 'kitchen', 'id': 49, 'name': 'knife'},
{'supercategory': 'kitchen', 'id': 50, 'name': 'spoon'},
{'supercategory': 'kitchen', 'id': 51, 'name': 'bowl'},
{'supercategory': 'food', 'id': 52, 'name': 'banana'},
{'supercategory': 'food', 'id': 53, 'name': 'apple'},
{'supercategory': 'food', 'id': 54, 'name': 'sandwich'},
{'supercategory': 'food', 'id': 55, 'name': 'orange'},
{'supercategory': 'food', 'id': 56, 'name': 'broccoli'},
{'supercategory': 'food', 'id': 57, 'name': 'carrot'},
{'supercategory': 'food', 'id': 58, 'name': 'hot dog'},
{'supercategory': 'food', 'id': 59, 'name': 'pizza'},
{'supercategory': 'food', 'id': 60, 'name': 'donut'},
{'supercategory': 'food', 'id': 61, 'name': 'cake'},
{'supercategory': 'furniture', 'id': 62, 'name': 'chair'},
{'supercategory': 'furniture', 'id': 63, 'name': 'couch'},
{'supercategory': 'furniture', 'id': 64, 'name': 'potted plant'},
{'supercategory': 'furniture', 'id': 65, 'name': 'bed'},
{'supercategory': 'furniture', 'id': 67, 'name': 'dining table'},
{'supercategory': 'furniture', 'id': 70, 'name': 'toilet'},
{'supercategory': 'electronic', 'id': 72, 'name': 'tv'},
{'supercategory': 'electronic', 'id': 73, 'name': 'laptop'},
{'supercategory': 'electronic', 'id': 74, 'name': 'mouse'},
{'supercategory': 'electronic', 'id': 75, 'name': 'remote'},
{'supercategory': 'electronic', 'id': 76, 'name': 'keyboard'},
{'supercategory': 'electronic', 'id': 77, 'name': 'cell phone'},
{'supercategory': 'appliance', 'id': 78, 'name': 'microwave'},
{'supercategory': 'appliance', 'id': 79, 'name': 'oven'},
{'supercategory': 'appliance', 'id': 80, 'name': 'toaster'},
{'supercategory': 'appliance', 'id': 81, 'name': 'sink'},
{'supercategory': 'appliance', 'id': 82, 'name': 'refrigerator'},
{'supercategory': 'indoor', 'id': 84, 'name': 'book'},
{'supercategory': 'indoor', 'id': 85, 'name': 'clock'},
{'supercategory': 'indoor', 'id': 86, 'name': 'vase'},
{'supercategory': 'indoor', 'id': 87, 'name': 'scissors'},
{'supercategory': 'indoor', 'id': 88, 'name': 'teddy bear'},
{'supercategory': 'indoor', 'id': 89, 'name': 'hair drier'},
{'supercategory': 'indoor', 'id': 90, 'name': 'toothbrush'}]
七、模型相关参数
MODEL:
META_ARCHITECTURE: "GeneralizedRCNN"
BACKBONE:
NAME: "build_resnet_fpn_backbone"
RESNETS:
OUT_FEATURES: ["res2", "res3", "res4", "res5"]
FPN:
IN_FEATURES: ["res2", "res3", "res4", "res5"]
ANCHOR_GENERATOR:
SIZES: [[32], [64], [128], [256], [512]] # One size for each in feature map
ASPECT_RATIOS: [[0.5, 1.0, 2.0]] # Three aspect ratios (same for all in feature maps)
RPN:
IN_FEATURES: ["p2", "p3", "p4", "p5", "p6"]
PRE_NMS_TOPK_TRAIN: 2000 # Per FPN level
PRE_NMS_TOPK_TEST: 1000 # Per FPN level
# Detectron1 uses 2000 proposals per-batch,
# (See "modeling/rpn/rpn_outputs.py" for details of this legacy issue)
# which is approximately 1000 proposals per-image since the default batch size for FPN is 2.
POST_NMS_TOPK_TRAIN: 1000
POST_NMS_TOPK_TEST: 1000
ROI_HEADS:
NAME: "StandardROIHeads"
IN_FEATURES: ["p2", "p3", "p4", "p5"]
ROI_BOX_HEAD:
NAME: "FastRCNNConvFCHead"
NUM_FC: 2
POOLER_RESOLUTION: 7
ROI_MASK_HEAD:
NAME: "MaskRCNNConvUpsampleHead"
NUM_CONV: 4
POOLER_RESOLUTION: 14
DATASETS:
TRAIN: ("coco_2017_train",)
TEST: ("coco_2017_val",)
SOLVER:
IMS_PER_BATCH: 16
BASE_LR: 0.02
STEPS: (60000, 80000)
MAX_ITER: 90000
INPUT:
MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800)
VERSION: 2
八、可视化结果
demo/demo.py
python demo/demo.py --config-file configs/COCO-Detection/faster_rcnn_R_50_FPN_1x.yaml --input /mnt/nfs-storage/train_data/coco/val2017/*.jpg --output coco_val_test --opt MODEL.WEIGHTS output/model_0049999.pth
如果类别不是coco的80类的话,需要修改下面两个地方为自己的类别数量:
detectron2_test/detectron2/configs/default.py