C++ 實現美顏(臉部上妝)(BeautyGAN)

在《一鍵上妝的BeautyGAN》一文中介紹了,BeautyGAN 的

實現功能:輸入兩張人臉圖片,一張無妝,一張有妝,模型輸出換妝之後的結果,即一張上妝圖和一張卸妝圖。

並在《https://github.com/Honlan/BeautyGAN》中有訓練好的模型下載。這裏也來試試。

python 復現結果:

輸入圖:

結果圖:

 

 我們只關注生成器部分:

這個生成器相當於前面 “風格轉移(style)”兩個合併:

把綠色部分合併成一起,就有兩個入口,兩個出口,和一個共用的中腹。

C++實現

定義數據池:

struct BeautyGAN模型
{
    //輸入1 素顏圖
	層數據 * conv0;
	InstanceNorm層數據 * inn0;
	層數據 * conv1;				//2步長縮小
	InstanceNorm層數據 * inn1;
	層數據 * conv2;				//2步長縮小
	InstanceNorm層數據 * inn2;

    //輸入2 樣榜圖
	層數據 * conv3;
	InstanceNorm層數據 * inn3;
	層數據 * conv4;				//2步長縮小
	InstanceNorm層數據 * inn4;
	層數據 * conv5;				//2步長縮小
	InstanceNorm層數據 * inn5;

	//合併

	//----------共用部分---------------->
	//主體
	int 公用層數量;//12層
	層數據 * conv6_17;
	InstanceNorm層數據 * inn6_17;

	//插值放大
	//----------共用部分----------------<

    //輸出1
	層數據 * conv18;
	InstanceNorm層數據 * inn18;
	//插值放大
	層數據 * conv19;
	InstanceNorm層數據 * inn19;
	層數據 * conv20;
	//生成素顏上妝圖

    //輸出2
	層數據 * conv21;
	InstanceNorm層數據 * inn21;
	//插值放大
	層數據 * conv22;
	InstanceNorm層數據 * inn22;
	層數據 * conv23;
	//生成樣榜卸妝圖

	
	//構造函數
	BeautyGAN模型();

};

主函數:

void BeautyGAN(char * savefilename,BeautyGAN模型 & sr,char * makeup)
{
	int wid=bmp.width;
	int hei=bmp.height;
		cout<<"輸入圖像寬度:"<<wid<<endl;
		cout<<"        高度:"<<hei<<endl;
//
	卷積層 rgb(wid,hei,3);//即 X_img
	rgb.data=new float[wid * hei *3]; 

	//無妝(需上妝)圖
	//jpg轉換爲RGB卷積層
	bmp2RGB(rgb);

	wid=rgb.width;
	hei=rgb.height;

	//---------------------------------------------->
	層數據 * 層;

	//兩個卷積層 交替前傳(源,目標)
			
	//用這個傳回
	卷積層 * di=(卷積層 *)malloc(sizeof(卷積層));
		di->width=1;
		di->height=1;
		di->depth=1;
		di->data=new float[1 ]; 
	卷積層 * si=(卷積層 *)malloc(sizeof(卷積層));
		si->width=1;
		si->height=1;
		si->depth=1;
		si->data=new float[1 ]; 

	卷積層 *源,*目標;

	源   = si;
	目標 = di;

	int pad;

		
	//有妝樣榜圖
	loadjpg(makeup);

	卷積層 Y_img(bmp.width,bmp.height,3);
	Y_img.data=new float[bmp.width*bmp.height *3]; 

	//jpg轉換爲RGB卷積層
	bmp2RGB(Y_img);


	cout<<"上妝輸入..."<<endl;
	//固定大小
	wid=256;hei=256;
	Resize卷積層(*源,wid,hei,3);

	if(rgb.width==wid && rgb.height==hei)
		卷積層複製(&rgb,源);
	else
		resize_卷積層(rgb,*源);


	cout<<"卷積 0..."<<endl;

	卷積和正則化(sr.conv0,1,sr.inn0);
		
	
	cout<<"卷積 1..."<<endl;

	//wid=wid/2;hei=hei/2;
	//卷積和正則化(sr.conv1,2,sr.inn1);
	步長爲2的卷積和正則化(sr.conv1,sr.inn1);

	cout<<"卷積 2..."<<endl;

	//wid=wid/2;hei=hei/2;
	//卷積和正則化(sr.conv2,2,sr.inn2);
	步長爲2的卷積和正則化(sr.conv2,sr.inn2);


	卷積層 合併(wid,hei,256);
	合併.data=new float[wid*hei*256];
		
	cout<<"複製..."<<endl;

	卷積層 複製(wid,hei,128);
	複製.data=合併.data;//合併.data+wid*hei*128;//
	卷積層複製(源,&複製);


	cout<<"卸妝輸入..."<<endl;

	wid=256;hei=256;
	Resize卷積層(*源,wid,hei,3);

	if(Y_img.width==wid && Y_img.height==hei)
		卷積層複製(&Y_img,源);
	else
		resize_卷積層(Y_img,*源);


	cout<<"卷積 3..."<<endl;

	卷積和正則化(sr.conv3,1,sr.inn3);

	cout<<"卷積 4..."<<endl;

	//wid=wid/2;hei=hei/2;
	//卷積和正則化(sr.conv4,2,sr.inn4);
	步長爲2的卷積和正則化(sr.conv4,sr.inn4);

		
	cout<<"卷積 5..."<<endl;


	//wid=wid/2;hei=hei/2;
	//卷積和正則化(sr.conv5,2,sr.inn5);
	步長爲2的卷積和正則化(sr.conv5,sr.inn5);


		
	cout<<"合併..."<<endl;
		
	複製.data=合併.data+wid*hei*128;//合併.data;//
	卷積層複製(源,&複製);

		
	Resize卷積層(*源,wid,hei,256);
	卷積層複製(&合併,源);

	cout<<"殘差塊..."<<endl;
		
	殘差塊總成(sr,源);//從s_di 傳入並返回


	cout<<"鄰近插值..."<<endl;
	wid *= 2;hei *= 2;
	Resize卷積層(*目標,wid,hei,256);
	最近鄰插值(*源,*目標);

	std::swap (源,目標);


	cout<<"卷積 18..."<<endl;
		
	卷積和正則化(sr.conv18,1,sr.inn18);



	cout<<"鄰近插值..."<<endl;
	wid *= 2;hei *= 2;
	Resize卷積層(*目標,wid,hei,64);
	最近鄰插值(*源,*目標);

	std::swap (源,目標);

	cout<<"卷積 19..."<<endl;
		
	卷積和正則化(sr.conv19,1,sr.inn19);

	cout<<"卷積 20..."<<endl;
		
	卷積前傳(sr.conv20,1);

	vl_tanh(源);

	cout<<"圖像轉換成jpg格式... "<<endl;



	RGB2bmp(*源);

	//del卷積層(*目標);

	savejpg(savefilename);

	cout<<"轉換文件已經保存爲:    "<<savefilename<<endl;

	//輸出無妝圖
	wid=輸出無妝.width;hei=輸出無妝.height;
	Resize卷積層(*源,wid,hei,輸出無妝.depth);
	卷積層複製(&輸出無妝,源);
	
		
	cout<<"卷積 21..."<<endl;

	卷積和正則化(sr.conv21,1,sr.inn21);

	cout<<"鄰近插值..."<<endl;
	wid *= 2;hei *= 2;
	Resize卷積層(*目標,wid,hei,64);
	最近鄰插值(*源,*目標);

	std::swap (源,目標);


	cout<<"卷積 22..."<<endl;

	卷積和正則化(sr.conv22,1,sr.inn22);

	cout<<"卷積 23..."<<endl;

	卷積前傳(sr.conv23,1);

		
	vl_tanh(源);

	RGB2bmp(*源);

	del卷積層(*目標);

	savejpg("無妝圖.jpg");

	cout<<"樣板去妝後圖已經保存爲:    "<<"無妝圖.jpg"<<endl;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章