转载博客:https://blog.csdn.net/chenriwei2/article/details/49706563
实验过程:
数据准备
由于港中文[1]他们有公开了训练集,所以我们就可以直接使用他们提供的图像库就好了。
数据是需要转化的:
1、框出人脸图像部分,从新计算关键点的坐标
2、缩放人脸框大小,同时更新计算的关键点坐标
3、一些数据增强处理:我只采样了左右对称的增强方法(还可以采用的数据增强方法有旋转图像,图像平移部分)
转换脚本如下:
略
数据转化
跟以往的图像分类采用LMDB或者LevelDB 作为数据处理不同,这里我们的标签是一个向量,而不是一个值,所以不能直接用LMDB来作为存储,还好,caffe提供了另外一种数据存储方法来处理这种需求,那就是HDF5, 直观的差别就在于LMDB的标签是一个数,而HDF5 的标签可以是任意(blob),也就是说对于分类任务,我们也可以采样HDF5作为存储的数据模式,但是HDF5直接读取文件,相比LMDB 速度上有所损失。
脚本如下:
import os
import random
import h5py
import numpy as np
from skimage import io
from skimage import transform as tf
trainpairlist=''
testpairlist=''
def save2hdf5(X,Y,filename):
with h5py.File(filename, 'w') as f:
f['data'] = X
f['label'] = Y
print 'having saving a hdf5 file !'
def convert(source_path,pairlist,savepath,hdf5list,w,h):
'''
@brief: 将图像列表里的图像转化为矩阵,
@return: X,Y
'''
step = 5000
fid=open(pairlist)
lines= fid.readlines()
fid.close()
X=np.empty((step,3,w,h),dtype=np.float)
Y=np.empty((step,10,1,1),dtype=np.float)
i=0
t=1
#记得HDF5需要实现shuffle.
random.shuffle(lines)
for line in lines:
words=line.split('\t')
inputimage=words[0]
#image 标签
points = np.zeros((10,))
points[0]=float(words[1])
points[1]=float(words[2])
points[2]=float(words[3])
points[3]=float(words[4])
points[4]=float(words[5])
points[5]=float(words[6])
points[6]=float(words[7])
points[7]=float(words[8])
points[8]=float(words[9])
points[9]=float(words[10])
im=io.imread(source_path+inputimage,as_grey=False)
im=tf.resize(im,(w,h))
X[i,0,:,:]=im[:,:,0]
X[i,1,:,:]=im[:,:,1]
X[i,2,:,:]=im[:,:,2]
Y[i,:,0,0]=points
i=i+1
if i==step:
filename = os.path.join(savepath, str(t)+ '.h5')
save2hdf5(X,Y,filename)
with open(os.path.join(savepath,hdf5list), 'a') as f:
f.write(filename + '\n')
i=0
t=t+1
if i > 0:
filename = os.path.join(savepath, str(t)+ '.h5')
save2hdf5(X[0:i,:,:,:],Y[0:i,:,:,:],filename)
with open(os.path.join(savepath,hdf5list), 'a') as f:
f.write(filename + '\n')
if __name__=='__main__':
w=39
h=39
source_path = '/media/crw/MyBook/MyDataset/FacePoint/train39X39/'
save_path = '/media/crw/MyBook/TrainData/HDF5/FacePoint/10000_39X39/train/'
hdf5list='/media/crw/MyBook/TrainData/HDF5/FacePoint/10000_39X39/train/train.txt'
filelist = '/media/crw/MyBook/MyDataset/FacePoint/train39X39/train.list'
convert(source_path,filelist,save_path,hdf5list,w,h)
source_path = '/media/crw/MyBook/MyDataset/FacePoint/test39X39/'
save_path = '/media/crw/MyBook/TrainData/HDF5/FacePoint/10000_39X39/test/'
hdf5list='/media/crw/MyBook/TrainData/HDF5/FacePoint/10000_39X39/test/test.txt'
filelist = '/media/crw/MyBook/MyDataset/FacePoint/test39X39/test.list'
convert(source_path,filelist,save_path,hdf5list,w,h)
网络结构
数据处理好之后,就可以开始设计网络结构了。
网络结构采样的是参照[1]的网络结构,相比于其它的大型的网络的特点在于:
1,输入图像小。
2,权值非共享。
这样的网络相比ImageNet 上的那些模型的优点很明显,参数比较少,学习相对快一些,
图片1:是论文中描绘的网络结构:
图片2:是caffe实现的网络结构:
需要注意的是,caffe 的master分支是没有local 层的,这个local 层去年(Caffe Local)就已经请求合并,然而由于各种原因却一直未能合入正式的版本。大家可以从上面那个链接里面clone 版本进行实验。
实验结果
正确的结果
实验分析
用深度学习来做回归任务,很容易出现回归到均值的问题,在人脸关键点检测的任务中,就是检测到的人脸点是所有值的平均值。在上面失败的例子中,两只眼睛和嘴巴预测的都比较靠近。//修正bug 过后就不会出现这个问题了。
这篇文章中,我只是尝试复现人脸关键点检测文章[1]的第一步,后面有时间的话,也会考虑用caffe 复现所有的结果。
要想完全的复现文章的结果,还需要:
1,级联,从粗到细的检测
2,训练多个网络取平均值(各个网络的输入图像块不一样)
代码托管
DeepFace GitHub 托管 欢迎提改进建议~
//update 2015.11.18:添加了数据处理的python文件