mmdetection v2.0在ubuntu16.04服务器上的配置和训练自己的voc数据集

一.mmdetection环境搭建

系统环境:
ubuntu16.04
cuda:10.0(此处一定注意检查自己的环境,关乎到后面cudatoolkit版本的安装问题)
默认大家都已经安装好 anaconda3 了,如果没有安装的,可以去官网下载一个,直接安装即可。

1.创建 Anaconda 的虚拟环境

conda create -n mmdetection python=3.7 (mmdetection虚拟环境的名字,可以自己设定)
conda activate mmdetection (激活虚拟环境)

2.安装Pytorch

conda install pytorch torchvision cudatoolkit=10.0 -c pytorch
注意:此处的cudatoolkit=10.0是对应你的cuda版本的,如果你的cuda版本是 9.0/ 9.2/ 10.1,那么相应改为cudatoolkit=9.0/ 9.2/ 10.1,不知道自己的 cuda 版本?去 /usr/local/ 下去看。

3.安装Cython

conda install cython

4.编译安装mmdetection

git clone https://github.com/open-mmlab/mmdetection.git (下载)
cd mmdetection
pip install -r requirements/build.txt (安装需要的组件)
pip install “git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI” (安装pycocotools)
pip install -v -e . # or “python setup.py develop”
安装过程如下:

(mmdetection) bubble@XPS-8930:~/mmdetection/0827/mmdetection$ python setup.py develop
Compiling mmdet/ops/nms/src/soft_nms_cpu.pyx because it changed.
[1/1] Cythonizing mmdet/ops/nms/src/soft_nms_cpu.pyx
/home/bubble/anaconda3/envs/mmdetection/lib/python3.7/site-packages/setuptools/dist.py:474: UserWarning: Normalizing '1.0.rc0+bfce31c' to '1.0rc0+bfce31c'
  normalized_version,
running develop
running egg_info
...
...
Using /home/bubble/anaconda3/envs/mmdetection/lib/python3.7/site-packages
Searching for setuptools==41.2.0
Best match: setuptools 41.2.0
Adding setuptools 41.2.0 to easy-install.pth file
Installing easy_install script to /home/bubble/anaconda3/envs/mmdetection/bin
 
Using /home/bubble/anaconda3/envs/mmdetection/lib/python3.7/site-packages
Searching for decorator==4.4.0
Best match: decorator 4.4.0
Adding decorator 4.4.0 to easy-install.pth file
 
Using /home/bubble/anaconda3/envs/mmdetection/lib/python3.7/site-packages
Finished processing dependencies for mmdet==1.0rc0+bfce31c
5.cocoapi的编译安装

1)下载cocoapi:git clone https://github.com/cocodataset/cocoapi.git
2)进入cocoAPI/PythonAPI目录,执行
python setup.py build_ext --inplace
python setup.py build_ext install

6.测试

命令行进入 python 环境之后测试

Python 3.7.8 | packaged by conda-forge | (default, Jul 23 2020, 03:54:19) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.__version__
'1.4.0'
>>> torch.cuda.is_available()
True
>>> 

至此,mmdetection环境配置成功。

二.利用 mmdetection训练自己的voc数据集

1.制作voc数据集

