纯C++超分辨率重建VDSR --改编

又找到一个caffe-vdsr-master,其中Test部分是用matconvnet来运行的,鼓捣一下也可以在Matlab 7.0+vc6.0中运行

所以,这一篇用 C++ 翻译 VDSR

VDSR 流程:
可以说:和 SRCNN 差不多,除了卷积核全部是 3x3 头尾一模一样,中间18层代替 SRCNN 的第二层,
残差网络也只是 网络结束后 加上双三次图。哪就开始吧:


先定义一个网络数据池:

struct VDSR模型
{
	int 层数; //20

	//权重
	int 权重_单个_长度; //核长 3x3 =9
	float *	权重_数据;

		
	//偏移
	int 偏移_单个_长度; //64,(不包括最后层 1)
	float *	偏移_数据;


	//构造函数
	VDSR模型();

};

VDSR模型::VDSR模型()
{
	层数=20; //

	int size;
	//偏移
	int 偏移_单个_长度=64; //64,最后层1
	size = sizeof(float)*(64 * 19 + 1);//
	偏移_数据 = (float*)malloc(size);

	//权重
	权重_单个_长度=9; //核长 3x3 =9
	size = sizeof(float) * (9 * 64 * 2 + 9 * 64 * 64 * 19 ); 
	权重_数据 = (float*)malloc(size);
		

}

大框架什么的和SRCCN都是相同的,这里直接进入 VDSR函数

先载入数据:

bool loadModel(VDSR模型 *sr)
{
	char name[]="VDSR_Official.txt";
	std::ifstream fin(name);

	//检查文件是否存在
	if (!fin)
	{
	return false;
	}

		cout<<"正在载入‘VDSR_Official.txt’的数据"<<endl;


	//从档案载入
	char str[40];
	int len;


	float *	w=sr->权重_数据;
	float *	b=sr->偏移_数据;
	for (int k = 0;k<20;k++)
	{
		cout<<k<<endl;

		//weight = model.weight{k};
		//wname=['权重_层' num2str(k) '\n'];
		//fprintf(FID,wname );
		fin >> str;
		cout<<str<<endl;

		//[h,w,c,p]=size(weight);
		//l=h*w*c*p;
		//fprintf(FID,'长度 %d\n',l );%有多少个
		fin >> str;
		cout<<str<<endl;

		fin >> len;//需要载入的个数
		cout<<len<<endl;

		//for i=1:c
		//    for j=1:p
		//        for s=1:h
		//            for t=1:w
		//                fprintf(FID, '%f ',weight(s,t,i,j)); 
		//            end
		//            fprintf(FID, '\n'); 

		//        end
		//    end
		//end
			
		//float tmp;
		for(int i=0;i<len;i++)
		{
			fin >> *w++;
			//fin >> tmp;
			//*w=tmp;w++;
		//cout<<"tmp:"<<tmp<<endl;
		}

		//bias = model.bias{k};
		//bname=['偏移_层' num2str(k) '\n'];
		//fprintf(FID,bname );
		fin >> str;
		cout<<str<<endl;

		//l=length(bias);
		//fprintf(FID,'长度 %d\n',l );%有多少个
		fin >> str;
		cout<<str<<endl;
		fin >> len;//需要载入的个数
		cout<<len<<endl;

		//for i=1:l
		//    fprintf(FID, '%f ',bias(i)); 
		//end
		//fprintf(FID, '\n'); 
		for(int i=0;i<len;i++)
		{
			fin >> *b++;
			//fin >> tmp;
			//(*b++)=tmp;
			//cout<<"tmp:"<<tmp<<endl;
		}
	}//end


		
	fin.close ();  
	return true;
}

其中注解部分就是从matlab 导出数据的代码,就不单独显示了

完整VDSR函数:

