本小节介绍一下python的使用接口。python接口的调用需要在编译正确python接口的环境下,详见安装篇。
make pycaffe
使用python接口的draw_net.py可以将提供的网络结构画出图像。
首先,需要安装graphviz,源码安装,yum源安装,jumbo安装等等都可以。
这里讲一下源码安装。
graphviz源码安装暂留
然后安装pydot,直接使用pip安装即可
pip install pydot
然后可以使用draw_net.py来画网络图,如下
draw_net.py执行的时候带三个参数
python draw_net.py ../examples/cifar10/cifar10_quick_train_test.prototxt cifa10.png
Python接口应用的很广泛,主要是简单易用。
写一个预测数字的python代码
predict_num.py代码如下:
__author__ = 'frank'
import os
import numpy as np
import matplotlib.pyplot as plt
import sys
import caffe
caffe_root = '/home/thirdparty/caffe-master/'
import sys
sys.path.append(caffe_root + 'python')
Path = "F:/caffe/data/"
# load mean file
mean_filename = Path+'image_mean.binaryproto'
proto_data = open(mean_filename, "rb").read()
a = caffe.io.caffe_pb2.BlobProto.FromString(proto_data)
mean = caffe.io.blobproto_to_array(a)[0]
#load pretrain file
pretrained_file = Path+'lenet_iter_10000.caffemodel'
#load modle file
model_file = Path+'deploy.prototxt'
#create caffe net
numReg_net = caffe.Classifier(model_file, pretrained_file,
mean = mean,
channel_swap=(2,1,0),
raw_scale=255,
image_dims=(32, 32))
#labels
list=['0','1','2','3','4','5','6','7','8','9']
image_path = Path + 'trainData/7/7-5-IFPYM1SLG8.jpg'
test_image = caffe.io.load_image(image_path)
plt.imshow(test_image)
plt.show()
prediction = numReg_net.predict([test_image])
print 'predictions:', prediction[0] #list[prediction[0].argmax()]
print 'predicted num:', list[prediction[0].argmax()]
运行结果
predictions: [ 0. 0.5 0. 0. 0. 0. 0. 0.5 0. 0. ]
predicted num: 1
试了好几次,每次都是输出两个概率为0.5的数字。后来经过调试,发现问题在于predict函数定义为
def predict(self, inputs, oversample=True):
"""
Predict classification probabilities of inputs.
Parameters
----------
inputs : iterable of (H x W x K) input ndarrays.
oversample : boolean
average predictions across center, corners, and mirrors
when True (default). Center-only prediction when False.
Returns
-------
predictions: (N x C) ndarray of class probabilities for N images and C
classes.
"""
其中有一个默认参数oversample,如果将其值设为True,则会将图像从中心,边界取图,做镜像翻转,然后预测之后取平均值。这里做数字预测肯定是不能开启这个选项的!
修改代码为
prediction = numReg_net.predict([test_image],False)
再次运行即得到正确结果
predictions: [ 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
predicted num: 7
python接口是对函数进行了封装,这部分不使用封装好的函数,直接用python进行预测。其实本质就是Classifier和predict函数。
一个实例如下
# -*- coding:utf-8 -*-
__author__ = 'fangjin'
import numpy as np #调用numpy模块,调用名称为np
import matplotlib.pyplot as plt #调用matplotlib.pyplot模块,调用名称为plt
import sys
import caffe
ImageEqulity_root = 'D:/data/' #caffe根目录
model_file = ImageEqulity_root + 'lenet_deploy.prototxt' #CaffeNet网络结构
pretrained = ImageEqulity_root + 'lenet_iter_10000.caffemodel' #参数文件
image_file = ImageEqulity_root+'testData/4/4-3-0Z5FN38C0Q.jpg' #测试数据
mean_filename = ImageEqulity_root + 'image_mean.binaryproto'
#npload = ImageEqulity_root + '/python/caffe/imagenet/ilsvrc_2012_mean.npy' #计算平均值
# 显示图像模块
plt.rcParams['figure.figsize'] = (10, 10) # 显示图标大小为10
plt.rcParams['image.interpolation'] = 'nearest' # 图形差值以最近为原则
plt.rcParams['image.cmap'] = 'gray' #背景颜色为灰色
IMAGE_SIZE = (32, 32)
MEAN_VALUE = 128
caffe.set_mode_cpu()
net = caffe.Net(model_file, pretrained, caffe.TEST)
proto_data = open(mean_filename, "rb").read()
a = caffe.io.caffe_pb2.BlobProto.FromString(proto_data)
mean = caffe.io.blobproto_to_array(a)[0]
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
# transformer.set_channel_swap('data',(2,1,0)) # 参考模型通道为BGR,需转换成RGB,括号中的数字表示排列顺序
#transformer.set_mean('data', np.array([MEAN_VALUE]))
#transformer.set_mean('data', mean)
transformer.set_raw_scale('data', 255)
image = caffe.io.load_image(image_file, True)
# net.blobs['data'].reshape(1, 3, 100, 100)
# net.blobs['data'].reshape(1, 3, *IMAGE_SIZE) # reshaoe
transformed_image = transformer.preprocess('data',image)#读取文件
net.blobs['data'].data[...]=transformed_image
out = net.forward()
score = out['prob'][0]
num_list=['0','1','2','3','4','5','6','7','8','9']
print "Predicted class is : " ,score
print 'predicted num:', num_list[score.argmax()]
主要是定义了一个Transformer,对图像进行预处理。然后通过out = net.forward()
进行前向计算,之后score = out['prob'][0]
输出prob层的结果就可以了,因为只有一张图像,所以是out['prob'][0]
。