最新版本的mmdetection2.0 (v2.0.0版本)环境搭建、训练自己的数据集、测试以及常见错误集合

欢迎大家关注笔者,你的关注是我持续更博的最大动力


原创文章,转载告知,盗版必究



本人环境声明:

  • 系统环境Ubuntu18.04.1
  • cuda版本10.2.89
  • cudnn版本7.6.5
  • torch版本1.5.0
  • torchvision版本0.6.0
  • mmcv版本0.5.5
  • 项目代码mmdetection v2.0.0官网是在20200506正式发布的v2.0.0版本

  • 20200805 ——最新的mmdetection版本已经更新到:v2.3.0
  • mmdetection2.3.0的环境安装参考:这篇博客

环境搭建和项目代码下载时间:2020年5月26号,当前最新代码,版本是:v2.0.0
在这里插入图片描述

注意:
这个版本的代码文件结构上改动比较大,还有一些细节性的东西,我会在文中详细阐述!

mmdetection v2.0.0版本的主要重构和修改,如下(详细参考):
1、速度更快:针对常见模型优化了训练和推理速度,将训练速度提高了30%,将推理速度提高了25%。更多模型细节请参考:model_zoo

2、性能更高:更改了一些默认的超参数而没有额外的费用,这导致大多数模型的性能得到提高。有关详细信息,请参阅兼容性

3、更多文档和教程:添加了许多文档和教程来帮助用户更轻松地入门,在这里阅读。

4、支持PyTorch 1.5:不再支持1.1和1.2,切换到一些新的API。

5、更好的配置系统:支持继承以减少配置的冗余。

6、更好的模块化设计:为了实现简单和灵活的目标,我们简化了封装过程,同时添加了更多其他可配置模块,例如BBoxCoder,IoUCalculator,OptimizerConstructor,RoIHead。标头中还包含目标计算,并且调用层次结构更简单。

7、支持新的方法FSAFPAFPN(部分PAFPN)。

MMDetection 1.x的训练方式与2.0版本不完全兼容,有关详细信息以及如何迁移到新版本,请参阅兼容性文档。


数据声明:
这里我以:VOC2007数据集作为训练数据,主要是为了方便快捷的做一个POC的验证,同时节省数据标注的时间,文中会详细阐述如何自定义自己的数据集,和修改修改和数据集相关的位置。

VOC2007数据下载:


1 mmdetection环境搭建

查看Cuda和cudnn的版本,参考
在Linux下查看cuda的版本:

cat /usr/local/cuda/version.txt

示例:

