Detectron训练自己的数据集(VOC格式)细节

#-----------------------ZR----------------------------

#              VOC格式转json格式训练

#-----------!未经同意,不得转载!------------

Detectron平台是基于COCO数据集训练的,而我一开始接触的faster-rcnn都是VOC2007数据集格式的,最近想要试试利用Detectron测试一下会不会有更好的效果,但是当然舍不得重新做数据集啦,当初做数据集真的是要了老命了。所以在此记录一下实现过程。

一、VOC数据集格式转json格式

1、下载 cocoapi,上一篇已经介绍了具体的下载方法

2、先展示转换代码再解释

% Convert ground truth for PASCAL to COCO format.
%
% USAGE
%  CocoUtils.convertPascalGt( dataDir, year, split, annFile )
%
% INPUTS
%  dataDir    - dir containing VOCdevkit2007/
%  year       - dataset year (e.g. '2007')
%  split      - dataset split (e.g. 'val')
%  annFile    - annotation file for writing results
clear all
clc

mex('CXXFLAGS=\$CXXFLAGS -std=c++11 -Wall','-largeArrayDims',...
    'private/gasonMex.cpp','../common/gason.cpp',...
     '-I../common/','-outdir','private');

CocoUtils.convertPascalGt( 'path/to/coco', '2007', 'test', './voc_2007_test.json')
CocoUtils.convertPascalGt( 'path/to/coco', '2007', 'train', './voc_2007_train.json')
CocoUtils.convertPascalGt( 'path/to/coco', '2007', 'trainval', './voc_2007_trainval.json')
CocoUtils.convertPascalGt( 'path/to/coco', '2007', 'val', './voc_2007_val.json')

(1) mex()是编译gason解析器,注意:Matlab 的当前目录必须是 cocoapi/MatlabAPI,否则会出错

(2) 参数说明:

dataDir:存放着我们将要转换的 VOC2007 数据集的 VOCdevkit2007 文件夹的父目录,此处我将 VOCdevkit2007 文件夹放在coco下;

annFile:要生成的转换目标 json 文件路径,注意:此处必须为相对路径,即按照我的代码不要修改,生成的 json 文件在MatlabAPI目录下(开始我用的绝对路径一直报错);

(3) 调用 CocoUtils.convertPascalGt()时,由于会用到 VOCcode 里的 VOCinit.m 文件,所以需要将 VOCdekit2007 添加到 Matlab 路径里,但是此时 Matlab 的当前目录仍为 MatlabAPI;

(4) 特别注意:

     1. 由于 CocoUtils.m 里并未指明 VOCdevkit 哪一年的,而我的直接用的 faster-rcnn 的 VOCdevkit2007 文件夹,所以要将里面会用到的函数里的 VOCdevkit 改为 VOCdevkit2007 ;

     2. 将 VOCcode 里的 VOCinit.m 里的数据集标签种类根据自己的修改

VOCopts.classes={...  
   '你的标签1'  
   '你的标签2'  
   '你的标签3'  
   '你的标签4'};  

     3. 最重要的,如果你的种类只有一种的话,一定要记得打开(可以用notepad)生成的json文件,找到 categories ,添加方括号 [ ],如下:

原始:
"categories":{"supercategory":"none","id":1,"name":"clear"}}

修改后:
"categories":[{"supercategory":"none","id":1,"name":"clear"}]}

不然训练的时候,coco.py 里 cats[cat['id']] = cat 会报错:TypeError: string indices must be integers.

当然,如果你的标签种类不止一种,可以忽略这步,因为转换时有多个 list 会自动添加方括号 [ ]。

另外,这个接口需要 xml 以及 jpg 文件命名方式为 0000xx.xml 和 0000xx.jpg 的数字形式,而我之前是用Labelimg标注的,命名方式也不一样,所以为了以防万一,我写了个程序统一修改成了标准的pascal_voc形式,及 xml 文件的修改主要包括修改 filename 和 folder 字段、删除 path 字段,同时也把对应的图片名改掉。

好了,转换到这儿就完成了。

二、数据集存放

1、数据集存放结构如下:

VOC<year>
|_ JPEGImages
|  |_ <im-1-name>.jpg
|  |_ ...
|  |_ <im-N-name>.jpg
|_ annotations
|  |_ voc_<year>_train.json
|  |_ voc_<year>_val.json
|  |_ ...
|_ VOCdevkit<year>

