在实际的生产环境中,有时候我们需要caffe模型转换为TensorFlow模型用于部署,甚至支持手机端(主要由于tensorflow有c++、python 的api支持手机端)。本文主要是介绍开源库caffe-tensorflow的使用。
python2版本:https://github.com/ethereon/caffe-tensorflow
python3版本:https://github.com/dhaase-de/caffe-tensorflow-python3
环境
- Python 2.7 (required by caffe-tensorflow)
- TensorFlow 1.x installed (tested with TensorFlow 1.9)
- caffe(no need,but required if convert the mean files)
转换过程
可以参考examples/mnist中转换示例,本文以转换一个年龄预测的模型为例:
1、convert a prototxt model to tensorflow code::
python ./convert.py /path/to/age.prototxt --code-output-path=age_net.py
生成的age_net.py如下:
from network import Network
class AgeNet(Network):
def setup(self):
(self.feed('data')
.conv(3, 3, 64, 1, 1, name='conv1_1')
.conv(3, 3, 64, 1, 1, name='conv1_2')
.max_pool(2, 2, 2, 2, name='pool1')
.conv(3, 3, 128, 1, 1, name='conv2_1')
.conv(3, 3, 128, 1, 1, name='conv2_2')
.max_pool(2, 2, 2, 2, name='pool2')
.conv(3, 3, 256, 1, 1, name='conv3_1')
.conv(3, 3, 256, 1, 1, name='conv3_2')
.conv(3, 3, 256, 1, 1, name='conv3_3')
.max_pool(2, 2, 2, 2, name='pool3')
.conv(3, 3, 512, 1, 1, name='conv4_1')
.conv(3, 3, 512, 1, 1, name='conv4_2')
.conv(3, 3, 512, 1, 1, name='conv4_3')
.max_pool(2, 2, 2, 2, name='pool4')
.conv(3, 3, 512, 1, 1, name='conv5_1')
.conv(3, 3, 512, 1, 1, name='conv5_2')
.conv(3, 3, 512, 1, 1, name='conv5_3')
.max_pool(2, 2, 2, 2, name='pool5')
.fc(4096, name='fc6')
.fc(4096, name='fc7')
.fc(101, relu=False, name='fc8-101')
.softmax(name='prob'))
2、convert .caffemodel weight files to .npy files
python ./convert.py /path/to/age.prototxt --caffemodel /path/to/age_iter_300000.caffemodel --data-output-path=age_model.npy
3、Convert the model and the mean file
此步骤需要caffe环境,我的实验没有这步骤,如果有需要可以参考示例如下:
来源参考:https://blog.wildcat.io/2018/04/a-simple-tutorial-about-caffe-tensorflow-model-conversion/
import caffe
import numpy as np
import sys
if len(sys.argv) != 3:
print("Usage: python convert_protomean.py proto.mean out.npy")
blob = caffe.proto.caffe_pb2.BlobProto()
data = open('./original-caffe-models/DB_train_w32_5.binaryproto', 'rb').read()
blob.ParseFromString(data)
arr = np.array(caffe.io.blobproto_to_array(blob))
out = arr[0]
np.save('mean.npy', out)
预测阶段
在预测阶段只需要四个文件即可
age_model.npy(生成的model文件)
network.py(来源于caffe-tensorflow/kaffe/tensorflow/network.py)
age_net.py(生成的网络文件)
age_predict.py(预测文件,可以参考examples/imagenet/classify.py,亦可参考代码如下)
#coding=utf-8
import os,cv2,time
from age_net import AgeNet
import numpy as np
import tensorflow as tf
class AgePredict:
model_data_path = r'face_age/age_model.npy'
def __init__(self):
self.input_node = tf.placeholder(tf.float32,shape=(None, 224, 224, 3))
self.net = AgeNet({'data': self.input_node})
self.sess = tf.Session()
with self.sess.as_default():
# Load the converted parameters
print('Loading the model')
self.net.load(self.model_data_path, self.sess)
def predict(self, im):
img = cv2.resize(im,(224,224),cv2.INTER_NEAREST)
img = img.astype(np.float32, copy=True)
img -= np.array([[[104, 117, 123]]])
output_prob = self.sess.run(self.net.get_output(), feed_dict={self.input_node: [img]})
age = 0
for idx, prob in enumerate(output_prob[0]):
age += idx * prob
return int(age)
def main(self):
pic_path = 'data/test_image.jpg'
img = cv2.imread(pic_path)
print(self.predict(img))
if __name__ == '__main__':
agePredict = AgePredict()
agePredict.main()