看了一些博客,要读取caffe模型数据(caffemodel格式),都需要编译caffe。
编译caffe除了 caffe-master 外还要 boost、OpenCV、OpenBlas、glog、leveldb、protobuf 等,好象还只支持64位。
所以,这里不准备完全编译caffe,只用caffe中和模型相关的一部分。
《tensorflow2caffe(1) : caffemodel解析,caffemodel里面到底记录了什么?》这篇文章最简单,就以它为参考进行。
流程:
1。下载 caffe-master (我这个不知道是什么版本)和 对应的protobuf(我这里是2.6.1)
2。编译其中的 libprotobuf(有个vs2005工程,可以自动转换到2008),生成libprotobuf.lib,并加入工程中
3。按本文包含部分caffe cpp
把ReadProtoFromBinaryFile 和WriteProtoToTextFile 复制过来,由于只有一个cpp,并很小,就看代码吧
//先用ReadProtoFromBinaryFile函数将二进制文件读入proto里面,再将proto文件写入txt文件就行了。
#define CPU_ONLY 1
#include "google/protobuf/io/coded_stream.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <algorithm>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <iostream>
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "D:/caffe-master/src/caffe/proto/caffe.pb.cc"
using namespace caffe;
using namespace std;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::Message;
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/importer.cc>
using google::protobuf::compiler::DiskSourceTree;
//这个函数里面就使用了open函数,和一些底层的google::protobuf的数据流。在这里我们其实就明白,是先把二进制文件(caffemodel)转化成文件流,再放入proto里面。
bool ReadProtoFromBinaryFile(const char* filename, Message* proto) {
#if defined (_MSC_VER) // for MSC compiler binary flag needs to be specified
int fd = open(filename, O_RDONLY | O_BINARY);
#else
int fd = open(filename, O_RDONLY);
#endif
//CHECK_NE(fd, -1) << "File not found: " << filename;
if(fd==-1)
printf("文件没有找到,请检查名称和路径: %s",filename);
ZeroCopyInputStream* raw_input = new FileInputStream(fd);
CodedInputStream* coded_input = new CodedInputStream(raw_input);
const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte.
coded_input->SetTotalBytesLimit(kProtoReadBytesLimit, 536870912);
bool success = proto->ParseFromCodedStream(coded_input);
delete coded_input;
delete raw_input;
close(fd);
return success;
}
void WriteProtoToTextFile(const Message& proto, const char* filename) {//写文本文件
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
FileOutputStream* output = new FileOutputStream(fd);
google::protobuf::TextFormat::Print(proto, output);//CHECK()
delete output;
close(fd);
}
int main()
{
//,NetParameter继承了实际是一个Message,Message是proto类型的
NetParameter proto;
ReadProtoFromBinaryFile("D:/Super-Resolution-master/FSRCNN/snapshot/snapshot_iter_2546000.caffemodel", &proto);//读
WriteProtoToTextFile(proto, "D:/Super-Resolution-master/FSRCNN/fscrcnn_caffemodel.txt");//写
return 0;
}
这里用FSRCNN的caffemodel来测试,马上生成一个fscrcnn_caffemodel.txt
name: "fsrcnn"
layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
phase: TRAIN
hdf5_data_param {
source: "./train.txt"
batch_size: 64
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
blobs {
data: -0.26126936
data: -0.029898185
data: 0.34117496
data: -0.11990144
data: 0.004115283
...这里略过1000多行
shape {
dim: 56
dim: 1
dim: 5
dim: 5
}
}
blobs {
data: -0.07148654
data: -0.023211269
data: -0.0055909543
data: -0.018043369
这里只是一部分。
完成。
为了转换方便,重新修改main:
//把caffemodel 拖到该程序上,在同一个文件夹中,生成 "原名.txt"文本文件
int main(int argc, char *argv[])
{
char modelName[256];
if( argc == 2 )
strcpy(modelName, argv[1]);
else
strcpy(modelName, "D:/Super-Resolution-master/FSRCNN/snapshot/snapshot_iter_2546000.caffemodel");//
//,NetParameter继承了实际是一个Message,Message是proto类型的
NetParameter proto;
ReadProtoFromBinaryFile(modelName, &proto);//读
strcat(modelName,".txt");//名称就是原名 + ".txt"
WriteProtoToTextFile(proto, modelName);//写
return 0;
}
这样,只要把caffemodel 拖到该程序上,在同一个文件夹中,就会生成一个文本文件。
我试了几个《从SRCNN到EDSR,总结深度学习端到端超分辨率方法发展历程 - CSDN博客》的几个模型,可以转换。
下载:
win32中转换caffemodel数据到文本方式的程序
地址: