C++ 实现美颜(脸部上妆)(BeautyGAN)

允我心安 提交于 2019-11-29 21:51:34

在《一键上妆的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;
}


 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!