训练⾃⼰的数据_PyTorch版CenterNet训练⾃⼰的数据集CenterNet(Objects as points)已经有⼀段时间了,之前这篇⽂章-【⽬标检测Anchor-Free】CVPR 2019 Object as
Points(CenterNet)中讲解了CenterNet的原理,可以回顾⼀下。
这篇博⽂主要讲解如何⽤这个版本的CenterNet训练⾃⼰的VOC数据集,环境的配置。
1. 环境配置
2. 配置⾃⼰的数据集
2.1 VOC类别修改
2.2 annotations
2.3 其他
3. 训练和测试
3.1 训练命令
3.2 测试命令
4. 结果
COCO:
PascalVOC:
5. 参考
1. 环境配置
环境要求:
python>=3.5
pytorch==0.4.1or 1.1.0 or 1.0.0(笔者⽤的1.0.0也可以)
tensorboardX(可选)
配置:
1. 将cudnn的batch norm关闭。打开torch/nn/functional.py⽂件,到torch.batch_norm这⼀⾏,
将torch.abled选项更改为False。
2. 克隆项⽬
CenterNet_ROOT=/path/to/clone/CenterNet
git clone github/zzzxxxttt/pytorch_simple_CenterNet_45 $CenterNet_ROOT
3. 安装cocoAPI
cd $CenterNet_ROOT/lib/cocoapi/PythonAPI
make
python setup.py install --user
4. 编译可变形卷积DCN
如果使⽤的是pytorch0.4.1, 将$CenterNet_ROOT/lib/DCNv2_old 重命名为 $CenterNet_ROOT/lib/DCNv2
如果使⽤的是pytorch1.1.0 or 1.0.0, 将$CenterNet_ROOT/lib/DCNv2_new 重命名为 $CenterNet_ROOT/lib/DCNv2.
然后开始编译
cd $CenterNet_ROOT/lib/DCNv2
./make.sh
5. 编译NMS
cd $CenterNet_ROOT/lib/nms
make
6.
7. 对于Pascal VOC格式的数据集,下载VOC转为COCO以后的数据集:
密码:4iu2
下载以后将annotations, images, VOCdevkit放在$CenterNet_ROOT/data/voc
PS:以上两者是官⽅数据集,如果制作⾃⼰的数据集的话可以往下看。
8. 如果选择Hourglass-104作为⾻⼲⽹络,下载CornerNet提供的Hourglass预训练模型:
密码:y1z4
将下载的权重checkpoint.t7放到$CenterNet_ROOT/ckpt/pretrain中。
2. 配置⾃⼰的数据集
这个版本提供的代码是针对官⽅COCO或者官⽅VOC数据集进⾏配置的,所以有⼀些细节需要修改。由于笔者习惯VOC格式数据集,所以以Pascal VOC格式为例,修改⾃⼰的数据集。
笔者只有⼀个类,‘dim target’,所以按照⼀个类来修改,其他的类别也很容易修改。
2.1 VOC类别修改
将datasets/pascal.py中16⾏内容:
VOC_NAMES = ['__background__', "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
"horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
"train", "tvmonitor"]
修改为⾃⼰类别的名称:
VOC_NAMES = ['__background__', 'dim target']
将datasets/pascal.py中第33⾏内容:
num_classes=20修改为⾃⼰对应的类别个数num_classes=1
将datasets/pascal.py中的第35⾏内容:
self.valid_ids = np.arange(1, 21, dtype=np.int32)中的21修改为类别数⽬+1
2.2 annotations
VOC格式数据集中没有annotations中所需要的json⽂件,这部分需要重新构建。
下⾯是⼀个VOC转COCO格式的脚本,需要改xml path和json file的名称。
ElementTree as ET
import os
import json
coco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []
category_set = dict()
image_set = set()
category_item_id = 0
image_id = 20200000000
annotation_id = 0
def addCatItem(name):
global category_item_id
category_item = dict()
category_item['supercategory'] = 'none'
category_item_id += 1
category_item['id'] = category_item_id
category_item['name'] = name
coco['categories'].append(category_item)
category_set[name] = category_item_id
return category_item_id
def addImgItem(file_name, size):
global image_id
if file_name is None:
raise Exception('Could not find filename tag in xml file.')
if size['width'] is None:
raise Exception('Could not find width tag in xml file.')
if size['height'] is None:
raise Exception('Could not find height tag in xml file.')
image_id += 1
image_item = dict()
image_item['id'] = image_id
image_item['file_name'] = file_name
image_item['width'] = size['width']
image_item['height'] = size['height']
coco['images'].append(image_item)
image_set.add(file_name)
return image_id
def addAnnoItem(object_name, image_id, category_id, bbox):
global annotation_id
annotation_item = dict()
annotation_item['segmentation'] = []
seg = []
#bbox[] is x,y,w,h
#left_top
seg.append(bbox[0])
seg.append(bbox[1])
#left_bottom
seg.append(bbox[0])
seg.append(bbox[1] + bbox[3])
#right_bottom
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1] + bbox[3])
#right_top
#right_top
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1])
annotation_item['segmentation'].append(seg)
annotation_item['area'] = bbox[2] * bbox[3]
annotation_item['iscrowd'] = 0
annotation_item['ignore'] = 0
annotation_item['image_id'] = image_id
annotation_item['bbox'] = bbox
annotation_item['category_id'] = category_id
annotation_id += 1
annotation_item['id'] = annotation_id
coco['annotations'].append(annotation_item)
def parseXmlFiles(xml_path):
for f in os.listdir(xml_path):
if dswith('.xml'):
continue
real_file_name = f.split(".")[0] + ".jpg"
bndbox = dict()
size = dict()
current_image_id = None
current_category_id = None
file_name = None
size['width'] = None
size['height'] = None
size['depth'] = None
xml_file = os.path.join(xml_path, f)
print(xml_file)
tree = ET.parse(xml_file)
root = t()
if root.tag != 'annotation':
raise Exception(
'pascal voc xml root element should be annotation, rather than {}'                .format(root.tag))
#elem is , , ,
for elem in root:
current_parent = elem.tag
current_sub = None
object_name = None
if elem.tag == 'folder':
continue
if elem.tag == 'filename':
file_name = real_file_name  #
if file_name in category_set:
raise Exception('file_name duplicated')
#add img item only after parse  tag
elif current_image_id is None and file_name is not None and size[                    'width'] is not None:
# print(file_name, "===", image_set)
if file_name not in image_set:
current_image_id = addImgItem(file_name, size)
print('add image with {} and {}'.format(file_name, size))
else:
pass
# raise Exception('duplicated image: {}'.format(file_name))
# raise Exception('duplicated image: {}'.format(file_name))
#subelem is , , , ,
for subelem in elem:
bndbox['xmin'] = None
bndbox['xmax'] = None
bndbox['ymin'] = None
bndbox['ymax'] = None
current_sub = subelem.tag
if current_parent == 'object' and subelem.tag == 'name':
object_name =
if object_name not in category_set:
current_category_id = addCatItem(object_name)
else:
current_category_id = category_set[object_name]
elif current_parent == 'size':
python处理xml文件if size[subelem.tag] is not None:
raise Exception('xml structure broken at size tag.')
size[subelem.tag] = )
#option is , , , , when subelem is
for option in subelem:
if current_sub == 'bndbox':
if bndbox[option.tag] is not None:
raise Exception(
'xml structure corrupted at bndbox tag.')
bndbox[option.tag] = )
#only after parse the  tag
if bndbox['xmin'] is not None:
if object_name is None:
raise Exception('xml structure broken at bndbox tag')
if current_image_id is None:
raise Exception('xml structure broken at bndbox tag')
if current_category_id is None:
raise Exception('xml structure broken at bndbox tag')
bbox = []
#x
bbox.append(bndbox['xmin'])
#y
bbox.append(bndbox['ymin'])
#w
bbox.append(bndbox['xmax'] - bndbox['xmin'])
#h
bbox.append(bndbox['ymax'] - bndbox['ymin'])
print('add annotation with {},{},{},{}'.format(
object_name, current_image_id, current_category_id,
bbox))
addAnnoItem(object_name, current_image_id,
current_category_id, bbox)
if __name__ == '__main__':
xml_path = './annotations/test'
json_file = './pascal_test2020.json'
#'./pascal_trainval0712.json'
parseXmlFiles(xml_path)
json.dump(coco, open(json_file, 'w'))
注意这⾥json⽂件的命名要通过datasets/pascal.py中第44到48⾏的内容确定的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。