参考1_使用transform
参考2_介绍详细
参考3_classifier的使用方法
老办法:
使用caffe.net接口初始化网络,然后定义一个caffe.io.transform对图片进行预处理,然后将预处理之后的图片传递给这个网络,然后提取特征即可,缺点是transform模块设置的代码太多且难记。
net = caffe.Net(deployPrototxt, modelFile, caffe.TEST)
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # caffe.io.Transformer 是用于预处理的类。事先填写进行预处理的要求
transformer.set_transpose('data', (2,0,1)) # 将 高x宽x通道,转化为,通道x高x宽的格式
#transformer.set_mean('data', np.load(caffe_root + meanFile).mean(1).mean(1)) # mean pixel
transformer.set_raw_scale('data', 255) #像素数值恢复[0-255] ,rescale from [0,1] to [0,255]
transformer.set_channel_swap('data', (2,1,0)) # swap channels from RGB to BGR
net.blobs['data'].reshape(1, 3,224, 224)# set net to batch size of 1 如果图片较多就设置合适的batchsize
img = caffe.io.load_image(imagePath)
#print img, img.shape
img = caffe.io.resize_image(img, (224,224))
net.blobs['data'].data[...] = transformer.preprocess('data', img)#设置data层的数据,这里以单张图像为例。将读取的图像传入,获得按之前设置的预处理方式处理好的新图像(通道x高x宽)。
out = net.forward()# 让数据通过整个训练好的模型,前向传播
feature = np.float64(net.blobs['fc7'].data)
# 要注意一点的就是:Caffe中彩色图像的通道是BGR格式,图像存储是【0,255】
#
# 使用caffe.io.load_image()读进来的是RGB格式和0~1(float)
#
# 所以在进行识别之前要在transformer中设置transformer.set_raw_scale('data',255)(缩放至0~255)
#
# 以及transformer.set_channel_swap('data',(2,1,0)(将RGB变换到BGR)
#
# cv2.imread()接口读图像,读进来直接是BGR 格式and 0~255
#
# 所以不需要再缩放到【0,255】和通道变换【2,1,0】,不需要transformer.set_raw_scale('data',255)和transformer.set_channel_swap('data',(2,1,0))
- 这样fc7层的特征就被提取到feature变量中了。可以看到使用transofrmer 设置的代码很冗长,caffe官方给出了一个继承于caffe.net的函数caffe.classifer,可以省去使用transform对图片进行预处理的麻烦。
#官方定义
class Classifier(caffe.Net):
"""
Classifier extends Net for image class prediction
by scaling, center cropping, or oversampling.
Parameters
----------
image_dims : dimensions to scale input for cropping/sampling.
Default is to scale to net input size for whole-image crop.
mean, input_scale, raw_scale, channel_swap: params for
preprocessing options.
"""
def __init__(self, model_file, pretrained_file, image_dims=None,
mean=None, input_scale=None, raw_scale=None,
channel_swap=None):
#例子
net = caffe.Classifier(ref_model_file, ref_pretrained,
mean=imagenet_mean,
channel_swap=(2,1,0),
raw_scale=255,#像素数值恢复[0-255]
image_dims=(256, 256))#测试图片的维度
net = caffe.Classifier(
model_file='deploy prototxt文件路径',
pretrained_file='生成的二进制caffemodel模型的路径',
mean=np.load('均值文件的路径'),
raw_scale=255 #若使用的原始图像值在0-255,则保留该参数
) #至此,初始化caffe的分类器模型,保存到变量
#这样就可以避免使用caffe.io.transformer设置预处理
- 这样提取特征的代码就可以变为,代码简单清楚许多,并且classifier里面有一个用于快速预测的函数,因为我没有用到,所以没有写出来。
net = caffe.Classifier(deployPrototxt, modelFile,
mean=meanFile,
channel_swap=(2, 1, 0),
raw_scale=255, # 像素数值恢复[0-255]
image_dims=(256, 256)) # 测试图片的尺寸
img = caffe.io.load_image(image)
net.blobs['data'].data[...]=img
out = net.forward() # 让数据通过整个训练好的模型,前向传播
feature = np.float64(net.blobs['fc7'].data)
# !/usr/bin/evn python
# -*- coding:utf-8 -*-
# Author:zhaoliang
# usage: extract ctcloss layer feature
import glob
import os
import numpy as np
import sys
CAFFEROOT='/ai/zhaoliang/7_caffe_ocr_for_linux/jiaqian_ocr/caffe_ocr_for_linux'
sys.path.insert(0,os.path.join(CAFFEROOT,'python'))
import caffe
OUTPUT='/ai/zhaoliang/7_caffe_ocr_for_linux/jiaqian_ocr'#输出txt文件夹
ROOTPATH='/ai/zhaoliang/7_caffe_ocr_for_linux/jiaqian_ocr/testModule'#存放deploy.prototxt,和model.caffemodel的文件夹
IMAGEPATH='/ai/zhaoliang/7_caffe_ocr_for_linux/jiaqian_ocr/wrong_pre'#存放测试图片的文件夹
caffe.set_device(1)
caffe.set_mode_gpu()
def detectError(deployproto=None,modelfile=None,meanfile=None,outputfile=None):
if not os.path.exists(deployproto):
raise IOError('deploy.prototxt not found!')
if not os.path.exists(modelfile):
raise IOError('model.caffemodel not found!')
# if not os.path.exists(meanfile):
# raise IOError('mean.binaryproto not found')
if not os.path.exists(outputfile):
os.mknod(outputfile)
if __name__=='__main__':
deployproto=os.path.join(ROOTPATH,'deploy.prototxt')
modelfile=os.path.join(ROOTPATH,'model.caffemodel')
meanfile=os.path.join(ROOTPATH,'mean.npy')
outputfile=os.path.join(OUTPUT,'feature.txt')
detectError(deployproto,modelfile,meanfile,outputfile)
net = caffe.Net(deployproto,modelfile,caffe.TEST)
#图片预处理设置
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) #设定图片的shape格式(1,3,28,28)
transformer.set_transpose('data', (2,0,1)) #改变维度的顺序,由原始图片(28,28,3)变为(3,28,28)
transformer.set_mean('data', np.load(meanfile).mean(1).mean(1)) #减去均值
transformer.set_raw_scale('data', 255) # 缩放到【0,255】之间
transformer.set_channel_swap('data', (2,1,0)) #交换通道,将图片由RGB变为BGR
print "creating caffe Net success!"
imageList=glob.glob(os.path.join(IMAGEPATH,'*.jpg'))
net.blobs['data'].reshape(1,3,64,128)#改变Data层的blob的形状
print "getting image list success!"
feaList=[]
for _,image in enumerate(imageList):
img=caffe.io.load_image(image)
img = caffe.io.resize_image(img, (64,128))
img=transformer.preprocess('data',img)#转换图片的通道
net.blobs['data'].data[...]=img
out=net.forward()
feature=np.float64(net.blobs['result'].data)
refList=list(np.reshape(feature,8))
numStr=''
for loop,num in enumerate(refList):
if int(num)==-1:
continue
else :
numStr+=str(int(num)-1)
imageName=image.split('/')[-1]
feaList.append(imageName+':'+numStr+'\n')
#filters=net.params['ReLU2'][0].data
prediction=out['result'].argmax()
# print "{} 's result feature has been extracted".format(image)
print type(feature),feature.shape
with open(outputfile,'w') as f:
for _,feature in enumerate(feaList):
f.write(feature)
print "features have been written in "
print "all done!"
# -*- 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')