(可参照我博客另一篇文章https://blog.csdn.net/qq_36756866/article/details/105269137)
制作voc数据集的第一步就是按voc数据集的格式创建好文件夹,下面是文件夹的组织方式,Annotations中存放图片的labelImg标注文件,JPEGImages存放图片数据。
VOC数据集目录结构如上
可以看到Main文件夹下存放了四个txt文件,这些文件里面的内容其实就是将数据集打乱并划分为测试集,训练集,训练验证集,验证集之后的文件名。在网络训练过程中,可以通过文件名来索引训练样本。这四个文件可由 gen_txt.py 来生成。

import os
import random

trainval_percent = 0.8    # trainval数据集占所有数据的比例
train_percent = 0.8       # train数据集占trainval数据的比例
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()

上述代码分割数据集,训练集占80%,测试集占20%,注意自己的文件路径,可能需要根据自己的存放位置进行修改。

2. 修改 VOC0712.py 文件

cd /mmdetection/configs/base/datasets 进入目录后打开voc0712.py

# dataset settings
dataset_type = 'VOCDataset'      # 数据集类型
# data_root = 'data/VOCdevkit/'
data_root = '/home/trainingai/zyang/darknet_MSW/darknet/'  # VOC数据集根目录
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),     # train data size
    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),                  # test data size
        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=8,           # 每个gpu计算的图像数量   batchsize
    workers_per_gpu=2,           # 每个gpu分配的线程数
    train=dict(
        type='RepeatDataset',
        times=3,
        dataset=dict(
            type=dataset_type,        # 数据集类型
            ann_file=[
                data_root + 'VOC2007/ImageSets/Main/train.txt',
                # data_root + 'VOC2012/ImageSets/Main/trainval.txt'
            ],
            img_prefix=[data_root + 'VOC2007/'],
            # img_prefix=[data_root + 'VOC2007/', data_root + 'VOC2012/'],
            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')

在data的配置 要删除屏蔽VOC2012的路径,和VOC2012变量 保存文件。

3.修改 voc.py 文件

cd /mmdetection/mmdet/datasets 进入目录后打开voc.py文件
这个CLASSE 是VOC标签的类别 我们要换成自己数据集的类别标签
在这里插入图片描述

4.修改class_names.py 文件

cd /mmdetection/mmdet/core/evaluation 进入目录后打开class_names.py 文件
修改 voc_classes() 函数返回的标签,换成自己数据集的标签 保存退出
在这里插入图片描述

5.修改 faster_rcnn_r50_fpn_1x_coco.py

cd mmdetection/configs/faster_rcnn 我们这次选用faster_rcnn 模型训练,进入目录后打开faster_rcnn_r50_fpn_1x_coco.py文件
在这里插入图片描述
faster_rcnn_r50_fpn_1xcoco.py文件里面调用了三个文件,第一个是模型配置文件,第二个是数据集配置文件,后来两个是配置学习率,迭代次数,模型加载路径等等,我们把原来COCO_detection.py 修改成VOC0712.py 文件

6.修改faster_rcnn_r50_fpn.py

cd /mmdetection/configs/base/models 进入目录后打开 faster_rcnn_r50fpn.py 文件 ,修改num_classes 数量,num_classes 的值等于类别数量,注意不需要加背景了
在这里插入图片描述
以上就是需要修改的内容,修改完成后开始训练模型

7.训练模型

指定GPU训练
CUDA_VISIBLE_DEVICES=0 python3 ./tools/train.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py
附上一张正在训练的日志截图
在这里插入图片描述
训练完成后可以参考/mmdetection/demo/image_demo.py文件进行测试

8.模型测试

测试代码命令如下:
CUDA_VISIBLE_DEVICES=0 python ./tools/test.py ./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py work_dirs/faster_rcnn_r50_fpn_1x_coco/latest.pth --out model/result.pkl --eval mAP
------./tools/test.py 测试代码
------./configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py 配置文件(同训练过程)
------work_dirs/faster_rcnn_r50_fpn_1x_coco/latest.pth 训练模型保存路径及文件
------out model/result.pkl 测试输出结果记录文件
测试结果如下:
在这里插入图片描述

测试demo

1)测试图片

python demo/image_demo.py  demo/demo.jpg  configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

2)测试视频

python demo/test_vedio.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py  checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth  --file demo/demo.mp4 --out demo/res.mp4
9.断点训练
# 当训练中断,可从断点权重文件处继续训练
 CUDA_VISIBLE_DEVICES=0 python tools/train.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py  --resume-from="work_dirs/faster_rcnn_r50_fpn_1x_coco/epoch_11.pth"
10.mmdetection自带的log分析工具

mmdetection会自动收集log信息,存储在work_dirs/目录下,官方提供了tools/analyze_logs.py工具可以轻松的可视化日志信息,如可视化损失值并保存为pdf文件,执行如下命令:

python tools/analysis_tools/analyze_logs.py plot_curve work_dirs/faster_rcnn_r50_fpn_1x_coco/20210809_132721.log.json --keys loss_rpn_cls loss_rpn_bbox  loss --out losses.pdf
# 训练过程显示的输出指标都可以可视化出来,添加到--keys参数后面即可

如下图是loss_rpn_cls,loss_rpn_bbox ,loss三个指标的可视化曲线图
在这里插入图片描述

以上就是mmdetection 在ubuntu16.04服务器上的配置详细过程和使用自己的数据集训练mmdetection faster_rcnn模型及测试的详细内容。

附:faster_rcnn_r50_fpn_1x.py配置文件详细注释

这个配置文件所描述的是基于resnet50的backbone,有5个fpn特征层的faster-RCNN目标检测网络,训练迭代次数为标准的12次epoch,下面逐条解释其含义