2、存放位置:

Detectron 默认存放位置在 ' detectron/datasets/data/VOC<year> ' ,如果你将 VOC<year> 存放在这儿的话,不需要其他步骤;

否则,你需要软链接到你的数据集:

$ mkdir -p $DETECTRON/detectron/datasets/data/VOC<year>
$ ln -s /path/to/VOC<year>/JPEGImages $DETECTRON/detectron/datasets/data/VOC<year>/JPEGImages
$ ln -s /path/to/VOC<year>/json/annotations $DETECTRON/detectron/datasets/data/VOC<year>/annotations
$ ln -s /path/to/VOC<year>/devkit $DETECTRON/detectron/datasets/data/VOC<year>/VOCdevkit<year>

三、训练设置

1、下载预训练模型

$ wget https://s3-us-west-2.amazonaws.com/detectron/ImageNetPretrained/MSRA/R-50.pkl /tmp/detectron/detectron-download-cache/ImageNetPretrained/MSRA/R-50.pkl

可以在训练的时候下载,不过估计没人这么干,肯定事先下载好。新建文件夹 pre-trained_model 把 R-50.pkl 模型文件放在该文件夹下

2、修改配置文件

(1) 为了防止配置文件改得面目全非,一般都是重新复制一个到新目录里,这样随你折腾。

在detectron路径下新建experiments,把configs/getting_started/tutoria_1gpu_e2e_faster_rcnn_R-50FPN.yaml复制到experiments 下,并重命名为 e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml(这个命名看个人,只要后面的更改一致就行):

cd detectron
mkdir experiments && cd experiments
cp ../configs/getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml

(2) 打开 e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml

修改 NUM_CLASSES: 后面数字为自建数据集标签种类+1,例如 n 种标签,那么就写 n+1 。同时在TRAIN中修改 WEIGHTS 为预训练模型路径,指向前面下载的 R-50.pkl,如 pre-trained_model/R-50.pkl 。

修改TRAIN和TEST中的DATASET为:'voc_2007_train' 和 'voc_2007_test' 。

其他的看着修改。

(3) 网上有说需要将 lib/modeling/fast_rcnn_heads.py 里所有的 cls_score 为 cls_score_voc,以及 bbox_pred 修改为 bbox_pred_voc。且在训练结束后 inferece 时,需要将 cls_score_voc 以及 bbox_pred_voc 改回,不然会报错。

但我实际训练时发现我没有修改并没有报错。

(4) 修改dummp_datasets.py和infer_simple.py

在 detectron的detectron/datasets/dummy_datasets.py 文件中仿照 get_coco_dataset() 函数添加一个 get_voc_dataset() 函数,具体如下:

def get_ivoc_dataset():
    """A dummy COCO dataset that includes only the 'classes' field."""
    ds = AttrDict()
    classes = [
        '__background__', '你的标签1', '你的标签2'
    ]
    ds.classes = {i: name for i, name in enumerate(classes)}
    return ds

 然后在 infer_simple.py 文件中将 main() 函数里面的

dummy_coco_dataset = dummy_datasets.get_coco_dataset()
改成:
dummy_coco_dataset = dummy_datasets.get_voc_dataset()

这样,最后的结果图上就是自己的标签名。并且,我还在 infer_simple.py 里将输出图像从默认的 pdf 格式改成里 jpg ,方便查看。

四、开始训练

$ python2 tools/train_net.py --cfg experiments/e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml  OUTPUT_DIR experiments/output

       测试训练结果

$ python2 tools/infer_simple.py --cfg experiments/e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml \
    --output-dir tmp/detectron-visualizations  --image-ext jpg --wts 训练结果路径/model_final.pkl \
    demo

      评估训练结果

$ python2 tools/test_net.py \
    --cfg experiments/e2e_faster_rcnn_resnet-50-FPN_pascal2007.yaml \
    TEST.WEIGHTS 训练结果路径/model_final.pkl \

      PS:若对训练结果不满意,可以尝试修改训练配置文件,然后删除 output 里面内容,再次训练。

五、最后,就是大家的自由探索了,毕竟 Detectron 里模型那么多......

猜你喜欢

转载自blog.csdn.net/u014236392/article/details/81127537