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