纯C++超分辨率重建SRCNN --改编--(二)第一层卷积

现在来写核心函数SCREEN了,

先做一个SCREEN数据池,用于存放model_x3的数据

struct SCREEN模型
{
	//偏移
	int 偏移_conv1_长度; //
	float *	偏移_conv1_数据;

	int 偏移_conv2_长度; //
	float *	偏移_conv2_数据;

	int 偏移_conv3_长度; //
	float *	偏移_conv3_数据;
	//权重
	int 权重_conv1_长度;
	int 权重_conv1_宽度;
	float *	权重_conv1_数据;

	int 权重_conv2_长度;
	int 权重_conv2_通道;
	float *	权重_conv2_数据;

	int 权重_conv3_长度;
	int 权重_conv3_宽度;
	float *	权重_conv3_数据;

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

};

SCREEN模型::SCREEN模型()
{
	int size;
	偏移_conv1_长度 = 64; //
	size = sizeof(float)*偏移_conv1_长度;
    偏移_conv1_数据 = (float*)malloc(size);

	偏移_conv2_长度 = 32; //
	size = sizeof(float)*偏移_conv2_长度;
    偏移_conv2_数据 = (float*)malloc(size);

	偏移_conv3_长度 = 1; //
	size = sizeof(float)*偏移_conv3_长度;
    偏移_conv3_数据 = (float*)malloc(size);

	//权重
	权重_conv1_长度 = 81;
	权重_conv1_宽度 = 64;
	size = sizeof(float) * 权重_conv1_长度 * 权重_conv1_宽度;
	权重_conv1_数据 = (float*)malloc(size);

	权重_conv2_长度 = 64;
	权重_conv2_通道 = 32;
	size = sizeof(float) * 权重_conv2_长度 * 权重_conv2_通道;
	权重_conv2_数据 = (float*)malloc(size);

	权重_conv3_长度 = 32;
	权重_conv3_宽度 = 25;
	size = sizeof(float) * 权重_conv3_长度 * 权重_conv3_宽度;
	权重_conv3_数据 = (float*)malloc(size);
}

然后载入数据:

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

接着图像(一通道)转化为卷积矩阵:  

	卷积矩阵 im_b=im2卷积矩阵(&im_h);

由于 前面卷积矩阵在建立多个时分配内存出错,这里换成vector 从新定义:

class 卷积矩阵
{
	public:
	int		width;    //宽
	int     height;   //高

	//数据
	
	vector<float>data;

	//构造函数
	卷积矩阵(int iwidth,int iheight);
	~卷积矩阵();
};

IMAGE jpg;//一张原图

//构成一个卷积过程中的矩阵
卷积矩阵::卷积矩阵(int iwidth,int iheight): width(iwidth),
                                            height(iheight)
											
{
	int size=width*height;
	data.resize(size) ;
}

卷积矩阵::~卷积矩阵()											
{
	data.clear();
}

这样哪个卷积函数也要重新写了,并且根据'same'参数四边切去一部分:

void 卷积(卷积矩阵*filter,卷积矩阵*arr, 卷积矩阵*res)
{
	int filterW=filter->width;
	int filterH=filter->height;
	int arrW=arr->width;
	int arrH=arr->height;

    float temp;  
	int resW=filterW+arrW-1;//输出宽
	int resH=filterH+arrH-1;//输出高

	卷积矩阵  tmp(resW,resH);
	

	//扩展边界,暂缺


	//'full'
	for (int i=0; i<resH; i++)  //输入
    {  
        for (int j=0; j<resW; j++)  
        {  
            temp = 0;  
            for (int m=0; m<filterH; m++)  //核
            {  
                for (int n=0; n<filterW; n++)  
                {  
                    if ((i-m)>=0 && (i-m)<arrH && (j-n)>=0 && (j-n)<arrW)  
                    {  
						
                        temp += filter->data[m*filterW+n]*arr->data[(i-m)*arrW+(j-n)];  //积 和
                    }  
                }  
            }  
            tmp.data[i*resW+j] = temp; 
			//if(i>46)
			//	if(j>54)
			//cout<<i<<","<<j<<endl;
        }  
    }  

	//'same'切去一部分,让输出与输入图像的大小相同
    for(int i=0; i<arrH; i++)  
	{
        for(int j=0; j<arrW; j++)  
        {  
            res->data[i*arrW+j]=tmp.data[(i+(filterH-1)/2)*resW+(j+(filterW-1)/2)];  
        }  
	}
	
}

这里没有实现'replicate'参数,图像中心部分应该不受影响吧

开始第一层卷积:

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

	cout<<"第一层卷积..."<<endl;
	int wid=im_b.width;
	int hei=im_b.height;

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

	for (int i = 0 ;i<64;i++)
	{
		//weights_conv1 = reshape(weights_conv1, conv1_patchsize, conv1_patchsize, conv1_filters);
		//准备卷积核
		卷积矩阵 filter(9,9);	
		转换卷积核(&sr,&filter,1,i);

		卷积矩阵 res(wid,hei);


		//	conv1_data(:,:,i) = imfilter(im_b, weights_conv1(:,:,i), 'same', 'replicate');
		//Conv2(filter.data, im_b.data, res.data, filter.width, filter.height, im_b.width,im_b.height) ; 
		卷积(&filter,&im_b, &res);

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


	}//end

为了检查输出64张特征图是否正确,让Mablab的输入图放到这里来:


把特征图转化为图像并保存,放在上面的函数中:

		//保存64张特征图
		im_tt=卷积矩阵2im(&res);//转化为图像
		sprintf(txt, "conv1_data_0%d.jpg", i);   
		saveimage(txt,	&im_tt);

看一下文件图:


在matlab 中也导入图像:

    %保存64张特征图
    im_tt=uint8(conv1_data(:,:,i) * 255);
    imwrite(im_tt, ['conv1_data_0' num2str(i-1) '.jpg']);

这里拿几个来对比一下:


左边是本程序的,右边是Matlab 的

边缘由于填充不同,可以看出明显的差别

第一层完成。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值