Caffemodel之C++修改参数

来源:互联网 发布:excel 一列数据递增 编辑:程序博客网 时间:2024/06/05 17:49

对Caffemodel的解析,更直接的说是对protobuf的解析。对Protobuf来说最重要的有三个文件,***.proto,***.pb.h,和***.pb.cc。基本的操作流程是首先写***.proto文件,然后编译出***.pb.h和***.pb.cc两个文件,我们就可以对Protobuf进行读写和修改了。
今天这里,我只想总结一下我在修改Caffemodel时遇到的一些坑,以及解决方案。
第一个也是困扰我最久的一个问题:
现象:读取层名时没有问题,但是读取层类型时会崩溃,而且这种崩溃时好时坏。
原因:在解读Caffemodel时使用了libcaffe.lib库,可能会造成解析混乱。
解决:我当时参考了这篇文章https://www.cnblogs.com/zhouyang209117/p/7218719.html,在文章的最后有如下两行代码:

编译可执行文件
g++addressbook.pb.cc read_data.cpp -o read.out-lprotobufg++addressbook.pb.cc write_data.cpp -o write.out-lprotobuf

看到这两行代码时,让我幡然醒悟,Caffemodel就是一个Protobuf文件,我们无需再依赖libcaffe.lib去解析,我之所以犯错是因为没有理解***.pb.cc文件的作用,我们需要在自己的工程里添加这个文件,使其和我们的main.cpp一起编译。搞定!,不再崩溃了。
第二个问题:怎样去修改Caffemodel里的参数?
以下面代码为例
// optional string name = 1;
inline bool has_name() const;    inline void clear_name();    static const int kNameFieldNumber = 1;    inline const ::std::string& name() const;    inline void set_name(const ::std::string& value);    inline void set_name(const char* value);    inline void set_name(const char* value, size_t size);    inline ::std::string* mutable_name();    inline ::std::string* release_name();    inline void set_allocated_name(::std::string* name);

大家在第一次,修改参数很有可能发现,我明明修改了但是为什么没有写进去呢?是因为大家没有注意到函数前后,关键字const的限制,很多函数只允许我们读,不允许我们写。如果你想写请记住两条准则1、使用指针;2、使用带”mutable_“前缀的函数。在这里只能说谷歌大神的代码太规范了。
第三个问题:原本以为Caffemodel文件不能原地修改,后来发现,修改后的参数是可以直接写回原文件的。单请记住一点,每次写完一定要执行关闭文件的操作,否则无法生效
最后给贴出一段代码:
#include <iostream>#include <string>#include <fstream>#include <istream>#include "caffe/proto/caffe.pb.h"using namespace std;int main(){GOOGLE_PROTOBUF_VERIFY_VERSION;caffe::NetParameter netparam;string model = "test.caffemodel";//ifstream caffemodel;//caffemodel.open(model, ifstream::in | ifstream::binary);ifstream caffemodel(model, ifstream::in | ifstream::binary);if (&caffemodel == NULL){cout << "The ptr of caffemodel is NULL" << endl;return 0;}if (!caffemodel.is_open()){cout << "Can not open model" << endl;return 0;}bool flag=netparam.ParseFromIstream(&caffemodel);//bool flag = ReadProtoFromBinaryFile(model, netparam);int layer_size = netparam.layer_size();cout << "layer_size = " << layer_size << endl;caffe::LayerParameter* layerparam=NULL;for (int i = 0; i < layer_size; i++){layerparam = netparam.mutable_layer(i);/*const string& layername = layerparam->name();cout << "layername: " << layername << endl;*/const string& layertype = layerparam->type();//cout << "layertype: " << layertype << endl;if (layertype == "hua"){const string& layername = layerparam->name();cout << "layername: " << layername << endl;const string& topname = layerparam->top(0);cout << "" << topname << endl;cout << "" << layerparam->type() << endl;//layerparam->Clear();//layerparam->clear_type();//layerparam->set_type("hua");//convparam = layerparam->mutable_convolution_param();//if (convparam->has_weight_filler()){//weight_f = convparam->mutable_weight_filler();//if (weight_f->has_type()){//cout << weight_f->type() << endl;;//}//}//weight_blob = layerparam->mutable_blobs(0);//cout << "N: " << weight_blob->num() << endl;//cout << "C: " << weight_blob->channels() << endl;//cout << "H: " << weight_blob->height() << endl;//cout << "W: " << weight_blob->width() << endl;//if (weight_blob->has_shape()){//BlobShape blobshape = weight_blob->shape();//cout << "N: " << blobshape.dim(0) << endl;//cout << "C: " << blobshape.dim(1) << endl;//cout << "H: " << blobshape.dim(2) << endl;//cout << "W: " << blobshape.dim(3) << endl;//}//BlobShape blobshape = weight_blob->shape();//for (int i = 0; i < (blobshape.dim(0)*blobshape.dim(1)*blobshape.dim(2)*blobshape.dim(3)); i++){//cout << "yuanshi:" << weight_blob->data(i) << endl;//weight_blob->set_data(i, 9999.0);//cout << "xiugai:" << weight_blob->data(i) << endl;//if (i == 10){//break;//}//}}}//fstream outcaffemodel("test.caffemodel",ios_base::out|ios_base::trunc|ios_base::binary);//netparam.SerializeToOstream(&outcaffemodel);caffemodel.close();//outcaffemodel.close();google::protobuf::ShutdownProtobufLibrary();return 0;}



原创粉丝点击