使用caffe的python接口进行特征提取和人脸验证,修改代码dis=1-dis 使用caffe的python接口进行特征提取和人脸验证

使用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

猜你喜欢

转载自blog.csdn.net/m0_37192554/article/details/85003866