# model settings
model = dict(
	type='FasterRCNN',                         # model类型
    pretrained='modelzoo://resnet50',          # 预训练模型:imagenet-resnet50
    backbone=dict(
        type='ResNet',                         # backbone类型
        depth=50,                              # 网络层数
        num_stages=4,                          # resnet的stage数量
        out_indices=(0, 1, 2, 3),              # 输出的stage的序号
        frozen_stages=1,                       # 冻结的stage数量,即该stage不更新参数,-1表示所有的stage都更新参数
        style='pytorch'),                      # 网络风格:如果设置pytorch,则stride为2的层是conv3x3的卷积层;如果设置caffe,则stride为2的层是第一个conv1x1的卷积层
    neck=dict(
        type='FPN',                            # neck类型
        in_channels=[256, 512, 1024, 2048],    # 输入的各个stage的通道数
        out_channels=256,                      # 输出的特征层的通道数
        num_outs=5),                           # 输出的特征层的数量
    rpn_head=dict(
        type='RPNHead',                        # RPN网络类型
        in_channels=256,                       # RPN网络的输入通道数
        feat_channels=256,                     # 特征层的通道数
        anchor_scales=[8],                     # 生成的anchor的baselen,baselen = sqrt(w*h),w和h为anchor的宽和高
        anchor_ratios=[0.5, 1.0, 2.0],         # anchor的宽高比
        anchor_strides=[4, 8, 16, 32, 64],     # 在每个特征层上的anchor的步长(对应于原图)
        target_means=[.0, .0, .0, .0],         # 均值
        target_stds=[1.0, 1.0, 1.0, 1.0],      # 方差
        use_sigmoid_cls=True),                 # 是否使用sigmoid来进行分类,如果False则使用softmax来分类
    bbox_roi_extractor=dict(
        type='SingleRoIExtractor',                                   # RoIExtractor类型
        roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),   # ROI具体参数:ROI类型为ROIalign,输出尺寸为7,sample数为2
        out_channels=256,                                            # 输出通道数
        featmap_strides=[4, 8, 16, 32]),                             # 特征图的步长
    bbox_head=dict(
        type='SharedFCBBoxHead',                     # 全连接层类型
        num_fcs=2,                                   # 全连接层数量
        in_channels=256,                             # 输入通道数
        fc_out_channels=1024,                        # 输出通道数
        roi_feat_size=7,                             # ROI特征层尺寸
        num_classes=81,                              # 分类器的类别数量+1,+1是因为多了一个背景的类别
        target_means=[0., 0., 0., 0.],               # 均值
        target_stds=[0.1, 0.1, 0.2, 0.2],            # 方差
        reg_class_agnostic=False))                   # 是否采用class_agnostic的方式来预测,class_agnostic表示输出bbox时只考虑其是否为前景,后续分类的时候再根据该bbox在网络中的类别得分来分类,也就是说一个框可以对应多个类别
# model training and testing settings
train_cfg = dict(
    rpn=dict(
        assigner=dict(
            type='MaxIoUAssigner',            # RPN网络的正负样本划分
            pos_iou_thr=0.7,                  # 正样本的iou阈值
            neg_iou_thr=0.3,                  # 负样本的iou阈值
            min_pos_iou=0.3,                  # 正样本的iou最小值。如果assign给ground truth的anchors中最大的IOU低于0.3,则忽略所有的anchors,否则保留最大IOU的anchor
            ignore_iof_thr=-1),               # 忽略bbox的阈值,当ground truth中包含需要忽略的bbox时使用,-1表示不忽略
        sampler=dict(
            type='RandomSampler',             # 正负样本提取器类型
            num=256,                          # 需提取的正负样本数量
            pos_fraction=0.5,                 # 正样本比例
            neg_pos_ub=-1,                    # 最大负样本比例,大于该比例的负样本忽略,-1表示不忽略
            add_gt_as_proposals=False),       # 把ground truth加入proposal作为正样本
        allowed_border=0,                     # 允许在bbox周围外扩一定的像素
        pos_weight=-1,                        # 正样本权重,-1表示不改变原始的权重
        smoothl1_beta=1 / 9.0,                # 平滑L1系数
        debug=False),                         # debug模式
    rcnn=dict(
        assigner=dict(
            type='MaxIoUAssigner',            # RCNN网络正负样本划分
            pos_iou_thr=0.5,                  # 正样本的iou阈值
            neg_iou_thr=0.5,                  # 负样本的iou阈值
            min_pos_iou=0.5,                  # 正样本的iou最小值。如果assign给ground truth的anchors中最大的IOU低于0.3,则忽略所有的anchors,否则保留最大IOU的anchor
            ignore_iof_thr=-1),               # 忽略bbox的阈值,当ground truth中包含需要忽略的bbox时使用,-1表示不忽略
        sampler=dict(
            type='RandomSampler',             # 正负样本提取器类型
            num=512,                          # 需提取的正负样本数量
            pos_fraction=0.25,                # 正样本比例
            neg_pos_ub=-1,                    # 最大负样本比例,大于该比例的负样本忽略,-1表示不忽略
            add_gt_as_proposals=True),        # 把ground truth加入proposal作为正样本
        pos_weight=-1,                        # 正样本权重,-1表示不改变原始的权重
        debug=False))                         # debug模式
