前面一次GLSL计算只能完成了一个卷积,应该可以加速。
先了解下网络卷积层的过程:
如果输入30个图(通道)要输出12个图(通道)的话,
1。分别对30图卷积,结果相加得到1图
2。重复12次这个过程,得到12图(共 30 X 12 = 360 个卷积)
相当于: 一个月30日,12个月(年)360日。
一个纹理可以完成一个卷积。多个纹理就可以完成多个卷积。
先检测 显卡支持纹理单元个数
//检查显卡支持纹理单元个数
GLint iUnits;
glGetIntegerv(GL_MAX_TEXTURE_UNITS,&iUnits);
printf("显卡支持纹理单元个数:%d\n\n",iUnits);
我的笔记本只有8个可用,有点少。
这次接口以层为单位:
//初始化
// main的参数 和 层高,宽
void conv_init(int argc, char* argv[],int h,int w);
//层卷积
//核数据,核宽,输入维度,输出维度,偏置数据,输入数据,输出数据,是否激活
//核大小:kw * kw * 输入维度 * 输出维度。
//输入数据大小:wh * 输入维度。 输出数据大小:wh * 输出维度。
void conv_GLSL_层(float* kernel,int kw,int inNum,int outNum,float *bias,float *inData, float * &outData,bool active=true);
用于SRCNN 是这样的:
void SRCNN(int argc, char* argv[],IMAGE *jpg,int up_scale)
{
// 先将低分辨率图像使用双三次插值放大至目标尺寸(如放大至2倍、3倍、4倍)
IMAGE im_h=*jpg;
//双三次放大
ResizeGrayscaleImage(&im_h,up_scale ) ;
SRCNN模型 sr;
// 加载 CNN 模型参数
loadModel(&sr);
int wid=im_h.getwidth();
int hei=im_h.getheight();
int wh=wid*hei;
//初始化GLSL
conv_init(argc, argv,hei, wid);
//图像转化为卷积矩阵
卷积矩阵 im_b(wid,hei);//即Y通道
卷积矩阵 U(wid,hei),V(wid,hei);
//RGB转换为YUV
RGB2YUV(&im_h,&im_b,&U,&V);
// 第一层卷积:卷积核尺寸9×9,卷积核数目64,输出64张特征图;
cout<<"第一层卷积..."<<endl;
float * _res ;//引用
conv_GLSL_层(sr.权重_conv1_数据,9,1,64,sr.偏移_conv1_数据,&im_b.data[0], _res,true);
// 第二层卷积:卷积核尺寸1×1,卷积核数目64x32,输出32张特征图;
cout<<"第二层卷积..."<<endl;
float *_res2;
conv_GLSL_层(sr.权重_conv2_数据,1,64,32,sr.偏移_conv2_数据,_res, _res2);
//删除第一层数据
delete []_res; _res=NULL;
// 第三层卷积:卷积核尺寸5×5,卷积核数目32,输出1张特征图即为最终重建高分辨率图像。
cout<<"第三层卷积..."<<endl;
卷积矩阵 conv3_data (wid,hei);
float *out;
conv_GLSL_层(sr.权重_conv3_数据,5,32,1,NULL,_res2, out, false);
memcpy(&conv3_data.data[0], out, wh*sizeof(float));
cout<<"卷积完成"<<endl;
//彩色
//YUV转回RGB
YUV2RGB(&conv3_data,&U,& V,&im_h);
saveimage("SRCNN 重建.jpg", &im_h);
}
这个看上去就比较简约了。
这里已经没有“转换卷积核”了,我已一次性转好。
片元着色器(一次完成8个卷积,加偏置也在其中&#x