Caffemodel之C++修改参数

对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-lprotobuf g++ 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;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值