最终目标:为课题组做一个人脸打卡系统。
项目1阶段已更新完毕,如有错误请不吝赐教~
注:作为一个负责任的博主,虽然过了好几个月了,但必须要说明一下,文中代码有bug,cv2.resize时,参数输入是 宽×高×通道。
遂在inference做高斯金字塔的代码中:scale_img=cv2.resize(img,((int(img.shape[0]*scale)),(int(img.shape[1]*scale))))
更改为:scale_img=cv2.resize(img,((int(img.shape[1]*scale)),(int(img.shape[0]*scale))))。
同时作为一个懒惰的博主,这只是个入门,弄着玩的所以懒得再把测试的地方重新修改博客了,反正修改bug后结果是挺好的。
2019.3.20
项目1阶段:基于Alexnet的人脸检测
项目环境及配置:Window10+GTX 1060+Python3.6+Anaconda5.2.0+Tensorflow1.9+gpu
1、数据获取
人脸数据网上的资源非常非常的多,如下附上了几个获取数据的网站。在下载和查找数据的时候需要同时百度一下这个数据的使用方法,如:原始图片在哪,含有标注的.txt文件或.mat文件都在哪等,否则自己瞎搞很容易浪费时间。
这两个链接包含了大多数开源的人脸数据
http://www.cvmart.net/community/article/detail/148
https://blog.csdn.net//chenriwei2/article/details/50631212
项目1阶段训练与验证使用的人脸数据集均为AFLW,如下可下载,其中aflw-images-0.tar.gz,aflw-images-2.tar.gz,aflw-images-3.tar.gz这三个文件是图片数据,windows下解压的时候把后面那个.gz删掉就可以解压了。AFLW的标注在aflw/data下的aflw.txt文件。至于标注的格式我认为是矩形框的左上角x、y坐标值和长度w高度h。
AFLW:https://pan.baidu.com/s/14McWGRZCnOcP2SBhK2ryrQ
非人脸数据截取于人脸数据,具体截取代码见后文。
2、数据集制作
本项目数据集使用Tensorflow的TFRecord格式,比较方便。
首先要从ALFW数据集种截取出人脸图片和非人脸图片,ALFW总共有21123张图片。25000多张人脸,我要做出人脸和非人脸数据训练集规模1:3,5W人脸对15万非人脸,测试集规模1:1,2W人脸和2万非人脸,此程序运行完人脸图片可得到7.2W张左右,非人脸可得到17.2W张左右。
正常的流程此时需要引入IoU的概念。
IoU代码如下:
def IoU(box,boxes):
"""
box为实际,boxes为人脸
"""
face_area=boxes[:,2]*boxes[:,3]
actual_area=(box[2]-box[0])**2
x1=np.maximum(box[0],boxes[:,0])
y1=np.maximum(box[1],boxes[:,1])
x2=np.minimum(box[2],boxes[:,2]+boxes[:,0])
y2=np.minimum(box[3],boxes[:,3]+boxes[:,1])
w=np.maximum(0,x2-x1+1)
h=np.maximum(0,y2-y1+1)
inter_area=w*h
return inter_area/(face_area+actual_area-inter_area)
由于ALFW的标注非常烦人,一张图片内有几张人脸,可是他的标注是一个个给出的,还好一张图片的几乎都是挨着的,运行了3638.5秒,设定的阈值IoU<0.3为非人脸样本,IoU>0.65为人脸样本。
制作数据集代码如下:
import os
import cv2
import time
import numpy as np
from numpy.random import randint
import random
def gen_pic(path,boxes,j,k):
img=cv2.imread(path)
if img is None:
return j,k
h1,w1,_=img.shape
if(min(w1,h1)<=210):
return j,k
num=8
while(num):
size=randint(100,min(w1,h1)/2)
x1=randint(1,w1-size)
y1=randint(1,h1-size)
box=np.array([x1,y1,x1+size,y1+size])
_boxes=boxes.copy()
if(np.max(IoU(box,np.array(_boxes)))<0.3):
resize_img=cv2.resize(img[y1:y1+size,x1:x1+size,:],(224,224))
cv2.imwrite('E:\\friedhelm\\Data\\Alexnet_data\\non-face\\non_face_%d.jpg'%(j),resize_img)
j=j+1
num=num-1
for bbox in boxes:
x=max(bbox[0],0)
y=max(bbox[1],0)
w=max(bbox[2],0)
h=max(bbox[3],0)
num=2
while(num):
size=randint(np.floor(0.5*min(w,h))+1,np.ceil(1.5*max(w,h))+2)
x1=randint(np.floor(0.5*x)+1,np.ceil(1.5*x)+2)
y1=randint(np.floor(0.5*y)+1,np.ceil(1.5*y)+2)
box=np.array([x1,y1,x1+size,y1+size])
_bbox=np.array(bbox).reshape(1,-1)
if(IoU(box,_bbox)>0.65):
resize_img=cv2.resize(img[y1:y1+size,x1:x1+size,:],(224,224))
cv2.imwrite('E:\\friedhelm\\Data\\Alexnet_data\\face\\face_%d.jpg'%(k),resize_img)
k=k+1
if(random.choice([0,1])):
resize_img=cv2.flip(resize_img,1)
cv2.imwrite('E:\\friedhelm\\Data\\Alexnet_data\\face\\face_%d.jpg'%(k),resize_img)
k=k+1
num=num-1
return j,k
def IoU(box,boxes):
"""
box为实际,boxes为人脸
"""
face_area=boxes[:,2]*boxes[:,3]
actual_area=(box[2]-box[0])**2
x1=np.maximum(box[0],boxes[:,0])
y1=np.maximum(box[1],boxes[:,1])
x2=np.minimum(box[2],boxes[:,2]+boxes[:,0])
y2=np.minimum(box[3],boxes[:,3]+boxes[:,1])
w=np.maximum(0,x2-x1+1)
h=np.maximum(0,y2-y1+1)
inter_area=w*h
return inter_area/(face_area+actual_area-inter_area)
def main():
begin=time.time()
addr='E:\\friedhelm\\AFLW\\'
with open(r'E:\friedhelm\alfw.txt') as f:
j=0
k=0
boxes=[]
path_compare="1"
for line in f.readlines():
line=line.strip().split()
path=addr+line[0]
x=int(line[1])
if x<0:x=0
y=int(line[2])
if y<0:y=0
w=int(line[3])
h=int(line[4])
if(path_compare==path):
boxes.append([x,y,w,h])
else:
if(path_compare!="1"):
j,k=gen_