1.准备所需文件
在caffe/examples 新建一个文件夹
1.1 文件清单
模型:train_iter_xxxx.caffemodel
deploy.prototxt
python 均值文件:mean.npy
标签说明:labels.txt
测试图片
1.2 编写label.txt
按照标签0开始编写类别名称,如果标签不是从0开始的,一定要补齐。如果输出层的类别比总的类别大,后面也要补齐。
例如标签从1开始,分三类,但是output为6:
类别0
飞机
猫
狗
类别4
类别5
如果label.txt 的项目数和模型的output不符,在加载模型进行测试的时候会出现类似错误:
Traceback (most recent call last):
File "/home/danale/PycharmProjects/untitled/venv/modelTest.py", line 37, in <module>
print(top_k[i], labels[top_k[i]], prob[top_k[i]])
IndexError: index 7 is out of bounds for axis 0 with size 4
1.3 生成mean.npy
caffe是由c++编写的,所以需要将均值文件转化为python可以接受的类型。
由mean.binaryproto 生成 mean.npy的代码如下:
import caffe
import numpy as np
MEAN_PROTO_PATH = 'imagenet_mean.binaryproto' # 待转换的pb格式图像均值文件路径
MEAN_NPY_PATH = 'mean.npy' # 转换后的numpy格式图像均值文件路径
blob = caffe.proto.caffe_pb2.BlobProto() # 创建protobuf blob
data = open(MEAN_PROTO_PATH, 'rb' ).read() # 读入mean.binaryproto文件内容
blob.ParseFromString(data) # 解析文件内容到blob
array = np.array(caffe.io.blobproto_to_array(blob))# 将blob中的均值转换成numpy格式,array的shape (mean_number,channel, hight, width)
mean_npy = array[0] # 一个array中可以有多组均值存在,故需要通过下标选择其中一组均值
np.save(MEAN_NPY_PATH ,mean_npy)
1.4 deploy.prototxt
以Alexnet为例,deploy.txt 在bvlc_alexnet文件夹下,但是如果你在训练过程中修改了模型 train_val.prototxt,那么相应的deploy.txt 也需要修改。否则在加载模型进行测试的时候会出现类似报错:
Cannot copy param 0 weights from layer 'fc6'; shape mismatch. Source param shape is 4096 2304 (9437184); target param shape is 4096 9216 (37748736). To learn this layer's parameters from scratch rather than copying from a saved net, rename the layer. *** Check failure stack trace: *** Aborted (core dumped)
2.编写python代码进行测试
import numpy as np
import caffe
import sys
import os
caffe_root = '/home/danale/caffe/'
model_name = 'alexnet_train_iter_1200.caffemodel'
sys.path.insert(0, caffe_root+'python')
caffe.set_mode_cpu()
deploy = caffe_root + 'examples/myfile/deploy.prototxt' #deploy文件
model = caffe_root + 'examples/myfile/'+model_name #训练好的模型
img = caffe_root + 'examples/myfile/test.jpg' # 测试图片
labels_filename = caffe_root + 'examples/myfile/labels.txt' # 类别名称,将数字标签换回类别名称
mean_file = caffe_root + 'examples/myfile/mean.npy' #均值文件
#加载模型和网络
net = caffe.Net(deploy, model, caffe.TEST)
#图片预处理设置
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) #设定图片的shape格式为(1,3,28,28)
transformer.set_transpose('data', (2, 0, 1)) #改变维度的顺序 ???
transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))
transformer.set_raw_scale('data', 255)
transformer.set_channel_swap('data', (2, 1, 0)) #交换通道将图片由RGB变为BGR
im = caffe.io.load_image(img)
net.blobs['data'].data[...] = transformer.preprocess('data', im) #执行上述预处理
out = net.forward()
labels = np.loadtxt(labels_filename, str, delimiter='\t')
prob = net.blobs['prob'].data[0].flatten()
top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1]
for i in np.arange(top_k.size):
print(top_k[i], labels[top_k[i]], prob[top_k[i]])
输出结果如下所示(格式为:标签 类别名 概率):
1 six 0.947912
2 ok 0.0441954
3 xue 0.00627356
0 little 0.00161887
4 others 6.78389e-09