使用 GLSL 运行网络(GLSL卷积)

使用GPU(OpenGL)来运行网络应该会快一点吧。

下面以《glsl着色器实现多重纹理与帧缓冲对象(fbo)》一文为模板生成一个卷积函数。用于超分SRCNN 中的卷积。

接口:

//初始化
// main的参数 和 层高,宽
void conv_init(int argc, char* argv[],int h,int w);

//卷积
//核数据,核宽,输入数据,输出数据
void conv_GLSL(float* kernel,int kw,float *inData, float * &outData);

拿这个去替换《纯C++超分辨率重建SRCNN》的卷积函数

下面说一下与《glsl着色器实现多重纹理与帧缓冲对象(fbo)》一文不同之处

片元着色器 卷积:

//片元着色器
const char *fShader = {
	"#version 400 compatibility \n"
	//层数据
    "uniform sampler2DRect  LenaTexture;         \n"
	//核宽
	"uniform int kw;                              \n"
	//9x9的核大小 , 5x5则只使用前面部分
	"uniform float kernel[81];                              \n"

	 
	"void main()"
	"{"
	"	vec2 pos = gl_TexCoord[0].st;\n"//坐标
	"	vec4 fSum = vec4(0.0,0.0,0.0,0.0);\n"//卷积值
	"	ivec2 vecSize = textureSize(LenaTexture);\n"//层数据宽高

	"	int index = 0;"
	"	int coreSize2=kw/2;"//半核宽
	"	for (float i = pos.x - coreSize2; i < pos.x + coreSize2 + 1.0; i += 1.0)" //对准核心
	"		for (float j = pos.y - coreSize2; j < pos.y + coreSize2 + 1.0; j += 1.0)"
	"		{"
	"			if (i >=0 && j >= 0 && i < vecSize.x && j < vecSize.y)"//相当于边界以 0 填充
	"			{"
	"				vec4 currentColor = texture2DRect(LenaTexture,vec2(i,j));\n"
	"				fSum += currentColor*kernel[index];\n" //积和
	"			}"
	"				index++;\n"//遍历核
	"		}"
	"	gl_FragColor = fSum;\n"

	"}"

};

纹理格式 把GL_RGBA 替换为 GL_R32F  和  GL_RED,这里只要单色就可以了。比如:

	//glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, imgWidth, imgHeight, 0,GL_RGBA,GL_FLOAT,0 ); 
	glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_R32F, imgWidth, imgHeight, 0,GL_RED,GL_FLOAT,0 ); 

初始化

 // main的参数 和 层高,宽
void conv_init(int argc, char* argv[],int h,int w)
{
	imgWidth=w;imgHeight=h;
	//printf("输入宽,高: %d,%d\n",w,h);
	glutInit( &argc, argv );

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

	glutInitWindowSize ( imgWidth, imgHeight);
	glutInitWindowPosition( 100, 100 );
	glutCreateWindow(" GLSL卷积 ");
	
	glewInit();
	initFBO2(imgWidth, imgHeight );

	int dataSize = imgHeight * imgWidth ;
	outPutFb = new GLfloat[dataSize];   //输出纹理缓冲  [imgHeight * imgWidth]
	memset(outPutFb,0,dataSize*sizeof(float));


	progHandle = initShaders(vShader, fShader); 


}

这 里是一个固定的宽高,所以要放在双三次放大的后面。

卷积

//核数据,核宽,输入数据,输出数据
void conv_GLSL(float* kernel,int kw,float *inData, float * &outData)
{
	//9x9,5x5核都放到kernel81
	init(inData);//数据生成纹理
	float kernel81[81]={0.0f};
	memcpy(kernel81, kernel, kw*kw*sizeof(float));

		
 
	if ( progHandle <= 0 )
		printf("Failed to run shader.\n");
	else{
		//设置初始一致变量
		glUniform1i( glGetUniformLocation( progHandle, "LenaTexture" ), 0 );   //0 是纹理的句柄//这个就是层数据(卷积对象)
		glUniform1i( glGetUniformLocation( progHandle, "kw" ), kw );   //核宽

		glUniform1fv( glGetUniformLocation( progHandle, "kernel"),81,kernel81);//核数据
	}
 
	display();//启用卷积计算
 
	readFromTexture( outPutFb );//读回卷积结果

	outData=outPutFb;
}

成2 个cpp文件,原来的 SRCNN.cpp 和 这个 GLSL.cpp。

SRCNN.cpp中只修改SRCNN函数

IMAGE SRCNN(int argc, char* argv[],IMAGE *jpg,int up_scale)
{
	// 双三次插值
	// 先将低分辨率图像使用双三次插值放大至目标尺寸(如放大至2倍、3倍、4倍)
	//im_b = imresize(im_gnd, up_scale, 'bicubic');
	 IMAGE im_h=*jpg;
	//双三次放大
	 ResizeGrayscaleImage(&im_h,up_scale ) ;

	//saveimage("放大.jpg",	&im_h);

	 //显示
	putimage(im_h.getwidth(), 0, &im_h);



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

	int wid=im_h.getwidth();
	int hei=im_h.getheight();

	//
	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);

	//用于保存调试图像的变量
	IMAGE im_tt;	
	//char txt[256];

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

	cout<<"第一层卷积..."<<endl;

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

	clock_t start_t, end_t;//计算时间
	double total_t;
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值