1 前言

最近有研究和使用faster rcnn的需求,吸取之前的经验(数据并行化等坑),决定直接从高级框架入手。关于搭建的事项,坑比较多,可以参考本人之前的文章。本文从Detectron环境搭建完成并成功运行官方demo开始,

2 制作自己的数据集

2.1 准备数据

将数据放置到$DETECTRON/lib/datasets/data(或其他目录下面再创建软连接),如ms_train数据集,并在其中以如下结构放置数据集的数据:
ms_train
├── annos.csv
├── annotations/
├── classes.txt
└── images/
其中,annos.csv是含BBox标注信息,每行对应一条BBOX标记:filename,label, x_min, y_min, x_max, y_max,如下

318818_002.png,31,237,313,261,327
318818_002.png,31,230,315,244,324
318818_005.png,31,200,180,246,205
318818_007.png,31,256,194,302,240
318818_007.png,31,262,358,289,378
318818_008.png,31,262,358,289,378
318818_009.png,31,262,358,289,378

annotations是空文件夹,准备拿来放生成的.json文件
classes.txt说明本次任务的类别与其id,如下

5 apple
16 cat

images文件夹放置所有图片,文件名与上文的filename相同

2.2 转化标注格式

照着别人的实现和COCO官方数据集的声明,自己写了一份代码,跑通了。root_path换成你的实际地址

import json
import os

# import cv2

# 根路径,里面包含images(图片文件夹),annos.txt(bbox标注),classes.txt(类别标签),以及annotations文件夹(如果没有则会自动创建,用于保存最后的json)
root_path = '/media/zht/4945048867750FD1/CT/converted_to_coco/ms_train'
# 用于创建训练集或验证集
phase = 'train'
# 训练集和验证集划分的界线
split = 88000
# 初始化数据集信息
dataset = {
    'licenses': [],
    'info': {},
    'categories': [],
    'images': [],
    'annotations': []
}
img_name_to_id = dict()

# 打开类别标签
with open(os.path.join(root_path, 'classes.txt')) as f:
    classes = f.readlines()
    # 建立类别标签和数字id的对应关系
    for cls in classes:
        cls_id, cls_name = cls.strip().split()
        dataset['categories'].append({'id': int(cls_id), 'name': cls_name, 'supercategory': 'tumour'})

# 读取images文件夹的图片名称
indexes = [f for f in os.listdir(os.path.join(root_path, 'images'))]
_indexes = indexes.copy()

# 判断是建立训练集还是验证集
if phase == 'train':
    indexes = [line for i, line in enumerate(_indexes) if i <= split]
elif phase == 'val':
    indexes = [line for i, line in enumerate(_indexes) if i > split]

# 添加图像的信息到dataset中
for k, index in enumerate(indexes):
    # 用opencv读取图片,得到图像的宽和高
    # im = cv2.imread(os.path.join(root_path, 'images/') + index)
    dataset['images'].append({'file_name': index,
                              'id': k,
                              'width': 512,
                              'height': 512})
    img_name_to_id[index] = k

# 读取Bbox信息
with open(os.path.join(root_path, 'annos.csv')) as tr:
    annos = tr.readlines()

for i, anno in enumerate(annos):
    parts = anno.strip().split(',')
    index = parts[0]
    # 如果图像的名称和标记的名称对上,则添加标记
    if index in img_name_to_id.keys():
        # if parts[0] == index:
        # 类别
        cls_id = parts[1]
        # x_min
        x1 = float(parts[2])
        # y_min
        y1 = float(parts[3])
        # x_max
        x2 = float(parts[4])
        # y_max
        y2 = float(parts[5])
        width = max(0, x2 - x1)
        height = max(0, y2 - y1)
        dataset['annotations'].append({
            'area': width * height,
            'bbox': [x1, y1, width, height],
            'category_id': int(cls_id),
            'id': i,
            'image_id': img_name_to_id[index],
            'iscrowd': 0,
            # mask, 矩形是从左上角点按顺时针的四个顶点
            'segmentation': [[x1, y1, x2, y1, x2, y2, x1, y2]]
        })

# 保存结果的文件夹
folder = os.path.join(root_path, 'annotations')
if not os.path.exists(folder):
    os.makedirs(folder)
json_name = os.path.join(root_path, 'annotations/{}.json'.format(phase))
with open(json_name, 'w') as f:
    json.dump(dataset, f)

2.3 设置指向自己的数据集

至此,你的ms_train文件夹下已经有了.json文件。COCO格式定义一个数据集,主要就是使用一个.json,即,一个.json + 一个图片文件夹 ==> 一个COCO数据集。
修改$DETECTRON/lib/datasets/dataset_catalog.py文件,照葫芦画瓢,添加自己的数据集(你也可以直接修改已有的数据集信息转向自己的数据集,但个人习惯不直接修改已有的):

    'coco_2014_train': {
        _IM_DIR:
            _DATA_DIR + '/coco/coco_train2014',
        _ANN_FN:
            _DATA_DIR + '/coco/annotations/instances_train2014.json'
    },
    'coco_2014_val': {
        _IM_DIR:
            _DATA_DIR + '/coco/coco_val2014',
        _ANN_FN:
            _DATA_DIR + '/coco/annotations/instances_val2014.json'
    },
    'ms_train': {
        _IM_DIR:
            _DATA_DIR + '/ms_train/images',
        _ANN_FN:
            _DATA_DIR + '/ms_train/annotations/train.json'
    },
    'ms_val': {
        _IM_DIR:
            _DATA_DIR + '/ms_train/images',
        _ANN_FN:
            _DATA_DIR + '/ms_train/annotations/val.json'
    },

