OneNet: End-to-End One-Stage Object Detection by Classification Cost
这里主要介绍下 OneNet: End-to-End One-Stage Object Detection by Classification Cost 这篇论文的训练过程:
paper
code
1.环境配置
根据 github中的 Readme 安装流程安装即可。
2.数据加载
这里数据加载有两种方式,以VOC2007文件格式为例(如下图),将你的的数据文件结构按照VOC的格式处理好。处理Main中的txt脚本见附件voc_data_process.py。
rootif cls not in class_names:
continue
|——VOC2007
|——Annotations #放入所有的xml文件
|——ImageSets
|—Main #放入train.txt,val.txt文件
|——JPEGImages
第一种方式:
使用软连接将数据连接进来,指令如下,连接后,在工程dataset下会出现你链的三那个文件,文件数量和源文件一样(copy)
ln -s your data root path/Annotations dataset/Annotations
ln -s your data root path/ImageSets dataset/ImageSets
ln -s your data root path/JPEGImages dataset/JPEGImages
第二种方式:
直接修改代码中的 root 路径,将root 路径改成你本地的root 路径,但需要注意的是,你下一级的文件名须要是VOC20(07/12) ,这和detection2 里面支持的数据集有关,名字不对应可能读不到,如果用voc,这个几个名字是支持的,具体支持哪些在builtin.py
中也可以查看。
修改 /OneNet/detectron2/data/datasets/builtin.py 文件的255行左右的内容
if __name__.endswith(".builtin"):
# Assume pre-defined datasets live in `./datasets`.
_root = os.getenv("DETECTRON2_DATASETS", "datasets")
### add
_root_ = "/data/Dataset/工程训练数据/检测数据"
register_all_coco(_root)
register_all_lvis(_root)
register_all_cityscapes(_root)
register_all_cityscapes_panoptic(_root)
###修改
register_all_pascal_voc(_root_)
register_all_ade20k(_root)
3.配置修改
(1)修改 yaml 配置文件, res18 nodcn为例
注意:DATASETS是根据你的文件名对应修改的,在/OneNet/detectron2/data/datasets/builtin.py
可以找到,voc的大概在220行。
_BASE_: "Base-OneNet.yaml"
MODEL:
WEIGHTS: "/data_2/learning/Detection/Torch/OneNet/Pre-trainedModel/torchvision-R-18.pkl"
BACKBONE:
FREEZE_AT: 0
RESNETS:
NORM: "BN"
DEPTH: 18
RES2_OUT_CHANNELS: 64
STRIDE_IN_1X1: False
OneNet:
DCN: False
# NUM_CLASSES: 80
NUM_CLASSES: 7
DECONV_CHANNEL: (512, 256, 128, 64)
DATASETS:
# TRAIN: ("coco_2017_train",)
# TEST: ("coco_2017_val",)
TRAIN: ("voc_2007_train",)
TEST: ("voc_2007_val",)
SOLVER:
# IMS_PER_BATCH: 64
IMS_PER_BATCH: 2
STEPS: (210000, 250000)
MAX_ITER: 270000
INPUT:
CROP:
ENABLED: True
FORMAT: "RGB"
OUTPUT_DIR: 'output_onenet_r18nodcn'
(2)修改/data_2/learning/Detection/Torch/OneNet/detectron2/data/datasets/pascal_voc.py
⓵ 将 CLASS_NAMES 替换成你自己的
⓶ 建议修改的地方,如果你的数据名中存在 # $等特殊符号
load_voc_instances()函数中
将
with PathManager.open(os.path.join(dirname, "ImageSets", "Main", split + ".txt")) as f:
fileids = np.loadtxt(f, dtype=np.str)
替换成
with open(os.path.join(dirname, "ImageSets", "Main", split + ".txt"))as f:
lines = []
read_txt(f, lines)
fileids = np.array(lines)
在函数上方定义read_txt()函数
def read_txt(f, lines):
for line in f:
line = line.replace('\n', '')
lines.append(line)
⓷ 建议修改的地方
还是load_voc_instances()函数中
找到如下代码块,大概在五六十行左右
for obj in tree.findall("object"):
cls = obj.find("name").text
在后面添加保护
if cls not in class_names:
continue
4 训练和测试
上述修改结束后可以训练
python projects/OneNet/train_net.py --num-gpus 1 --config-file projects/OneNet/configs/onenet.res18.nodcn.yaml
5 附件脚本
voc_data_process.py
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
#@File : voc_create_txt.py
#@Author : whiplash
#@Email : zhanyan_whiplash@163.com
#@License : (C)Copyright 2017-2018, Liugroup-NLPR-CASIA
#@Time : 2021/3/22 下午8:19
#@Software: PyCharm
'''
import os
import random
def pascal_voc():
total_xml = os.listdir(xml_path)
num = len(total_xml)
list_ = range(num)
train_val = int(num * trainval_percent)
train_ = int(train_val * train_percent)
trainval = random.sample(list_, train_val)
train = random.sample(trainval, train_)
ftrain_val = open(os.path.join(txt_path, 'trainval.txt'), 'w')
ftest = open(os.path.join(txt_path, 'test.txt'), 'w')
ftrain = open(os.path.join(txt_path, 'train.txt'), 'w')
fval = open(os.path.join(txt_path, 'val.txt'), 'w')
for i in list_:
name = total_xml[i][:-4] + '\n'
if i in trainval:
ftrain_val.write(name)
if i in train:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrain_val.close()
ftrain.close()
fval.close()
ftest.close()
if __name__ == '__main__':
xml_path = '/data/Dataset/工程训练数据/通用检测数据/训练数据/VOC2007/Annotations' # xml path
txt_path = '/data/Dataset/工程训练数据/通用检测数据/训练数据/VOC2007/ImageSets/Main' # save path
trainval_percent = 1
train_percent = 0.95
pascal_voc(xml_path, txt_path, trainval_percent, train_percent)