test_cfg = dict(
    rpn=dict(                                 # 推断时的RPN参数
        nms_across_levels=False,              # 在所有的fpn层内做nms
        nms_pre=2000,                         # 在nms之前保留的的得分最高的proposal数量
        nms_post=2000,                        # 在nms之后保留的的得分最高的proposal数量
        max_num=2000,                         # 在后处理完成之后保留的proposal数量
        nms_thr=0.7,                          # nms阈值
        min_bbox_size=0),                     # 最小bbox尺寸
    rcnn=dict(
        score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100)   # max_per_img表示最终输出的det bbox数量
    # soft-nms is also supported for rcnn testing
    # e.g., nms=dict(type='soft_nms', iou_thr=0.5, min_score=0.05)            # soft_nms参数
)
# dataset settings
dataset_type = 'CocoDataset'                # 数据集类型
data_root = 'data/coco/'                    # 数据集根目录
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)   # 输入图像初始化,减去均值mean并处以方差std,to_rgb表示将bgr转为rgb
data = dict(
    imgs_per_gpu=2,                # 每个gpu计算的图像数量
    workers_per_gpu=2,             # 每个gpu分配的线程数
    train=dict(
        type=dataset_type,                                                 # 数据集类型
        ann_file=data_root + 'annotations/instances_train2017.json',       # 数据集annotation路径
        img_prefix=data_root + 'train2017/',                               # 数据集的图片路径
        img_scale=(1333, 800),                                             # 输入图像尺寸,最大边1333,最小边800
        img_norm_cfg=img_norm_cfg,                                         # 图像初始化参数
        size_divisor=32,                                                   # 对图像进行resize时的最小单位,32表示所有的图像都会被resize成32的倍数
        flip_ratio=0.5,                                                    # 图像的随机左右翻转的概率
        with_mask=False,                                                   # 训练时附带mask
        with_crowd=True,                                                   # 训练时附带difficult的样本
        with_label=True),                                                  # 训练时附带label
    val=dict(
        type=dataset_type,                                                 # 同上
        ann_file=data_root + 'annotations/instances_val2017.json',         # 同上
        img_prefix=data_root + 'val2017/',                                 # 同上
        img_scale=(1333, 800),                                             # 同上
        img_norm_cfg=img_norm_cfg,                                         # 同上
        size_divisor=32,                                                   # 同上
        flip_ratio=0,                                                      # 同上
        with_mask=False,                                                   # 同上
        with_crowd=True,                                                   # 同上
        with_label=True),                                                  # 同上
    test=dict(
        type=dataset_type,                                                 # 同上
        ann_file=data_root + 'annotations/instances_val2017.json',         # 同上
        img_prefix=data_root + 'val2017/',                                 # 同上
        img_scale=(1333, 800),                                             # 同上
        img_norm_cfg=img_norm_cfg,                                         # 同上
        size_divisor=32,                                                   # 同上
        flip_ratio=0,                                                      # 同上
        with_mask=False,                                                   # 同上
        with_label=False,                                                  # 同上
        test_mode=True))                                                   # 同上
# optimizer
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)   # 优化参数,lr为学习率,momentum为动量因子,weight_decay为权重衰减因子
optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))          # 梯度均衡参数
# learning policy
lr_config = dict(
    policy='step',                        # 优化策略
    warmup='linear',                      # 初始的学习率增加的策略,linear为线性增加
    warmup_iters=500,                     # 在初始的500次迭代中学习率逐渐增加
    warmup_ratio=1.0 / 3,                 # 起始的学习率
    step=[8, 11])                         # 在第8和11个epoch时降低学习率
checkpoint_config = dict(interval=1)      # 每1个epoch存储一次模型
# yapf:disable
log_config = dict(
    interval=50,                          # 每50个batch输出一次信息
    hooks=[
        dict(type='TextLoggerHook'),      # 控制台输出信息的风格
        # dict(type='TensorboardLoggerHook')
    ])
# yapf:enable
# runtime settings
total_epochs = 12                               # 最大epoch数
dist_params = dict(backend='nccl')              # 分布式参数
log_level = 'INFO'                              # 输出信息的完整度级别
work_dir = './work_dirs/faster_rcnn_r50_fpn_1x' # log文件和模型文件存储路径
load_from = None                                # 加载模型的路径,None表示从预训练模型加载
resume_from = None                              # 恢复训练模型的路径
workflow = [('train', 1)]                       # 当前工作区名称
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值