先从Torch、tensorflow 等导入模型:
String t7model="mosaic.t7";//Torch
// 加载模型
dnn::Net net = cv::dnn::readNetFromTorch(t7model.c_str());
然后读出各层名称:
std::vector<String> lname=net.getLayerNames() ;
按名称得到id,:
int id=net.getLayerId(lname[i]);
按id得到各层训练参数:
Mat blob=net.getParam(id, j);
然后按caffe格式保存。
完整cpp:
//从OpenCV导出风格模型训练参数: 加载模型 -> 取得各层名和参数 -> 导出成caffe 格式
#include <opencv2\opencv.hpp>
#include <opencv2\dnn.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
//字符串是否包含子串
bool endsWith(const String &str, const char *substr)
{
int lc=str.length() - strlen(substr);
if (lc>=0)//子串<母串(长度)
{
return str.rfind(substr) == lc;
}
else//子串>母串
return false;
}
//保存一个参数,这里只有 2、4 维的情况
void save_mat (ofstream& fout,Mat& b)
{
fout <<" blobs {\n";
if(b.isContinuous()) //连续
{
float* outData=b.ptr<float>(0);
if(b.dims==2)
{
for (int i=0; i<b.size[0] * b.size[1]; ++i)
{
fout <<" data: "<<*outData++ <<endl;;
}
fout <<" shape {\n";
fout <<" dim: " <<b.size[0]<<endl;
fout <<" dim: " <<b.size[1]<<endl;
fout <<" }\n" ;
}
else if(b.dims==4)
{
for (int i=0; i<b.size[0] * b.size[1] * b.size[2] * b.size[3]; ++i)
{
fout <<" data: "<<*outData++ <<endl;;
}
fout <<" shape {\n";
fout <<" dim: " <<b.size[0]<<endl;
fout <<" dim: " <<b.size[1]<<endl;
fout <<" dim: " <<b.size[2]<<endl;
fout <<" dim: " <<b.size[3]<<endl;
fout <<" }\n" ;
}
}
else
cout<<"出错了,数据不连续!"<<endl;
fout <<" }\n";
}
//导出参数
void saveModel(dnn::Net& net,String & t7model,String & filename)//文件中的名称,文件名
{
ofstream fout (filename.c_str());
fout <<"name: \""<<t7model<<"\"\n" ; //第一行 名称
std::vector<String> lname=net.getLayerNames() ;
for (size_t i = 0; i != lname.size(); i++)
{
cout<<"层名:"<<lname[i]<<endl;
fout <<"layer {\n";
fout <<" name: \""<<lname[i]<<"\"\n" ; //层名
int id=net.getLayerId(lname[i]);
if(endsWith(lname[i], "Convolution")) //卷积层
{
fout <<" type: \"卷积\"\n";//类型
}
else if(endsWith(lname[i], "BatchNorm")) // 批归范化
{
fout <<" type: \"批归范\"\n";//类型
}
else if(endsWith(lname[i], "Deconvolution")) // 反卷积
{
fout <<" type: \"反卷积\"\n";//类型
}
//各层有没有训练参数呢?有几个?
int layerBlobs_size=10;// 如何确定有多少个训练参数呢?CV dnn中有没有什么函数可用呢?
//如何确定参数顺序呢?比如:批归范化4个(均值、方差、权重、偏移)
try //j到哪步出错,说明有几个参数
{
for (size_t j = 0; j != layerBlobs_size; j++)
{
Mat blob=net.getParam(id, j);
cout<<"dims:"<<blob.dims<<endl;
cout<<"size:"<<blob.size<<endl;
save_mat (fout,blob) ;//保存一个参数
}
}
catch(...)
{
}
fout <<"}\n";
}
fout.close ();
}
int main(int argc, char *argv[])
{
String t7model="mosaic.t7";//Torch
// 加载模型
dnn::Net net = cv::dnn::readNetFromTorch(t7model.c_str());
//导出训练参数,大致按 caffe 方式存放
String filename="style." + t7model +".txt";
saveModel(net,t7model,filename);//导出所有层名和参数
}