原
使用caffe的python接口进行特征提取和人脸验证
近期使用caffe模型进行人脸识别时,需要提取指定网络层中的数据进行特征比较,常见的比如提取全连接层等。本文基于caffe的python接口实现了一个简单的特征提取及人脸验证测试。测试使用的数据是LFW官网的6000对图片
本文主要参考caffe官网的例子:
Image Classification and Filter Visualization
具体内容见代码注释: feature_extract_and_evaluate.py
# -*- coding: utf-8 -*-
"""
Created on Tue. Mar 07 16:59:55 2017
@author: wujiyang
@brief:读取lfw数据库6000对人脸数据进行精确度验证
"""
import numpy as np
import matplotlib.pyplot as plt
import os
import sys
import sklearn
import sklearn.metrics.pairwise as pw
caffe_root = '/home/wujiyang/caffe/'
sys.path.insert(0, caffe_root + 'python')
import caffe
#图片库路径,若label.txt中使用的是绝对路径,则无需修改
imageBasePath = ''
#模型初始化相关操作
def initilize():
print 'model initilizing...'
deployPrototxt = "./vgg-face-deploy.prototxt"
modelFile = "./vgg-face.caffemodel"
caffe.set_mode_gpu()
caffe.set_device(0)
net = caffe.Net(deployPrototxt, modelFile,caffe.TEST)
return net
#读取图像标签
def readImagelist(labelFile):
'''
@brief:从列表文件中,读取图像数据到矩阵文件中
@param: labelfile 图像列表文件
@return :需要对比的图片路径,以及是否为同一个人的标记
labelfile的格式说明:每一行的数据如下所示,左边分别为要对比的图片,右边为是否是同一个人的标记
同一个表示为1,不同人表示为0
img1 img2 label
'''
file = open(labelFile)
lines = file.readlines()
file.close()
left = []
right = []
labels = []
for line in lines:
path = line.strip('\n').split('\t')
#read left image
left.append(path[0])
#read right image
right.append(path[1])
#read label
labels.append(int(path[2]))
assert(len(left) == len(right))
assert(len(right) == len(labels))
return left, right, labels
#特征提取,使用caffe的io接口
def extractFeature(leftImageList, rightImageList, net):
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # create transformer for the input called 'data'
transformer.set_transpose('data', (2,0,1)) # move image channls to outermost dimension
#transformer.set_mean('data', np.load(caffe_root + meanFile).mean(1).mean(1)) # mean pixel
transformer.set_raw_scale('data', 255) # rescale from [0,1] to [0,255]
transformer.set_channel_swap('data', (2,1,0)) # swap channels from RGB to BGR
# set net to batch size of 1 如果图片较多就设置合适的batchsize
net.blobs['data'].reshape(1, 3,224, 224)
leftfeature = []
rightfeature = []
for i in range(len(leftImageList)):
#分别读取左右列图像数据
#读取左边图像,并提取特征
imageleft = os.path.join(imageBasePath, leftImageList[i])
img = caffe.io.load_image(imageleft)
#print imageleft, img.shape
img = caffe.io.resize_image(img, (224,224))
#print imageleft, img.shape
net.blobs['data'].data[...] = transformer.preprocess('data', img)
#print net.blobs['data'].data.shape
out = net.forward()
#featureleft = np.float64(out['fc7'])
#print featureleft.shape
feature = np.float64(net.blobs['fc7'].data)
#print feature, type(feature)
leftfeature.append(feature)
#读取右边图像,并提取特征
imageright = os.path.join(imageBasePath, rightImageList[i])
img = caffe.io.load_image(imageright)
img = caffe.io.resize_image(img, (224,224))
net.blobs['data'].data[...] = transformer.preprocess('data', img)
out = net.forward()
feature = np.float64(net.blobs['fc7'].data)
rightfeature.append(feature)
return leftfeature, rightfeature #list
#计算精确度
def calculate_accuracy(distance, labels, num):
'''
#计算识别率,
选取阈值,计算识别率
'''
accuracy = {}
predict = np.empty((num,))
threshold = 0.1
while threshold <= 0.9 :
for i in range(num):
if distance[i] >= threshold:
predict[i] = 0
else:
predict[i] = 1
predict_right =0.0
for i in range(num):
if predict[i] == labels[i]:
predict_right += 1.0
current_accuracy = (predict_right / num)
accuracy[str(threshold)] = current_accuracy
threshold = threshold + 0.001
#将字典按照value排序
temp = sorted(accuracy.items(), key = lambda d:d[1], reverse = True)
highestAccuracy = temp[0][1]
thres = temp[0][0]
return highestAccuracy, thres
#绘制roc曲线
def draw_roc_curve(fpr,tpr,title='cosine',save_name='roc_lfw'):
#绘制roc曲线
plt.figure()
plt.plot(fpr, tpr)
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic using: '+title)
plt.legend(loc="lower right")
plt.show()
#plt.savefig(save_name+'.png')
if __name__ == '__main__':
#模型初始化
net = initilize()
#读取文件列表
print "reading imagelist..."
leftImageList, rightImageList, labels = readImagelist('tmp.txt')
#提取特征
print "feature extracting..."
leftfeature_list, rightfeature_list = extractFeature(leftImageList, rightImageList, net)
#将特征list变为2维ndarray
leftfeature = np.reshape(leftfeature_list,(len(labels),4096))
rightfeature = np.reshape(rightfeature_list,(len(labels),4096))
#print leftfeature.shape, rightfeature.shape
#print leftfeature, type(leftfeature)
#进行距离计算 cosine距离
print "computing distance..."
dis = pw.pairwise_distances(leftfeature, rightfeature, metric='cosine')
distance = np.empty((len(labels),))
for i in range(len(labels)):
distance[i] = dis[i][i]
print 'Distance before normalization:\n', distance
print 'Distance max:', np.max(distance), 'Distance min:', np.min(distance), '\n'
#距离需要归一化到0-1,与标签0-1匹配
distance_norm = np.empty((len(labels),))
for i in range(len(labels)):
distance_norm[i] = (distance[i]-np.min(distance))/(np.max(distance)-np.min(distance)) #此处计算时会有误差产生,理论上应该有1的,然而却没有!
print 'Distance after normalization:\n', distance_norm
print 'Distance_norm max:', np.max(distance_norm), 'Distance_norm min:', np.min(distance_norm), '\n'
#根据label和distance_norm计算精确度
highestAccuracy, threshold = calculate_accuracy(distance_norm,labels,len(labels))
print ("The highest accuracy is : %.4f, and the corresponding threshold is %s \n"%(highestAccuracy, threshold))
#绘制roc曲线
fpr, tpr, thresholds = sklearn.metrics.roc_curve(labels, distance_norm)
draw_roc_curve(fpr, tpr, title='cosine',save_name='lfw_evaluate')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
此脚本也可在我的github上找到 caffe-test-script