IMAGE VDSR(IMAGE *jpg,int up_scale)
{
	// 双三次插值
	// 先将低分辨率图像使用双三次插值放大至目标尺寸(如放大至2倍、3倍、4倍)
	//im_b = imresize(im_gnd, up_scale, 'bicubic');
	 IMAGE im_h=*jpg;
	//双三次2倍(&im_h);
	 ResizeGrayscaleImage(&im_h,up_scale ) ;

	//saveimage("放大.jpg",	&im_h);

	//// //显示
	putimage(im_h.getwidth(), 0, &im_h);



	VDSR模型 sr;
	// 加载 CNN 模型参数
	loadModel(&sr);

	int wid=im_h.getwidth();
	int hei=im_h.getheight();

	//图像转化为卷积矩阵
#define 彩色 1

#if 彩色==1
	//彩色
	卷积矩阵 im_b(wid,hei);//即Y通道
	卷积矩阵 U(wid,hei),V(wid,hei);

	//RGB转换为YUV
	RGB2YUV(&im_h,&im_b,&U,&V);
#else

	//单色
	卷积矩阵 im_b=im2卷积矩阵(&im_h);
	//save_卷积矩阵 ("im_b.txt",&im_b);  //保存权重
#endif

	//用于保存调试图像的变量
	IMAGE im_tt;	
	char txt[256];

	// 第一层卷积:卷积核尺寸3×3(f1×f1),卷积核数目64(n1),输出64张特征图;

	cout<<"第一层卷积..."<<endl;

	//conv1_data = zeros(hei, wid, conv1_filters);
	vector <卷积矩阵> conv0_data;//[64]结果

	clock_t start_t, end_t;//计算时间
	double total_t;
 
	start_t = clock();
 
	for (int i = 0 ;i<64;i++)
	{
		//weights_conv1 = reshape(weights_conv1, conv1_patchsize, conv1_patchsize, conv1_filters);
		//准备卷积核
		卷积矩阵 filter(3,3);	
		转换卷积核(&sr,&filter,0,i);

		卷积矩阵 res(wid,hei);


		//	conv1_data(:,:,i) = imfilter(im_b, weights_conv1(:,:,i), 'same', 'replicate');
		卷积(&filter,&im_b, &res);
		//卷积9x9核(&filter,&im_b, &res);

		//	conv1_data(:,:,i) = max(conv1_data(:,:,i) + biases_conv1(i), 0);
		加上偏移(&res,sr.偏移_数据,i);
		conv0_data.push_back(res);

		//

		////保存64个卷积核
		//sprintf(txt, "conv1_filter_%d.txt", i);   
		//save_卷积矩阵 (txt,&filter);

		//保存64个卷积结果矩阵
		//sprintf(txt, "conv1_data_%d.txt", i);   
		//save_卷积矩阵 (txt,&conv_data[i]);  //保存权重


		////保存64张特征图
		//im_tt=卷积矩阵2im(&res);
		//sprintf(txt, "conv1_data_0%d.jpg", i);   
		//saveimage(txt,	&im_tt);
	   end_t = clock();
	   
	   total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
	   if(total_t>1.0){
			cout<<i<<"/"<<64<<endl;
			start_t = clock();

			filter.~卷积矩阵();
			res.~卷积矩阵();
	   }

	}//end

	vector <卷积矩阵> conv1_data;//[64];//结果
			
	卷积矩阵 空(wid,hei);//
	//与conv0_data 一起组成 源 目标 存放池


	cout<<"第二至十九层卷积..."<<endl;
	for(int k = 1;k<19;k++)
	{

			cout<<"第"<<k+1<<"层卷积..."<<endl;
			// 第二层卷积:卷积核尺寸3×3(f2×f2),卷积核数目64x64(n2),输出64张特征图;

			if(k!=1)
			{
			   //交换源 和目标
				conv1_data.swap(conv0_data);
			}

				//清空目标
				conv1_data.clear();
				for (int i = 0;i<64 ;i++)
				{
					conv1_data.push_back(空);
				}
			int ff=0;
			start_t = clock();
			for (int i = 0;i<64 ;i++)
			{
				卷积矩阵 conv2(wid,hei);
				for (int j = 0 ;j<64;j++)
				{
					//准备卷积核
					卷积矩阵 filter(3,3);	
					转换卷积核(&sr,&filter,k,i*64+j);
					卷积(&filter,&conv0_data[j],&conv2);
					加上矩阵(&conv2,&conv1_data[i]);

					////保存64个卷积核
					//sprintf(txt, "conv%d_filter_%d.txt",k, ff);   ff++;
					//save_卷积矩阵 (txt,&filter);
				}//end
				//conv2_data(:,:,i) = max(conv2_data(:,:,i) + biases_conv2(i), 0);
				加上偏移(&conv1_data[i],sr.偏移_数据,64+(k-1)*64+i);

				////保存64张特征图
				//im_tt=卷积矩阵2im(&conv1_data[i]);
				//sprintf(txt, "conv2_data_0%d.jpg", i);   
				//saveimage(txt,	&im_tt);

				end_t = clock();

				total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
				if(total_t>1.0){
					cout<<i<<"/"<<64<<endl;
					start_t = clock();
				}


			}//end
	}//end

	cout<<"第二十层卷积..."<<endl;
	// 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。
	//conv3_data = zeros(hei, wid);
	卷积矩阵 conv3_data (wid,hei);

		start_t = clock();

	for(int i = 0;i<64;i++)
	{
		//conv3_subfilter = reshape(weights_conv3(i,:), conv3_patchsize, conv3_patchsize);
		卷积矩阵 conv3_subfilter(3,3);
		转换卷积核(&sr,&conv3_subfilter,19,i);

					////保存64个卷积核
					//sprintf(txt, "conv%d_filter_%d.txt",19, i);   ff++;
					//save_卷积矩阵 (txt,&conv3_subfilter);
		卷积矩阵 conv3_temp (wid,hei);

		卷积(&conv3_subfilter,&conv1_data[i],&conv3_temp);

		//第三层运算(&conv3_data,&conv3_temp);//特征图迭加
		加上矩阵(&conv3_temp,&conv3_data);

		//保存32张特征图
		//im_tt=卷积矩阵2im(&conv3_temp);
		//sprintf(txt, "conv3_temp_0%d.jpg", i);   
		//saveimage(txt,	&im_tt);

		//保存32次迭加图
		//im_tt=卷积矩阵2im(&conv3_data);
		//sprintf(txt, "conv3_data_0%d.jpg", i);   
		//saveimage(txt,	&im_tt);

		   end_t = clock();
		   
		   total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
		   if(total_t>1.0){
				cout<<i<<"/"<<64<<endl;
				start_t = clock();
		   }
	}//end

	cout<<"卷积完成"<<endl;
	
	//输入图 + 残差图
	加上矩阵(&im_b,&conv3_data);

	#if 彩色==1
		//彩色
	
		//YUV转回RGB
		YUV2RGB(&conv3_data,&U,& V,&im_h);
	#else
		//单色
		//卷积矩阵转化为图像
		im_h=卷积矩阵2im(&conv3_data);
	
	#endif

	 return im_h;
}

效果图:

   

分别为原图,SRCNN重建 和 VDSR重建图

vdsr中已去掉了modcrop,所以图片大了一点

再来一个:


这个相比效果更好

虽然效果好,时间也长,一个只有几秒钟,一个要500多秒。

先这样吧


猜你喜欢

转载自blog.csdn.net/juebai123/article/details/80721352