(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$ cat /usr/local/cuda/version.txt
CUDA Version 10.2.89
(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$

在Linux下查看cudnn的版本:

cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

示例:

(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$ cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
#define CUDNN_MAJOR 7
#define CUDNN_MINOR 6
#define CUDNN_PATCHLEVEL 5
--
#define CUDNN_VERSION (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL)

#include "driver_types.h"
(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$

如上,我的cudnn版本是:7.6.5

1.1 搭建虚拟环境

1、创建虚拟环境:

conda create -n mmdetection python=3.7

2、激活虚拟环境

conda acitvate mmdetectionsource activate mmdetection

退出虚拟环境:

conda deactivatesource deactivate

注意:

在安装下面的环境的时候,一定要确保自己在虚拟环境中,不要退出来

1.2 安装必要的库包

安装torch、torchvision、mmcv库包

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch==1.5.0 torchvision==0.6.0 mmcv==0.5.5

我安装的版本:

torch==1.5.0
torchvision==0.6.0
mmcv==0.5.5
Cython==0.29.16

注意:
如果下载经常中断,建议先把torch的.whl库包文件下载下来,然后使用pip intall torch_xxxx.whl进行安装

torch1.5.0下载地址:点我-》带你去https://pypi.tuna.tsinghua.edu.cn/packages/76/58/668ffb25215b3f8231a550a227be7f905f514859c70a65ca59d28f9b7f60/torch-1.5.0-cp37-cp37m-manylinux1_x86_64.whl

1.3 下载mmdetection

1、克隆mmdetection到本地

git clone https://github.com/open-mmlab/mmdetection.git

如果git clone下载的速度太慢,可以使用github的镜像进行下载,如下:

或 :git clone https://github.com.cnpmjs.org/open-mmlab/mmdetection.git

2、进入到项目目录中

cd mmdetection

1.4 安装mmdetection依赖和编译mmdetection

1.4.1 安装mmdetection依赖

  • 安装依赖的库,同时会检查一些库包的版本是否符合

pip install -r requirements/build.txt

mmdetection/requirements.txt定义的内容:

-r requirements/build.txt
-r requirements/optional.txt
-r requirements/runtime.txt
-r requirements/tests.txt

可看到,一共有四个安装依赖文件:build.txt, optional.txt, runtime.txt, tests.txt,四个依赖文件中定义的内容如下:

# build.txt
# These must be installed before building mmdetection
numpy
torch>=1.3

####################################################
# optional.txt
albumentations>=0.3.2
cityscapesscripts
imagecorruptions

##################################################
# runtime.txt
matplotlib
mmcv>=0.5.1
numpy
# need older pillow until torchvision is fixed
Pillow<=6.2.2
six
terminaltables
torch>=1.3
torchvision

##################################################
# tests.txt
asynctest
codecov
flake8
isort
# Note: used for kwarray.group_items, this may be ported to mmcv in the future.
kwarray
pytest
pytest-cov
pytest-runner
ubelt
xdoctest >= 0.10.0
yapf

会安装一些没有的依赖库,同时会检查安装依赖库的版本是否符合要求。

1.4.2 安装cocoapi

  • 安装库包cocoapi

pip install "git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI"

如果下载不下来,或者下载的特别慢,同上面一样使用github镜像,如下:

或: pip install "git+https://github.com.cnpmjs.org/cocodataset/cocoapi.git#subdirectory=PythonAPI"

注意:

如果你克隆下载的时候出现:Couldn't find host github.com in the .netrc file; using defaults信息,然后就一直卡着不动了,你就使用github镜像下载

1.4.3 编译mmdetection环境

在运行下面的编译命令之前,现在.bashrc把cuda-10.2添加到环境变量中
1、添加环境变量

vi ~/.bashrc

添加内容如下:

export PATH=/usr/local/cuda-10.2/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

2、让环境变量生效

source ~/.bashrc

3、编译mmdetection

python setup.py developpip install -v -e .

正确编译的结果如下:
在这里插入图片描述

注意1:

如果你在编译的过程如下报错:error: command 'usr/bin/nvcc' failed with exit status 1,记得按照是上面的方式添加把cuda添加到环境变量中即可
>如果你再
注意2:

如果后面你在执行训练或测试命令时,报错:ModuleNotFoundError: No module named 'mmdet',这也是由于没有正确编译导致的错误。

注意3:
最好使用python setup.py develop进行编译,我使用pip install -v -e . 进行编译的时候,报mmcv版本错误!

2 准备自己的数据集

2.1 数据标注

数据标注工具使用LabelImg,然后把所有的数据都标注成VOC数据格式,关于如何LabelImg工具如何使用,请参考我的博客:LabelImg教程详细使用

  • 所有的数据图片放在:JPEGImage文件夹
  • 所有的数据图片的标签文件放在:Annotation文件夹

2.2 数据划分与存放

2.2.1 VOC2007数据集说明

VOC数据集共包含:训练集(5011幅),测试集(4952幅),共计9963幅图,共包含20个种类。

类别训练数量测试集数量
aeroplane238204
bicycle243239
bird330282
boat181172
bottle244212
bus186174
car713721
cat337322
chair445417
cow141127
diningtable200190
dog421418
horse287274
motorbike245222
person20082007
pottedplant245224
sheep9697
sofa229223
train261259
tvmonitor256229

更多VOC数据集介绍,可以参考

2.2.2 VOC2007数据集划分与存放

数据集存放在如下机构中:

  • 所有的数据标签存放在:./data/VOCdevkit/VOC2007/Annotations
  • 所有的图片数据存放在:./data/VOCdevkit/VOC2007/JPEGImage
./data
└── VOCdevkit
    └── VOC2007
        ├── Annotations  # 标注的VOC格式的xml标签文件
        ├── JPEGImages   # 数据集图片
        ├── ImageSet
        │     └── Main
		│ 	     ├── test.txt   # 划分的测试集
		│ 	     ├── train.txt   # 划分的训练集
		│        ├── trainval.txt
		│        └── val.txt   # 划分的验证集
        ├── cal_txt_data_num.py  # 用于统计text.txt、train.txt等数据集的个数
        └── split_dataset.py  # 数据集划分脚本

1、数据集的划分,使用:split_dataset.py脚本

脚本内容:

import os
import random

trainval_percent = 0.8
train_percent = 0.8
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
total_xml = os.listdir(xmlfilepath)

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('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/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()

执行完该脚本后,会在./data/VOCdevkit/VOC2007/ImageSets/Main目录下,生成四个txt文件:

  • train.txt
  • trainval.txt
  • test.txt
  • val.txt

每个txt文件中存储的都是图片的名字(不含图片名字的后缀.jpg),例如:trian.txt中的内容如下:

000005
000007
000016
000019
000020
000021
000024
000046
000052
...

当然你也可以把数据放到其他目录,然后使用软连接的形式连接到./mmdetection/data目录下():

ln -s /HDD/VOCdevkit ./data # 就是把实体目录VOCdevkit做一个链接放到 ./data目录下

2、统计划分数据集数据的个数,使用:cal_txt_data_num.py脚本

脚本内容:

import sys
import os

# 计算txt中有多少个数据,即有多上行

names_txt = os.listdir('./ImageSets/Main')
#print(names_txt)
for name_txt in names_txt:
    with open(os.path.join('./ImageSets/Main', name_txt)) as f:
        lines = f.readlines()
        print(('文件 %s'%name_txt).ljust(35) + ("共有数据:%d个"%len(lines)).ljust(50))

执行结果,如下(显示了我数据集的划分情况):

文件 test.txt                        共有数据:1003个
文件 val.txt                         共有数据:802个
文件 train.txt                       共有数据:3206个
文件 trainval.txt                    共有数据:4008

当然你也可以用coco格式数据集,但是需要把labelImg标注的xml标签转化一下参考1, 参考2 格式转换

至此,数据集的准备工作已经全部完成

3 训练自己的数据集

在数据进行训练前,需要先进行一些配置文件的修改工作

3.1 修改配置文件

3.1.1 修改模型配置文件

修改:./mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py

faster_rcnn_r50_fpn_1x_coco.py脚本内容的原始内容

_base_ = [
    '../_base_/models/faster_rcnn_r50_fpn.py',
    '../_base_/datasets/coco_detection.py',
    '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]

faster_rcnn_r50_fpn_1x_coco.py脚本内容的修改如下(使用VOC数据格式)

_base_ = [
    '../_base_/models/faster_rcnn_r50_fpn.py',
    '../_base_/datasets/voc0712.py',
    '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]

之前是把模型的配置文件,和模型结构都是定义到faster_rcnn_r50_fpn_1x_coco.py这种脚本文件中,最近mmdetection项目代码更新,只不过是做了更好的封装,把这文件进行了拆分,放到了mmdetection/configs/_base_ 目录下,所以要有些内容就要到_base_目录下的文件中进行修改,_base_目录结构如下:

_base_/
├── datasets  # 定义数据路径等信息
│   ├── cityscapes_detection.py
│   ├── cityscapes_instance.py
│   ├── coco_detection.py
│   ├── coco_instance.py
│   ├── coco_instance_semantic.py
│   ├── voc0712.py
│   └── wider_face.py
├── default_runtime.py
├── models  # 定义模型的配置信息
│   ├── cascade_mask_rcnn_r50_fpn.py
│   ├── cascade_rcnn_r50_fpn.py
│   ├── faster_rcnn_r50_caffe_c4.py
│   ├── faster_rcnn_r50_fpn.py
│   ├── fast_rcnn_r50_fpn.py
│   ├── mask_rcnn_r50_caffe_c4.py
│   ├── mask_rcnn_r50_fpn.py
│   ├── retinanet_r50_fpn.py
│   ├── rpn_r50_caffe_c4.py
│   ├── rpn_r50_fpn.py
│   └── ssd300.py
└── schedules  # 定义训练策略信息
    ├── schedule_1x.py
    ├── schedule_20e.py
    └── schedule_2x.py
  • ../_base_/models/faster_rcnn_r50_fpn.py:定义模型文件
    如果你想使用
  • ../_base_/datasets/coco_detection.py:定义训练数据路径等
  • ../_base_/schedules/schedule_1x.py:定义学习策略,例如leaning_rate、epoch等
  • ../_base_/default_runtime.py:定义一些日志等其他信息

3.1.2 修改训练数据的配置文件

修改:./mmdetection/configs/_base_/datasets/voc712.py

因为我们使用的是VOC2007数据,因此只要把其中含有VOC2012路径注释即可,修改后的内容如下:

# dataset settings
dataset_type = 'VOCDataset'
data_root = 'data/VOCdevkit/'
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', with_bbox=True),
    dict(type='Resize', img_scale=(1000, 600), keep_ratio=True),
    dict(type='RandomFlip', flip_ratio=0.5),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='Pad', size_divisor=32),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=(1000, 600),
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='RepeatDataset',
        times=3,
        # dataset=dict(
        #     type=dataset_type,
        #     ann_file=[
        #         data_root + 'VOC2007/ImageSets/Main/trainval.txt',
        #         data_root + 'VOC2012/ImageSets/Main/trainval.txt'
        #     ],
        #     img_prefix=[data_root + 'VOC2007/', data_root + 'VOC2012/'],
        #     pipeline=train_pipeline)),
        # 把含有VOC2012的路径去掉
        dataset=dict(
            type=dataset_type,
            ann_file=[
                data_root + 'VOC2007/ImageSets/Main/trainval.txt',
            ],
            img_prefix=[data_root + 'VOC2007/'],
            pipeline=train_pipeline)),
    val=dict(
        type=dataset_type,
        ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
        img_prefix=data_root + 'VOC2007/',
        pipeline=test_pipeline),
    test=dict(
        type=dataset_type,
        ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
        img_prefix=data_root + 'VOC2007/',
        pipeline=test_pipeline))
evaluation = dict(interval=1, metric='mAP')

3.1.3 修改模型文件中的类别个数

修改:./mmdetection/configs/_base_/models/faster_rcnn_r50_fpn.py

因为这里使用的是VOC2007数据集,一共有20个类别,因此这里把``faster_rcnn_r50_fpn.py第46行的num_classes`的值改为20,根据自己的分类的个数,有多少类就改成多少,修改完如下所示:

model = dict(
    type='FasterRCNN',
    pretrained='torchvision://resnet50',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch'),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[.0, .0, .0, .0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', out_size=7, sample_num=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=20,     # 把类别个数改成自己数据集的类别,如果是voc2007数据集就改成20
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0., 0., 0., 0.],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0))))
# model training and testing settings
train_cfg = dict(
    rpn=dict(
        assigner=dict(
            type='MaxIoUAssigner',
            pos_iou_thr=0.7,
            neg_iou_thr=0.3,
            min_pos_iou=0.3,
            match_low_quality=True,
            ignore_iof_thr=-1),
        sampler=dict(
            type='RandomSampler',
            num=256,
            pos_fraction=0.5,
            neg_pos_ub=-1,
            add_gt_as_proposals=False),
        allowed_border=-1,
        pos_weight=-1,
        debug=False),
    rpn_proposal=dict(
        nms_across_levels=False,
        nms_pre=2000,
        nms_post=1000,
        max_num=1000,
        nms_thr=0.7,
        min_bbox_size=0),
    rcnn=dict(
        assigner=dict(
            type='MaxIoUAssigner',
            pos_iou_thr=0.5,
            neg_iou_thr=0.5,
            min_pos_iou=0.5,
            match_low_quality=False,
            ignore_iof_thr=-1),
        sampler=dict(
            type='RandomSampler',
            num=512,
            pos_fraction=0.25,
            neg_pos_ub=-1,
            add_gt_as_proposals=True),
        pos_weight=-1,
        debug=False))
test_cfg = dict(
    rpn=dict(
        nms_across_levels=False,
        nms_pre=1000,
        nms_post=1000,
        max_num=1000,
        nms_thr=0.7,
        min_bbox_size=0),
    rcnn=dict(
        score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100)
    # soft-nms is also supported for rcnn testing
    # e.g., nms=dict(type='soft_nms', iou_thr=0.5, min_score=0.05)
)

注意:

之前的代码版本是,num_classes改成类别+1,也就把背景也算作一类,在mmdetection V2.0.0版本,背景不在作为一类,因此不用再加1,有多少个类别就写多少

3.1.4 修改测试时的标签类别文件

修改:./mmdetection/mmdet/core/evaluation/class_names.py

修改mmdetection/mmdet/core/evaluation/class_names.py下的class_names.py中的voc_classes,将 其改为要训练的数据集的类别名称。如果不改的话,最后测试的结果的名称还会是’aeroplane’, ‘bicycle’, ‘bird’, ‘boat’,…这些。因为我使用的是voc2007因此可以不做改动,你可以根据自己的类别进行修改:

def voc_classes():
    return [
        'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat',
        'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person',
        'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'
    ]

注意:
如果只有一个类别,需要加上一个逗号,否则将会报错,例如只有一个类别,如下:

def voc_classes():
    return ['aeroplane', ]

3.1.5 修改voc.py文件

修改:mmdetection/mmdet/datasets/voc.py

修改mmdetection/mmdet/datasets/voc.py下的voc.py中的CLASSES,将 其改为要训练的数据集的类别名称。如果不改的话,最后测试的结果的名称还会是’aeroplane’, ‘bicycle’, ‘bird’, ‘boat’,…这些。因为我使用的是voc2007因此可以不做改动,你可以根据自己的类别进行修改:

class VOCDataset(XMLDataset):

    CLASSES = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car',
               'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
               'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train',
               'tvmonitor')

注意:
如果只有一个类别,需要加上一个逗号,否则将会报错,例如只有一个类别,如下:

class VOCDataset(XMLDataset):

    CLASSES = ('aeroplane', )

提示错误:
1、IndentationError: unexpected indent
2、FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmp32p_rtz7/tmp6f4slg8x.py'

从上面看提示了两个错误,我一开始关注的是第二个错误,然后就没有找到错误的原因,后面看到上面还有一个错误:IndentationError: unexpected indent,这种错误一般是由于空格Tab空格混用导致的,看错误上面的dataset=dict(可以定位到这个错误的位置,然后进行修改。

因此建议,在vi编辑器中全部使用空格键进行缩进,最好是在编辑器中,例如Pycharm中改好在再替换,一般不会出现这种错误。
在这里插入图片描述
到此为止,环境的搭建、数据的准备、配置文件的修改已经全部准备完毕,下面就让我们开始训练吧

3.2 开始训练模型

3.2.1 快速开始训练

关于多GPU训练,请参考:这篇博客

1、训练命令:

python python tools/train.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py

我是在VOC2007数据集上,2080Ti(11G显存,实际使用显存大概4G)的显卡上训练12epoch,训练时间3个小时
在这里插入图片描述
结果信息:

+-------------+-----+------+--------+-------+
| class       | gts | dets | recall | ap    |
+-------------+-----+------+--------+-------+
| aeroplane   | 48  | 113  | 0.708  | 0.646 |
| bicycle     | 74  | 145  | 0.824  | 0.773 |
| bird        | 89  | 205  | 0.640  | 0.524 |
| boat        | 75  | 175  | 0.587  | 0.464 |
| bottle      | 99  | 171  | 0.545  | 0.418 |
| bus         | 41  | 111  | 0.732  | 0.573 |
| car         | 247 | 370  | 0.854  | 0.799 |
| cat         | 84  | 198  | 0.869  | 0.735 |
| chair       | 181 | 355  | 0.470  | 0.359 |
| cow         | 53  | 174  | 0.849  | 0.577 |
| diningtable | 33  | 158  | 0.818  | 0.547 |
| dog         | 99  | 352  | 0.919  | 0.739 |
| horse       | 76  | 213  | 0.868  | 0.762 |
| motorbike   | 74  | 182  | 0.905  | 0.813 |
| person      | 881 | 1477 | 0.829  | 0.757 |
| pottedplant | 127 | 187  | 0.425  | 0.323 |
| sheep       | 76  | 153  | 0.579  | 0.491 |
| sofa        | 48  | 214  | 0.833  | 0.547 |
| train       | 54  | 140  | 0.759  | 0.673 |
| tvmonitor   | 58  | 117  | 0.690  | 0.582 |
+-------------+-----+------+--------+-------+
| mAP         |     |      |        | 0.605 |
+-------------+-----+------+--------+-------+
2020-05-27 14:09:53,057 - mmdet - INFO - Epoch [12][6013/6013]  lr: 0.00020, mAP: 0.6050

2、训练完成在工作目录下生成模型文件和日志文件

训练完成之后,训练的模型文件和日志文件等会被保存在./mmdetection/work_dir目录下(work_dir目录不指定会自动创建,也可以用参数--work-dir自己指定):

work_dirs/
└── faster_rcnn_r50_fpn_1x_coco
    ├── 20200527_105051.log
    ├── 20200527_105051.log.json
    ├── epoch_10.pth
    ├── epoch_11.pth
    ├── epoch_12.pth
    ├── epoch_1.pth
    ├── epoch_2.pth
    ├── epoch_3.pth
    ├── epoch_4.pth
    ├── epoch_5.pth
    ├── epoch_6.pth
    ├── epoch_7.pth
    ├── epoch_8.pth
    ├── epoch_9.pth
    ├── latest.pth -> epoch_12.pth
    └── faster_rcnn_r50_fpn_1x_coco.py  # 把之前的列表中的三个文件的代码都写到这个文件中

从上面生成的文件可以看出:每训练完一轮都会保存一个epoch_x.pth模型,最新的也是最终的模型会被保存为latest.pth,同时会生成两个日志文件:

  • 20200527_105051.log 日志内容就是训练时输出的信息:
    在这里插入图片描述
  • 20200527_105051.log.json 日志内容是训练过程中的损失、学习率、精度等信息,主要是为了数据可视化展示,方便调试:
    在这里插入图片描述

注意1:
在训练的过程中程序终止,报错:IndexError: list index out of range
,这个错误是由于类别(num_classes)没有修改导致的,同时类别的修改也发生变化,现在的类别已经不包括背景(background)
在这里插入图片描述

注意2:
这次我使用的是自己的数据集进行训练,一共两类:

  • hard_hat
  • other

训练的时候没有报错,但是出现异常,所有的训练损失都变成了0,每一轮的label也不是自己设置的label,而变成了VOC的label,这个问题是因为少了一个逗号,我也不知道为什么会因为一个逗号而引发一场血案:在/mmdetection/configs/_base_/datasets/voc0712.py中的'VOC2007/ImageSets/Main/trainval.txt'后的逗号一定要加上,否则会报同样的错误。

异常信息:
在这里插入图片描述
问题解决: 把后面的逗号补上

dataset=dict(
            type=dataset_type,
            ann_file=[
                data_root + 'VOC2007/ImageSets/Main/trainval.txt', ],
            img_prefix=[data_root + 'VOC2007/'],

在这里插入图片描述

3.2.2 训练命令中的指定参数

训练命令:

python python tools/train.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py

  • --work-dir:指定训练保存模型和日志的路径
  • --resume-from:从预训练模型chenkpoint中恢复训练
  • --no-validate:训练期间不评估checkpoint
  • --gpus:指定训练使用GPU的数量(仅适用非分布式训练)
  • --gpu-ids: 指定使用哪一块GPU(仅适用非分布式训练)
  • --seed:随机种子
  • --deterministic:是否为CUDNN后端设置确定性选项
  • --options: arguments in dict
  • --launcher: {none,pytorch,slurm,mpi} job launcher
  • --local_rank: LOCAL_RANK
  • --autoscale-lr: automatically scale lr with the number of gpus

加其他参数的训练命令:

1、自己指定模型保存路径

python python tools/train.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py --work-dir my_faster

2、指定GPU数量

python python tools/train.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py --gpus 1 --no-validate --work-dir my_faster

3.3 在自己的预训练模型上进行测试

3.3.1 测试命令1,使用测试脚本test.py

测试命令

tools/test.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py ./work_dirs/my_faster_rcnn_r50_fpn_1x_coco/latest.pth --out ./result.pkl

  • configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py:是模型文件
  • ./work_dirs/my_faster_rcnn_r50_fpn_1x_coco/latest.pth:是我们自己训练保存的模型
  • ./result.pkl:生成一个result.pkl文件,大小1.2M,该文件中会保存各个类别对应的信息,用于计算AP

如下是我测试的结果显示(test.txt 测试集图片有1003张):

(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$ python tools/test.py configs/faster_rcnn/my_faster_rcnn_r50_fpn_1x_coco.py ./work_dirs/my_faster_rcnn_r50_fpn_1x_coco/latest.pth --out ./result.pkl
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 1003/1003, 7.5 task/s, elapsed: 134s, ETA:     0s
writing results to ./result.pkl

测试的其他参数:

MMDet test (and eval) a model

positional arguments:
  config                test config file path
  checkpoint            checkpoint file

optional arguments:
  -h, --help            show this help message and exit
  --out OUT             output result file in pickle format
  --fuse-conv-bn        Whether to fuse conv and bn, this will slightly
                        increasethe inference speed
  --format-only         Format the output results without perform evaluation.
                        It isuseful when you want to format the result to a
                        specific format and submit it to the test server
  --eval EVAL [EVAL ...]
                        evaluation metrics, which depends on the dataset,
                        e.g., "bbox", "segm", "proposal" for COCO, and "mAP",
                        "recall" for PASCAL VOC
  --show                show results
  --show-dir SHOW_DIR   directory where painted images will be saved
  --show-score-thr SHOW_SCORE_THR
                        score threshold (default: 0.3)
  --gpu-collect         whether to use gpu to collect results.
  --tmpdir TMPDIR       tmp directory used for collecting results from
                        multiple workers, available when gpu-collect is not
                        specified
  --options OPTIONS [OPTIONS ...]
                        arguments in dict
  --launcher {none,pytorch,slurm,mpi}
                        job launcher
  --local_rank LOCAL_RANK

使用--show-dir 参数,可以把测试的检测图片检测结果保存到指定文件夹中,如下命令:

python tools/test.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py ./work_dirs_hat_faster_rcnn/latest.pth --out ./result.pkl --show-dir test_hat_result

生成的测试结果图片会被保存到test_hat_result/JPEGImages文件夹下,部分测试结果如下:
在这里插入图片描述

3.3.2 测试命令2,使用测试脚本test_robustness.py

测试命令:

python tools/test_robustness.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py ./work_dirs/faster_rcnn_r50_fpn_1x_coco/latest.pth --out ./result2.pkl

如下是我测试的结果显示(test.txt 测试集图片有1003张):

(mmdetection) zpp@estar-cvip:/HDD/zpp/shl/mmdetection$ python tools/test_robustness.py ./configs/faster_rcnn/my_faster_rcnn_r50_fpn_1x_coco.py ./work_dirs/my_faster_rcnn_r50_fpn_1x_coco/latest.pth --out ./result2.pkl

Testing gaussian_noise at severity 0
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 1003/1003, 7.6 task/s, elapsed: 132s, ETA:     0s
Testing gaussian_noise at severity 1
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 1003/1003, 7.6 task/s, elapsed: 132s, ETA:     0s

test_robustness.py有很多其他的参数,如下:

positional arguments:
  config                test config file path
  checkpoint            checkpoint file

optional arguments:
  -h, --help            show this help message and exit
  --out OUT             output result file
  --corruptions {all,benchmark,noise,blur,weather,digital,holdout,None,gaussian_noise,shot_noise,impulse_noise,defocus_blur,glass_blur,motion_blur,zoom_blur,snow,frost,fog,brightness,contrast,elastic_transform,pixelate,jpeg_compression,speckle_noise,gaussian_blur,spatter,saturate} [{all,benchmark,noise,blur,weather,digital,holdout,None,gaussian_noise,shot_noise,impulse_noise,defocus_blur,glass_blur,motion_blur,zoom_blur,snow,frost,fog,brightness,contrast,elastic_transform,pixelate,jpeg_compression,speckle_noise,gaussian_blur,spatter,saturate} ...]
                        corruptions
  --severities SEVERITIES [SEVERITIES ...]
                        corruption severity levels
  --eval {proposal,proposal_fast,bbox,segm,keypoints} [{proposal,proposal_fast,bbox,segm,keypoints} ...]
                        eval types
  --iou-thr IOU_THR     IoU threshold for pascal voc evaluation
  --summaries SUMMARIES
                        Print summaries for every corruption and severity
  --workers WORKERS     workers per gpu
  --show                show results
  --tmpdir TMPDIR       tmp dir for writing some results
  --seed SEED           random seed
  --launcher {none,pytorch,slurm,mpi}
                        job launcher
  --local_rank LOCAL_RANK
  --final-prints {P,mPC,rPC} [{P,mPC,rPC} ...]
                        corruption benchmark metric to print at the end
  --final-prints-aggregate {all,benchmark}
                        aggregate all results or only those for benchmark
                        corruptions

3.3.3 计算类别的AP

之前计算AP的命令为(参考):python tools/voc_eval.py results.pkl ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py,在mmdetection v1.0.0的版本中还有voc_eval.py这个测试脚本,但是在mmdetection v2.0.0已经取消这个脚本,然后集成都了robustness_eval.py这个脚本中

1、新的计算AP脚本
因此,使用robustness_eval.py脚本计算AP的命令如下:

python tools/robustness_eval.py ./result.pkl --dataset voc --metric AP

2、继续使用之前的脚本计算AP
此时你可以在./tools下新建一个my_voc_eval.py脚本,脚本如下:

'''
项目名称:计算AP
创建时间:20200528
'''

__Author__ = "Shliang"
__Email__ = "shliang0603@gmail.com"


from argparse import ArgumentParser

import mmcv

from mmdet import datasets
from mmdet.core import eval_map


def voc_eval(result_file, dataset, iou_thr=0.5, nproc=4):
    det_results = mmcv.load(result_file)
    annotations = [dataset.get_ann_info(i) for i in range(len(dataset))]
    if hasattr(dataset, 'year') and dataset.year == 2007:
        dataset_name = 'voc07'
    else:
        dataset_name = dataset.CLASSES
    eval_map(
        det_results,
        annotations,
        scale_ranges=None,
        iou_thr=iou_thr,
        dataset=dataset_name,
        logger='print',
        nproc=nproc)


def main():
    parser = ArgumentParser(description='VOC Evaluation')
    parser.add_argument('result', help='result file path')
    parser.add_argument('config', help='config file path')
    parser.add_argument(
        '--iou-thr',
        type=float,
        default=0.5,
        help='IoU threshold for evaluation')
    parser.add_argument(
        '--nproc',
        type=int,
        default=4,
        help='Processes to be used for computing mAP')
    args = parser.parse_args()
    cfg = mmcv.Config.fromfile(args.config)
    test_dataset = mmcv.runner.obj_from_dict(cfg.data.test, datasets)
    voc_eval(args.result, test_dataset, args.iou_thr, args.nproc)


if __name__ == '__main__':
    main()

输入计算AP的命令:

python tools/my_voc_eval.py ./result.pkl ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py

运行结果:
在这里插入图片描述

3.4 用自己训练的模型在图片和视频上做测试

3.4.1 用自己训练的模型在图片上做测试

测试的脚本为:./mmdetection/demo/image_demo.py

from argparse import ArgumentParser

from mmdet.apis import inference_detector, init_detector, show_result_pyplot


def main():
    parser = ArgumentParser()
    parser.add_argument('img', help='Image file')
    parser.add_argument('config', help='Config file')
    parser.add_argument('checkpoint', help='Checkpoint file')
    parser.add_argument(
        '--device', default='cuda:0', help='Device used for inference')
    parser.add_argument(
        '--score-thr', type=float, default=0.3, help='bbox score threshold')
    args = parser.parse_args()

    # build the model from a config file and a checkpoint file
    model = init_detector(args.config, args.checkpoint, device=args.device)
    # test a single image
    result = inference_detector(model, args.img)
    # show the results
    show_result_pyplot(model, args.img, result, score_thr=args.score_thr)


if __name__ == '__main__':
    main()

然后在命令行中输入命令进行测试:

python image_demo.py ../test.jpg ../configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py ../work_dirs/faster_rcnn_r50_fpn_1x_coco/latest.pth

原图:
在这里插入图片描述

下面是我做的其他检测任务的一些检测效果:
在这里插入图片描述

3.4.2 用自己训练的模型在视频上做测试

3.5 训练结果可视化,以及训练时间计算

3.5.1 可视化训练的loss结果

1、可视化命令:

python tools/analyze_logs.py plot_curve ./1_work_dir_gfl_hat_hair_beard/20200805_154359.log.json --keys loss_cls loss_ bbox loss_dfl --out ./plot_result/1_gfl_hat_hair_beard

在这里插入图片描述
2、可视化命令参数介绍:

  • plot_curve:该参数后跟的是训练保存的json文件
  • --keys:后面跟的是要绘制的损失关键字,可以跟多个值
  • --out:后面跟的是绘制保存的结果,可以保存成png图片,也可以保存成pdf

3、绘图的结果:
在这里插入图片描述

3.5.2 计算训练的时间

计算训练时间的命令:

python tools/analyze_logs.py cal_train_time ./1_work_dir_gfl_hat_hair_beard/20200805_154359.log.json

在这里插入图片描述

参考1: # 内容比较详细
参考2:https://blog.csdn.net/syysyf99/article/details/96574325
参考3:https://blog.csdn.net/weicao1990/article/details/93484603


在这里插入图片描述




在这里插入图片描述
♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__0809 返回首页