3 新建配置文件,开始训练

到这里,设置好了相应的数据集,下面需要指定训练模型使用该数据集,Detectron是通过配置文件来指定的。

3.1 新建配置文件(.yaml)

根据你使用的GPU数量与要训练的网络模型,选择一个yaml配置文件;
可以直接复制Detectron自带的配置文件,并稍作修改即可,在$DETECTRON根目录下复制:

cd configs
mkdir animals
cp getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml animals/animals_1gpu_e2e_faster_rcnn_R-50-FPN.yaml

然后打开animals_1gpu_e2e_faster_rcnn_R-50-FPN.yaml进行编辑:

MODEL:
  TYPE: generalized_rcnn
  CONV_BODY: FPN.add_fpn_ResNet50_conv5_body
  NUM_CLASSES: 5
  FASTER_RCNN: True
NUM_GPUS: 1
SOLVER:
  WEIGHT_DECAY: 0.0001
  LR_POLICY: steps_with_decay
  BASE_LR: 0.0025
  GAMMA: 0.1
  MAX_ITER: 60000
  STEPS: [0, 30000, 40000]
  # Equivalent schedules with...
  # 1 GPU:
  #   BASE_LR: 0.0025
  #   MAX_ITER: 60000
  #   STEPS: [0, 30000, 40000]
  # 2 GPUs:
  #   BASE_LR: 0.005
  #   MAX_ITER: 30000
  #   STEPS: [0, 15000, 20000]
  # 4 GPUs:
  #   BASE_LR: 0.01
  #   MAX_ITER: 15000
  #   STEPS: [0, 7500, 10000]
  # 8 GPUs:
  #   BASE_LR: 0.02
  #   MAX_ITER: 7500
  #   STEPS: [0, 3750, 5000]
RPN:
  ASPECT_RATIOS: (0.5, 1, 2)
FPN:
  FPN_ON: True
  MULTILEVEL_ROIS: True
  MULTILEVEL_RPN: True
  RPN_ASPECT_RATIOS: (0.5, 1, 2)
FAST_RCNN:
  ROI_BOX_HEAD: fast_rcnn_heads.add_roi_2mlp_head
  ROI_XFORM_METHOD: RoIAlign
  ROI_XFORM_RESOLUTION: 7
  ROI_XFORM_SAMPLING_RATIO: 2
TRAIN:
  WEIGHTS: pretrained_models/ImageNetPretrained/MSRA/R-50.pkl
  DATASETS: ('ms_train',)
  SCALES: (500,)
  SNAPSHOT_ITERS: 5000
  MAX_SIZE: 833
  BATCH_SIZE_PER_IM: 256
  RPN_PRE_NMS_TOP_N: 2000  # Per FPN level
TEST:
  DATASETS: ('ms_val',)
  SCALES: (500,)
  MAX_SIZE: 833
  NMS: 0.5
  RPN_PRE_NMS_TOP_N: 1000  # Per FPN level
  RPN_POST_NMS_TOP_N: 1000
  FORCE_JSON_DATASET_EVAL: True
OUTPUT_DIR: .

主要修改以下内容:

  1. MODEL里的NUM_CLASSES,根据自己的数据集进行修改,包括背景。
    2.T RAIN和TEST里的DATASETS,设置为如上所示,因为我们已经修改了dataset_catalog.py中的相应内容并指向了我们的数据集,所以我们可以直接使用这两个数据集的名字。
  2. TRAIN里的WEIGHTS是一个预训练的模型,如果本地有,修改指向它即可。
  3. 关于NUM_GPUS,这个需要与SOLVER里面的学习率等一干参数进行联动设置。

有个坑,在测试阶段,配置文件里要添加一条FORCE_JSON_DATASET_EVAL: True,如下

TEST:
  FORCE_JSON_DATASET_EVAL: True

3.2 开始训练

设置好数据集和配置文件,即可开始训练模型了。回到$DETECTRON根目录,打开Terminal运行如下命令即可开始训练:

python tools/train_net.py --cfg configs/animals/animals_1gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR detectron-output

更多请参考官方文档

后记

第一次使用大型框架来做图像相关的任务,大概花了两天时间配置环境,然后又用了两天跑通自己的数据集,写下本文记录这个过程,转载请获得授权并注明本站信息
后续会研习相关paper并调整参数

参考

https://blog.csdn.net/qq_15969343/article/details/80848175
https://www.yueye.org/2018/train-object-detection-model-using-detectron.html

最后修改日期: 2019年7月18日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。