C++实现超分辨率重建 ESRGAN (二) 主流程

在ESRGAN函数内完成主流程:

void ESRGAN(char * savefilename,ESRGAN模型 & sr)
{

//		
	int wid=jpg.getwidth();
	int hei=jpg.getheight();
		
	int wh=wid*hei;


	卷积层 rgb(wid,hei,3);//即rgb通道
	rgb.data=new float[wid * hei *3]; 

	//jpg转换为RGB卷积层
	jpg2RGB(&jpg,&rgb);

	RGB2BGR(rgb) ;

	//---------------------------------------------->
	层数据 * 层;

	//两个卷积层 交替前传(源,目标)
			
	//用这个传回
	卷积层 * di=(卷积层 *)malloc(sizeof(卷积层));
		di->width=1;
		di->height=1;
		di->depth=1;
		di->data=new float[1 ]; 

	卷积层 *源,*目标;
	源 = &rgb;
	
	目标 = di;

	int pad;

	act_TYPE act_type;
		
	#define 一层卷积(ConvX) \
	\
	层=ConvX;/* Conv2 层 */ \
	/*int 层数=2;*/\
		if(层->输出维度 != 目标->depth || 目标->width != wid || 目标->height != hei)\
			Resize卷积层(*目标,wid,hei,层->输出维度);\
		pad=层->核宽/2;\
		vl_nnconv(源,目标,层 ,1,1,pad,pad,pad,pad);\
		if(act_type==relu)\
			vl_nnrelu(目标);/*激励函数relu*/\
		else if(act_type==leakyrelu)\
			vl_nnrelu(目标,0.2f);/*激励函数Prelu*/\
\
		std::swap (源,目标);\


	//特征层
	act_type=none;
	一层卷积(sr.特征_conv);
			save_卷积层2jpg(源,"con1");


	//连接池
	卷积层 连接池(wid,hei,192); //用于密集残差块
	连接池.data=new float[wh * 192 ]; 

	//ShortcutBlock----------------------------------------->
	卷积层 副本(wid,hei,64);
	副本.data=new float[wh * 64 ]; 		
	卷积层复制(源,&副本);


	密集残差组 * rb0=sr.rb_blocks.sub;
	卷积层 sub副本(wid,hei,64);
	sub副本.data=new float[wh * 64 ]; 
	for(int j=0;j<sr.rb_blocks.个数;j++)
	{
		cout<<j<<endl;

		卷积层复制(源,&sub副本);
		密集残差块前传(rb0->RDB1,*源,连接池);//
		密集残差块前传(rb0->RDB2,*源,连接池);//
		密集残差块前传(rb0->RDB3,*源,连接池);//
		//out.mul(0.2) + x
		卷积层乘以(*源,0.2f);//残差缩放
		卷积层相加(&sub副本,源);

		rb0++;
	}

	cout<<"LR_conv"<<endl;
	act_type=none;
	一层卷积(sr.LR_conv);
	//output = x + self.sub(x)
	卷积层相加(&副本,源);
			save_卷积层2jpg(源,"LR");
	//ShortcutBlock-----------------------------------------<


	//第一2倍放大
	层=sr.up2x_1.conv;
	wid*=2;hei*=2;
	Resize卷积层(*目标,wid,hei,层->输出维度);
	最近邻插值(*源,*目标);
	std::swap (源,目标);

	act_type=leakyrelu;
	一层卷积(sr.up2x_1.conv);

	//第二 2倍放大
	层=sr.up2x_2.conv;
	wid*=2;hei*=2;
	Resize卷积层(*目标,wid,hei,层->输出维度);
	最近邻插值(*源,*目标);
	std::swap (源,目标);

	一层卷积(sr.up2x_2.conv);
		
	//输出层
	cout<<"输出层..."<<endl;
	一层卷积(sr.HR_conv0);
	act_type=none;
	一层卷积(sr.HR_conv1);

	RGB2BGR(*源) ;


	//save_卷积层2txt("out.txt",目标);


	RGB2jpg(源,&jpg);

	//del卷积层(*目标);

	savejpg(&jpg,savefilename);
	cout<<"转换文件已经保存为:    "<<savefilename<<endl;
	//                
}

其中的密集残差块(PyTorch):

    def forward(self, x):
        x1 = self.conv1(x)
        x2 = self.conv2(torch.cat((x, x1), 1))
        x3 = self.conv3(torch.cat((x, x1, x2), 1))
        x4 = self.conv4(torch.cat((x, x1, x2, x3), 1))
        x5 = self.conv5(torch.cat((x, x1, x2, x3, x4), 1))
        return x5.mul(0.2) + x

之C++实现:

void 密集残差块前传(密集残差块 & b,卷积层 & s_di,卷积层 & 连接池)//从s_di 传入并返回
{
	int wid=s_di.width;
	int hei=s_di.height;
	int wh=wid*hei;

	卷积层 cat目标(wid , hei , 64);//也用于复制
	cat目标.data=连接池.data;//指向头,后面向后移
	卷积层复制(&s_di,&cat目标);
	cat目标.depth=32;//修改为32
	cat目标.data+=wh*64;

	卷积层 cat(wid , hei , 64);
	cat.data=连接池.data;//指向头,后面长度慢慢加32

	层数据 * 层;
	int pad;

	#define cat卷积(ConvX) \
	\
	层=ConvX;\
		pad=层->核宽/2;\
		vl_nnconv(&cat,&cat目标,层 ,1,1,pad,pad,pad,pad);\
		vl_nnrelu(&cat目标,0.2f);\
\
		cat目标.data+=wh*32;/* 向后移32 */\
		cat.depth+=32;/*加32长度*/\
		

	cat卷积(b.conv1);
	cat卷积(b.conv2);
	cat卷积(b.conv3);
	cat卷积(b.conv4);

	层=b.conv5;
		pad=层->核宽/2;
		vl_nnconv(&cat,&s_di,层 ,1,1,pad,pad,pad,pad);

	//x5.mul(0.2) + x 中的 mul(0.2) 
	卷积层乘以(s_di,0.2f);//残差缩放

	cat目标.depth=64;//
	cat目标.data=连接池.data; //头部是原输入
	//x5.mul(0.2) + x 中的  + x 
	卷积层相加(&cat目标,&s_di);

}

记得前面生成过一个SRGAN,来比一比效果:

小图

SRGAN生成

ESRGAN生成

结束。

下载:

win32超分辩重建ESRGAN实用程序

超分辨率重建ESRGAN(4倍)的win32程序,ESRGAN是在[PIRM2018-SR竞赛](区域3)中获得了第一名并获得了最佳感知指数。

https://download.csdn.net/download/juebai123/11046100

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值