使用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核都放到kernel81init(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转换为YUVRGB2YUV(&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;start_t = clock();卷积层 _im_b=卷积矩阵2卷积层(&im_b);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');//卷积(&filter,&im_b, &res);//卷积快速(&filter,&im_b, &res);{//----------替换卷积------------------->卷积层 ttt=卷积矩阵2卷积层(&filter);float * _res ;//引用 conv_GLSL(ttt.data,9,_im_b.data, _res);卷积层 out(wid,hei);out.data=_res;卷积层2卷积矩阵_复制(&out,&res);}//-----------替换卷积--------------------<// conv1_data(:,:,i) = max(conv1_data(:,:,i) + biases_conv1(i), 0);加上偏移(&res,sr.偏移_conv1_数据,i);conv1_data.push_back(res);////保存64个卷积核//sprintf(txt, "conv1_filter_%d.txt", i); //save_卷积矩阵 (txt,&filter);//保存64个卷积结果矩阵//if(i<2){sprintf(txt, "conv1_data_%d.txt", i); //sprintf_s(txt,256, "conv1_data_%d.txt", i); //save_卷积矩阵 (txt,&conv1_data[i]); //保存权重//}//保存64张特征图//im_tt=卷积矩阵2im(&res);//sprintf(txt, "conv1_data_0%d.jpg", i); //saveimage(txt, &im_tt);end_t = clock();total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;if(total_t>1.0){cout<<i<<"/"<<64<<endl;start_t = clock();}}//endcout<<"第二层卷积..."<<endl;// 第二层卷积:卷积核尺寸1×1(f2×f2),卷积核数目32(n2),输出32张特征图;vector <卷积矩阵> conv2_data;//[32];//结果start_t = clock();for (int i = 0;i<32 ;i++){//cout<<i<<endl;卷积矩阵 conv2(wid,hei);for (int j = 0 ;j<64;j++){//conv2_data(:,:,i) = conv2_data(:,:,i) + weights_conv2(j,:,i) * conv1_data(:,:,j);第二层运算(&conv2,&sr,&conv1_data[j],i,j);}//end//conv2_data(:,:,i) = max(conv2_data(:,:,i) + biases_conv2(i), 0);加上偏移(&conv2,sr.偏移_conv2_数据,i);conv2_data.push_back(conv2);//保存32张特征图//im_tt=卷积矩阵2im(&conv2);//sprintf(txt, "conv2_data_0%d.jpg", i); //saveimage(txt, &im_tt);end_t = clock();total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;if(total_t>1.0){cout<<i<<"/"<<32<<endl;start_t = clock();}}//endcout<<"第三层卷积..."<<endl;// 第三层卷积:卷积核尺寸5×5(f3×f3),卷积核数目1(n3),输出1张特征图即为最终重建高分辨率图像。//conv3_data = zeros(hei, wid);卷积矩阵 conv3_data (wid,hei);start_t = clock();for(int i = 0;i<32;i++){//conv3_subfilter = reshape(weights_conv3(i,:), conv3_patchsize, conv3_patchsize);卷积矩阵 conv3_subfilter(5,5);转换卷积核(&sr,&conv3_subfilter,3,i);//保存32个卷积核//sprintf(txt, "conv3_filter%d.txt", i); //save_卷积矩阵 (txt,&conv3_subfilter);卷积矩阵 conv3_temp (wid,hei);//conv3_data(:,:) = conv3_data(:,:) + imfilter(conv2_data(:,:,i), conv3_subfilter, 'same', 'replicate');//卷积快速(&conv3_subfilter,&conv2_data[i],&conv3_temp);//卷积(&conv3_subfilter,&conv2_data[i],&conv3_temp);{float * _res ;//引用 卷积层 ttt=卷积矩阵2卷积层(&conv3_subfilter);卷积层 _data=卷积矩阵2卷积层(&conv2_data[i]);conv_GLSL(ttt.data,5,_data.data, _res);卷积层 out(wid,hei);out.data=_res;卷积层2卷积矩阵_复制(&out,&conv3_temp);}第三层运算(&conv3_data,&conv3_temp);//特征图迭加//保存32张特征图//im_tt=卷积矩阵2im(&conv3_temp);//sprintf(txt, "conv3_temp_0%d.jpg", i); //saveimage(txt, &im_tt);//保存32次迭加图//im_tt=卷积矩阵2im(&conv3_data);//sprintf(txt, "conv3_data_0%d.jpg", i); //saveimage(txt, &im_tt);//if(i<2){sprintf(txt, "conv1_data_%d.txt", i); //sprintf_s(txt,256, "conv3_data_%d.txt", i); //save_卷积矩阵 (txt,&conv3_temp); //保存权重//}end_t = clock();total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;if(total_t>1.0){cout<<i<<"/"<<32<<endl;start_t = clock();}}//endcout<<"卷积完成"<<endl;//彩色//YUV转回RGBYUV2RGB(&conv3_data,&U,& V,&im_h);return im_h;
}
完整的文件在以前的文章中。
完整的 GLSL.cpp
//GLSL 卷积
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "OpenGL32.lib")#include<windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
//#include "savePicture.h"//纹理的编号
static GLuint texture; //lena图像作为纹理
//static GLuint texWeigArr1; //自己生成的纹理1
//static GLuint texWeigArr2; //自己生成的纹理2
static GLuint texOutput; //产生结果的纹理static GLuint fb; //FBO编号#define printOpenGLError() printOglError(__FILE__, __LINE__)//std::string imgName;
GLint imgHeight , imgWidth;GLfloat *outPutFb; //输出纹理缓冲 [imgHeight * imgWidth]GLubyte *pData; //存储最终的图像数据//顶点着色器
const char *vShader = {"void main()""{""gl_TexCoord[0] = gl_MultiTexCoord0;""gl_Position = ftransform();""}"
};//片元着色器
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""}"};//输出错误相关信息
int printOglError(char *file, int line)
{GLenum glErr;int retCode = 0;glErr = glGetError();while (glErr != GL_NO_ERROR){printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));retCode = 1;glErr = glGetError();}return retCode;
}//输出opengl错误
void printInfoLog(GLhandleARB obj)
{int infologLength = 0;int charsWritten = 0;GLcharARB *infoLog;printOpenGLError();glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);printOpenGLError();if(infologLength > 0){infoLog = (GLcharARB*)malloc(infologLength);if(infoLog == NULL){printf("ERROR: Could not allocate InfoLog buffer\n");exit(1);}glGetInfoLogARB(obj,infologLength,&charsWritten,infoLog);printf("InfoLog:\n%s\n\n",infoLog);free(infoLog);}printOpenGLError();
}/*************************************************************
function name: initShaders
input: 1. const char *vShaderCode, 2. const char *fShaderCode,
output: 1. -1 compile error2. -2 link error3. progHandle
description:*****************************************************************/
GLhandleARB initShaders( const char *vShaderCode, const char *fShaderCode )
{GLhandleARB vertHandle, fragHandle, progHandle; //对象句柄GLint vertCompiled, fragCompiled; //状态值GLint linked;//创建顶点着色器对象和片元着色器对象vertHandle = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);fragHandle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);//将源代码字符串加载到着色器中glShaderSource( vertHandle, 1, &vShaderCode, NULL );glShaderSource( fragHandle, 1, &fShaderCode, NULL );printf("编译码块顶点着色器并打印编译器日志文件:\n");//编译码块顶点着色器并打印编译器日志文件glCompileShaderARB(vertHandle);printOpenGLError(); //检查opengl错误glGetObjectParameterivARB(vertHandle,GL_OBJECT_COMPILE_STATUS_ARB, &vertCompiled);printInfoLog(vertHandle);printf("编译码块片元着色器并打印编译器日志文件:\n");//编译码块片元着色器并打印编译器日志文件glCompileShaderARB(fragHandle);printOpenGLError(); //检查opengl错误glGetObjectParameterivARB(fragHandle,GL_OBJECT_COMPILE_STATUS_ARB, &fragCompiled);printInfoLog(fragHandle);if(!vertCompiled || !fragCompiled)return -1;//创建一个程序对象并附加两个编译好的着色器progHandle = glCreateProgramObjectARB();glAttachObjectARB(progHandle, vertHandle);glAttachObjectARB(progHandle, fragHandle);printf("链接程序对象并打印信息日志:\n");//链接程序对象并打印信息日志glLinkProgramARB(progHandle);printOpenGLError(); //检查opengl错误glGetObjectParameterivARB(progHandle, GL_OBJECT_LINK_STATUS_ARB, &linked);printInfoLog(progHandle);if(!linked)return -2;//将程序对象安装为当前状态的一部分glUseProgramObjectARB(progHandle); //改为运行的函数,用于测试该算法的时间return progHandle;
}//装载一个bmp图像使之成为纹理,其中貌似包含了 glTexImage2D这个函数的功能
int LoadGLTextures(float *pTexData)
{glGenTextures( 1, &texture );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texture);//当卷积内核超过了图像边界时使用图像边缘的像素值//glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );//glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//替换为glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP);//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, imgWidth, imgHeight, 0,GL_RGB,GL_UNSIGNED_BYTE,pTexData );//glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, imgWidth, imgHeight, 0,GL_LUMINANCE, GL_FLOAT,pTexData );glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_R32F, imgWidth, imgHeight, 0,GL_RED, GL_FLOAT,pTexData );glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE );return 0;
}int LoadGLTextures(unsigned char *pTexData)
{glGenTextures( 1, &texture );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texture);//当卷积内核超过了图像边界时使用图像边缘的像素值glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, imgWidth, imgHeight, 0,GL_RGB,GL_UNSIGNED_BYTE,pTexData );glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE );return 0;
}void init()
{glShadeModel( GL_FLAT );glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );glViewport(0,0, imgWidth, imgHeight );glEnable ( GL_DEPTH_TEST );//LoadGLTextures("texture.bmp");//if ( LoadGLTextures(imgName.c_str()) == 1 )// printf( " Load Faild! \n");//设置输出纹理的参数glGenTextures( 1, &texOutput );glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texOutput );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//没有给输出的纹理数据,等待程序进行赋值glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, imgWidth, imgHeight, 0,GL_RGBA,GL_FLOAT,0 ); glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE );//激活各个纹理glActiveTexture( GL_TEXTURE0 );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texture);
}void init(unsigned char *pTexData)
{glShadeModel( GL_FLAT );glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );glViewport(0,0, imgWidth, imgHeight );glEnable ( GL_DEPTH_TEST );//LoadGLTextures("texture.bmp");if ( LoadGLTextures(pTexData) == 1 )printf( " Load Faild! \n");//设置输出纹理的参数glGenTextures( 1, &texOutput );glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texOutput );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//没有给输出的纹理数据,等待程序进行赋值glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, imgWidth, imgHeight, 0,GL_RGBA,GL_FLOAT,0 ); glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE );//激活各个纹理glActiveTexture( GL_TEXTURE0 );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texture);
}void init(float *pTexData)
{glShadeModel( GL_FLAT );glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );glViewport(0,0, imgWidth, imgHeight );glEnable ( GL_DEPTH_TEST );//LoadGLTextures("texture.bmp");if ( LoadGLTextures(pTexData) == 1 )printf( " Load Faild! \n");//设置输出纹理的参数glGenTextures( 1, &texOutput );glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texOutput );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//没有给输出的纹理数据,等待程序进行赋值//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 ); glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE );//激活各个纹理glActiveTexture( GL_TEXTURE0 );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texture);
}void initFBO2( unsigned unWidth, unsigned unHeight )
{//创建FBO,准备屏幕外帧缓存glGenFramebuffersEXT( 1, &fb );//绑定屏幕外帧缓存,即避开了窗口系统默认的渲染目标glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, fb );}
void readFromTexture( GLfloat *data )
{glReadBuffer( GL_COLOR_ATTACHMENT0_EXT );//指定要读取的缓存//GL_APHPA 按照ALPHA值存储纹理单元//GL_LUMINANCE 按照亮度值存储纹理单元//GL_LUMINANCE_ALPHA 按照亮度和alpha值存储纹理单元//GL_RGB 按照RGB成分存储纹理单元//GL_RGBA 按照RGBA成分存储纹理单元//GL_RED 单一红色的纹理 <----------------------就要这个glReadPixels( 0, 0, imgWidth, imgHeight,GL_RED , GL_FLOAT, data );//单一红色//glReadPixels( 0, 0, imgWidth, imgHeight,// GL_LUMINANCE , GL_FLOAT, data );// 亮度//glReadPixels( 0, 0, imgWidth, imgHeight,// GL_RGB, GL_FLOAT, data );//三色}void display( void )
{glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );关联输出缓存至FBOglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB,texOutput,0 );glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );glBegin( GL_QUADS ); glMultiTexCoord2f( GL_TEXTURE0, 0.0, 0.0); glMultiTexCoord2f( GL_TEXTURE1, 0.0, 0.0); glMultiTexCoord2f( GL_TEXTURE2, 0.0, 0.0); glVertex2f( -1.0, -1.0); glMultiTexCoord2f(GL_TEXTURE0, 0.0, imgHeight ); glMultiTexCoord2f(GL_TEXTURE1, 0.0, imgHeight ); glMultiTexCoord2f( GL_TEXTURE2, 0.0, imgHeight ); glVertex2f( -1.0, 1.0 );glMultiTexCoord2f(GL_TEXTURE0, imgWidth, imgHeight ); glMultiTexCoord2f(GL_TEXTURE1, imgWidth, imgHeight ); glMultiTexCoord2f( GL_TEXTURE2, imgWidth,imgHeight ); glVertex2f( 1.0, 1.0 );glMultiTexCoord2f(GL_TEXTURE0, imgWidth, 0.0 ); glMultiTexCoord2f(GL_TEXTURE1, imgWidth, 0.0 ); glMultiTexCoord2f( GL_TEXTURE2, imgWidth, 0.0); glVertex2f ( 1.0, -1.0 );glEnd( );glFlush();
}GLhandleARB progHandle = 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核都放到kernel81init(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;
}
如果你只想看看这个卷积是否可用,下面的简单测试(4x4输入,3x3核)可以手算于之比一下是否一样。
这个和超分SCRRN.cpp无关。
void test_conv(int argc, char* argv[])
{float inData[16]={1,2,3,4,5,6,7,-8,0.8f,-0.8f,-7,16,5,4,13,2};int w=4;int h=4;float kernel[9]={-1, 1,-1,1, 2, 1,-1, 1,-1};int kw=3;//初始化conv_init(argc, argv,h, w);float * outData;//卷积conv_GLSL( kernel,kw,inData, outData);//显示结果for(int i=0;i<h;++i){for(int j=0;j<w;++j){cout<<*outData++<<" ";}cout<<"\n";}cout<<"\n";
}int main( int argc, char *argv[])
{test_conv(argc, argv);system("pause");return 0;
}
win8 + vs2008 + glew + glut 编译环境。
结束