欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2023-12-30 19:24:40
...
又找到一个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;
}

效果图:

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

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

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

再来一个:

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

这个相比效果更好

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

先这样吧


上一篇:

下一篇: