YOLO,是You Only Look Once的缩写,一种基于深度卷积神经网络的物体检测算法,YOLO v3是YOLO的第3个版本,检测算法更快更准。
本文源码:https://github.com/SpikeKing/keras-yolo3-detection
欢迎Follow我的GitHub:https://github.com/SpikeKing
YOLO v3已经提供 COCO(Common Objects in Context)数据集的模型参数。我们可以把COCO的模型参数作为预训练参数,再结合已有的数据集,创建自己的检测算法。
本例使用WIDER FACE
人脸数据,训练一个高精度的人脸检测模型。
WIDER
数据集:WIDER Face
建立时间:2015-11-19
WIDER FACE 数据集是一个人脸检测基准(benchmark)数据集,图片选取自 WIDER(Web Image Dataset for Event Recognition) 数据集。图片数 32,203 张,人脸数 393,703 个,在大小(scale)、位置(pose)、遮挡(occlusion)等不同形式中,人脸是高度变换的。WIDER FACE 数据集是基于61个事件类别,每个事件类别,随机选取训练40%、验证10%、测试50%。训练和测试含有边框(bounding box)真值(ground truth),而验证不含。
数据集在官网可以公开下载,其中在Face annotations 中,wider_face_train_bbx_gt.txt
是边框真值,数据格式如下:
0--Parade/0_Parade_marchingband_1_849.jpg
1
449 330 122 149 0 0 0 0 0 0
数据说明:
- 第1行:图片的位置和名称;
- 第2行:边框的数量;
- 第3~n行:每个人脸的边框和属性:
- 其中1~4位是
x1, y1, w, h
- blur:模糊,0清晰、1一般、2严重;
- expression:表情,0正常、1夸张;
- illumination:曝光,0正常、1极度;
- occlusion:遮挡,0无、1部分、2大量;
- pose:姿势,0正常,1非典型;
- 其中1~4位是
wider_face_val_bbx_gt.txt
与此类似。
图片数据的清晰度一般,大小不一,尺寸为1024x,宽度相同。
数据转换
为了符合训练要求,需要转换wider数据集中的边框格式,为训练要求的边框格式。
即文件路径,边框xmin,ymin,xmax,ymax,label
:
data/WIDER_val/images/10--People_Marching/10_People_Marching_People_Marching_2_433.jpg 614,346,771,568,0 245,382,392,570,0 353,222,461,390,0 498,237,630,399,0
转换源码。遍历数据文件夹,逐行解析不同格式的数据,写入文件。注意:
- 物体框,Wider的数据格式是x,y,w,h,而训练的数据格式是xmin,ymin,xmax,ymax;
- 只检测人脸一个类别,则类别索引均为0;
具体参考工程的wider_annotation.py
脚本。
def generate_train_file(bbx_file, data_folder, out_file):
paths_list, names_list = traverse_dir_files(data_folder)
name_dict = dict()
for path, name in zip(paths_list, names_list):
name_dict[name] = path
data_lines = read_file(bbx_file)
sub_count = 0
item_count = 0
out_list = []
for data_line in data_lines:
item_count += 1
if item_count % 1000 == 0:
print('item_count: ' + str(item_count))
data_line = data_line.strip()
l_names = data_line.split('/')
if len(l_names) == 2:
if out_list:
out_line = ' '.join(out_list)
write_line(out_file, out_line)
out_list = []
name = l_names[-1]
img_path = name_dict[name]
sub_count = 1
out_list.append(img_path)
continue
if sub_count == 1