现在来写核心函数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 的
边缘由于填充不同,可以看出明显的差别
第一层完成。