Meta-SR(任意放大倍數的超分辨率),大概意思是 :可以是非整數倍的,並且只要一個模型(就可以實現2,3,4 倍及它們之中間倍數,比如,2.3, 3.5 倍等)
在《Meta-SR--master》中提供了 一個訓練好的模型 (百度盤),這裏用C++實現下(便於沒有安裝Pytorch的電腦運行)。
分成 特徵學習、元放大 兩塊。
先定義數據池,把訓練模型數據載入:
struct 層數據
{
int 權重長度;
float * 權重_數據;
int 偏移長度;
float * 偏移_數據;
int 輸入維度;
int 輸出維度;
int 核寬;
};
struct Linear權重//這個全連接以前是直接用“層數據”,並且用卷積代替這裏的torch.nn.Linear
{
int 權重長度;
float * 權重_數據;
int 偏移長度;
float * 偏移_數據;
int 輸入維度;
int 輸出維度;
};
struct 密集殘差塊 // 8+1個卷積層
{
//輸入 0; -->64
//0 連續存儲 64
層數據 * conv1;//64-->64
//0,1 連續存儲 128
層數據 * conv2;//128-->64
//0,1,2 連續存儲 192
層數據 * conv3;//192-->64
//0,1,2,3 連續存儲 256
層數據 * conv4;//256-->64
//0,1,2,3 ,4連續存儲 320
層數據 * conv5;//320-->64
層數據 * conv6;//384-->64
層數據 * conv7;//448-->64
層數據 * conv8;//512-->64
層數據 * conv9;//576-->64 局部特徵融合 1x1卷積
};
struct Meta_SR模型
{
層數據 * sub_mean;//減均值
層數據 * add_mean;//加均值
//淺層特徵提取
層數據 * conv1;//3->64
層數據 * conv2;//64->64
//密集殘差塊
int 密集殘差塊數量;//16塊
密集殘差塊 * 塊;
//16個密集殘差塊連續存儲 1024
層數據 * conv3; //1024-->64 特徵融合 1x1卷積
層數據 * conv4; //64-->64
//全局殘差相加
//放大
Linear權重 * Pos2Weight1; //in:3, out:256
Linear權重 * Pos2Weight2; //in:256,out:1728
//構造函數
Meta_SR模型();
};
主函數:
void Meta_SR(char * savefilename, Meta_SR模型 & sr)
{
int wid=bmp.width;
int hei=bmp.height;
cout<<"輸入圖像寬度:"<<wid<<endl;
cout<<" 高度:"<<hei<<endl;
卷積層 rgb(wid,hei,3);
rgb.data=new float[wid * hei * 3 ];
//jpg轉換爲RGB卷積層
bmp2RGB(rgb);
//---------------特徵學習模塊----------------------->
層數據 * 層;
//兩個卷積層 交替前傳(源,目標)
卷積層 * di=(卷積層 *)malloc(sizeof(卷積層));
di->width=1;
di->height=1;
di->depth=1;
di->data=new float[1 ];
卷積層 *源,*目標;
源 = &rgb;
目標 = di;
int pad;
RGB2BGR(*源);
卷積前傳無RELU(sr.sub_mean);
cout<<"輸入層..."<<endl;
卷積前傳無RELU(sr.conv1);
//備份
卷積層 conv1備份(wid,hei,源->depth);//f__1
conv1備份.data=new float[wid * hei * 源->depth ];
卷積層複製(源,&conv1備份);
卷積前傳無RELU(sr.conv2);
//第二部分 密集殘差塊
密集殘差塊總成(sr,*源);
cout<<"GFF_out:";
卷積層相加(&conv1備份,源);del卷積層(conv1備份);
cout<<"當前寬,高,深度:"<<源->width<<","<<源->height<<","<<源->depth<<endl;
卷積層 x(1,1);
Resize卷積層(x,源->width,源->height,源->depth);
卷積層複製(源,&x);
//---------------特徵學習模塊-----------------------<
//--------------- 元放大模塊 ----------------------->
cout<<"矩陣寬,高:"<<源->width<<","<<源->height<<endl;
float scale=2.0f;//可以是小數倍數
cout<<"\n"<< scale<<" 倍\n\n";
int scale_int=(int)ceil(scale);
cout<<"倍數選擇矩陣:\n";
void input_matrix_wpn(int inH,int inW,float scale,卷積層 &out);//
input_matrix_wpn(源->height,源->width,scale,*源);
cout<<"當前寬,高,深度:"<<源->width<<","<<源->height<<","<<源->depth<<endl;
vl_nnLinear(源,目標,sr.Pos2Weight1);
swap(源,目標);
cout<<"當前寬,高,深度:"<<源->width<<","<<源->height<<","<<源->depth<<endl;
vl_nnrelu(源);
vl_nnLinear(源,目標,sr.Pos2Weight2);
swap(源,目標);
cout<<"當前寬,高,深度:"<<源->width<<","<<源->height<<","<<源->depth<<endl;
刪除模型數據(sr);
cout<<"多維前傳:\n";
多維前傳(x,*源,scale_int);
//--------------- 元放大模塊 -----------------------<
wid = 源->width;hei = 源->height;
//加均值
後處理(*源);
RGB2BGR(*源);
cout<<"生成寬,高:"<<wid<<","<<hei<<endl;
RGB2bmp(*源);
cout<<"圖像轉換成jpg格式... "<<endl;
char filename[255];
sprintf_s(filename,"Meta %d 倍",scale_int);
savejpg(filename);
cout<<"轉換文件已經保存爲: "<<filename<<endl;
del卷積層(*源);
del卷積層(*目標);
}
左面的特徵學習模塊還是按以前的方法運行,右面的元放大模塊的原理也沒有看懂,只能按《Meta-SR--master》中的pytorch 代碼照樣運行。由於其中要用到多維張量(3,5,6維),放到下一文章說明吧。