//需要先在运行目录下创建文件夹opencv_layers
#include <iostream>
#include <unistd.h>
#include <opencv4/opencv2/opencv.hpp>
#include <opencv4/opencv2/dnn.hpp>
#include <opencv4/opencv2/dnn/dnn.hpp>
using namespace std;
/*
equal list
opencv_conv*relu = pycaffe_conv*
*/
int main(int argc, char *argv[])
{
//// SHOULD BE 4.*.*
cerr<<"WORKING IN OPENCV_VERSION "<<CV_VERSION<<'\n';
cv::Mat src = cv::imread("src.jpg");
string cfg ="deploy.prototxt";
string weights ="net_iter_25000.caffemodel";
cv::dnn::Net net = cv::dnn::readNetFromCaffe(cfg,weights);
if(net.empty()){
cerr<<"loaded net failed.\n";
return -1;
}
cv::Mat inputBlob = cv::dnn::blobFromImage(src, 1/255.F, cv::Size(300, 300), cv::Scalar(), false, false);
net.setInput(inputBlob,"data");
vector<cv::String> outputname=net.getLayerNames();
outputname.insert(outputname.begin(),"data");
cv::dnn::MatShape netInputSize = {1,3,300,300};
vector<cv::dnn::MatShape> netlastSize;
vector<vector<cv::dnn::MatShape> >layerSizes;
for(size_t i=0;i<outputname.size();++i){
vector<cv::dnn::MatShape>inputLayerSize;
vector<cv::dnn::MatShape>outputLayerSize;
net.getLayerShapes(netInputSize,i,inputLayerSize,outputLayerSize);
cerr<<"layer <<"<<outputname[i]<<">> size [\n";
for(size_t j=0;j<inputLayerSize.size();++j){
cerr<<"\t["<<inputLayerSize[j][0];for(size_t k=1;k<inputLayerSize[j].size();++k)cerr<<" x "<<inputLayerSize[j][k];cerr<<"]\n";
}
cerr<<"\tto\n";
for(size_t j=0;j<outputLayerSize.size();++j){
cerr<<"\t["<<outputLayerSize[j][0];for(size_t k=1;k<outputLayerSize[j].size();++k)cerr<<" x "<<outputLayerSize[j][k];cerr<<"]\n";
}
cerr<<"]\n";
layerSizes.push_back(outputLayerSize);
netlastSize=inputLayerSize;
}
vector<vector<cv::Mat> > outputBlob;
try{
cerr<<"\nNet forward ";
net.forward(outputBlob, outputname);
cerr<<"done\n\n";
}catch(exception e){
cerr << e.what() << '\n';
}
string selectLayer="conv4";
for(size_t i=0;i<outputname.size();++i){
for(size_t j=0;j<outputBlob[i].size();++j){
try{
cv::Mat blob;
cv::normalize(outputBlob[i][j], blob, 255, 0, cv::NORM_MINMAX);
cerr<<"blob dim = "<<blob.size.dims()<<" with type "<<blob.type()<<'\n';
//b * c * w * h
//b * w * h
//b * w
cerr<<"blob shape ["<<blob.size.p[0];for(size_t k=1;k<blob.size.dims();++k)cerr<<" x "<<blob.size.p[k];cerr<<"]\n";
cerr<<"real shape ["<<layerSizes[i][j][0];for(size_t k=1;k<layerSizes[i][j].size();++k)cerr<<" x "<<layerSizes[i][j][k];cerr<<"]\n";
cv::Mat saveimg;
float* data=(float*)blob.data;
string savepath;
int s[6]={0};
switch(blob.size.dims()){
case 2:
saveimg.create(layerSizes[i][j][1],1,CV_8UC1);
for(size_t pi=0; pi<layerSizes[i][j][1]; ++pi){
saveimg.data[pi]=data[pi];
}
savepath = "opencv_layers/layer_"+strip(outputname[i],"/")+".jpg";
cv::imwrite(savepath,saveimg);
saveimg.release();
break;
case 3:
s[1]=layerSizes[i][j][1];
s[0]=layerSizes[i][j][2];
saveimg.create(layerSizes[i][j][1],layerSizes[i][j][2],CV_8UC1);
for(size_t pi=0; pi<s[1]*s[0]; ++pi){
saveimg.data[pi]=(uchar)data[pi];
}
savepath = "opencv_layers/layer_"+strip(outputname[i],"/")+".jpg";
cv::imwrite(savepath,saveimg);
saveimg.release();
break;
case 4:
s[1]=layerSizes[i][j][2];
s[0]=layerSizes[i][j][3];
s[2]=s[1]*s[0];
s[3]=ceil(sqrt(layerSizes[i][j][1]));
s[4]=0;
saveimg=cv::Mat::zeros((s[1]+2)*s[3],(s[0]+2)*s[3],CV_8UC1);
fprintf(stderr,"saveimg <%d,%d> for %d\n",saveimg.rows,saveimg.cols,layerSizes[i][j][1]);
for(size_t wy=0; wy<s[3]; ++wy){
for(size_t wx=0; wx<s[3]; ++wx){
if(s[4]>=layerSizes[i][j][1])break;
s[5]=0;
for(size_t py=0; py<s[1]; ++py){
for(size_t px=0; px<s[0]; ++px){
saveimg.data[(wy*(s[1]+2)+py)*s[3]*(s[0]+2)+wx*(s[0]+2)+px]=(uchar)data[s[4]*s[2]+s[5]];
++s[5];
}
}
++s[4];
}
}
savepath = "opencv_layers/layer_"+strip(outputname[i],"/")+".jpg";
cv::imwrite(savepath,saveimg);
saveimg.release();
break;
default:
cerr<<" exordinary dim\n";
break;
}
cerr<<"save to "<<savepath<<'\n';
blob.release();
}catch(exception e){
cerr<<" escape beacuse "<<e.what()<<'\n';
}
}
}
fprintf(stderr, "float %d, double %d\n",sizeof(float),sizeof(double));
//blob <CV_32FC1,5> float
fprintf(stderr, "type list : <CV_8UC1,%d> <CV_8UC3,%d> <CV_16FC1,%d> <CV_16FC3,%d> <CV_16SC1,%d> <CV_16SC3,%d> <CV_32FC1,%d> <CV_32SC1,%d> ",
CV_8UC1,CV_8UC3,CV_16FC1,CV_16FC3,CV_16SC1,CV_16SC3,CV_32FC1,CV_32SC1);
return 0;
}