今天晚上没事将以前弄的OPENGL着色语言实现滤镜效果的实现和大家分享一下,滤镜主要包括图像的对比度调整、浮雕效果、彩色图片灰度化、卷积等操作。

这些操作其本质上是属于图像处理的东西,OpenGL实现图像处理主要是用到了GLSL着色语言。具体到着色器就是片段着色器。

说白了就是如何用OpenGL做通用GPU计算,OpenGL做通用计算的步骤主要如下:

读取数据->顶点着色器->片段着色器->渲染到纹理->从纹理读写数据。

步骤具体细化如下:

(1)初始化。

初始化窗口系统。

void InitGLUT(int argc,char**argv)

{

glutInit(&argc,argv);

glutWindow = glutCreateWindow("GPGPU");

}

初始化FBO。在此阶段还需要将投影设置为正摄投影的方式,视口与图像的幅宽一样大,并且还要讲纹理重采样方式设置为最邻近采样,这样就保证了片段操作的时候取得每个数据都是原始数据。

void InitFBO(int nWidth,intnHeight,GLuint*pFb)

{

//创建FBO并绑定

glewInit();

GLuint fb;

glGenFramebuffersEXT(1,&fb);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fb);

*pFb = fb;

//用绘制来调用

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0,nWidth,0,nHeight);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glViewport(0,0,nWidth,nHeight);

}

初始化shader,包括从文件中读取数据以及编译等操作。

void InitGLSL()

{

//创建顶点shader

vertShader = glCreateShader(GL_VERTEX_SHADER);

if( 0 == vertShader)

{

fprintf(stderr,"Error creating vertex shader.\n");

exit(1);

}

GLint result;

//加载片元着色器

fragShader = glCreateShader(GL_FRAGMENT_SHADER);

if( 0 == fragShader)

{

fprintf(stderr,"片元着色器创建失败.\n");

exit(1);

}

//c拷贝shader源码

const GLchar *shaderCode2 = loadShaderAsString("BrightNess.glsl");

glShaderSource( fragShader,1, &shaderCode2, NULL );

delete []shaderCode2;

//编译shader

glCompileShader(fragShader);

//检查编译状态

glGetShaderiv( fragShader,GL_COMPILE_STATUS, &result );

if (GL_FALSE ==result)

{

fprintf( stderr,"片元着色器编译失败!\n" );

GLint logLen;

glGetShaderiv( fragShader,GL_INFO_LOG_LENGTH, &logLen );

if( logLen > 0)

{

char * log = (char *)malloc(logLen);

GLsizei written;

glGetShaderInfoLog(fragShader,logLen, &written,log);

fprintf(stderr,"Shaderlog:\n%s", log);

free(log);

}

}

//创建程序对象

programHandle = glCreateProgram();

if( 0 == programHandle)

{

fprintf(stderr,"Error creating program object.\n");

exit(1);

}

//将着色器链接到程序对象

glAttachShader(programHandle,fragShader);

//链接程序

glLinkProgram(programHandle);

//检查链接状态

GLint status;

glGetProgramiv( programHandle,GL_LINK_STATUS, &status );

if( GL_FALSE == status )

{

fprintf( stderr,"链接失败!\n" );

GLint logLen;

glGetProgramiv(programHandle,GL_INFO_LOG_LENGTH,

&logLen);

if( logLen > 0)

{

char * log = (char *)malloc(logLen);

GLsizei written;

glGetProgramInfoLog(programHandle,logLen,

&written, log);

fprintf(stderr,"Program log: \n%s",log);

free(log);

}

glDeleteProgram(programHandle);

}

else

{

glUseProgram(programHandle);

}

}

(2)创建纹理对象以及设置参数

这里需要创建两个纹理对象,一个用于输入图像,另外一个用于保存输出的结果,即将保存结果的纹理对象绑定到帧缓存对象上,即实现渲染到纹理的目标。

//创建纹理对象并绑定

GLuint xTexID,yTexID;

glGenTextures(1,&xTexID);

glGenTextures(1,&yTexID);

设置纹理属性如下:

void SetupTexture(stTextureParatextureParameters,constGLuinttexID,int nWidth,int nHeight)

{

glBindTexture(textureParameters.texTarget,texID);

//设置纹理参数

glTexParameteri(textureParameters.texTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

glTexParameteri(textureParameters.texTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

glTexParameteri(textureParameters.texTarget,GL_TEXTURE_WRAP_S,GL_CLAMP);

glTexParameteri(textureParameters.texTarget,GL_TEXTURE_WRAP_T,GL_CLAMP);

//定义纹理数据单元类型

glTexImage2D(textureParameters.texTarget,0,textureParameters.texInternalFormat,nWidth,nHeight,0,

textureParameters.texFormat,GL_FLOAT,0);

}

然后将输入数据加载到输入纹理缓存上面

//传入输入数据

glBindTexture(textureParameters.texTarget,xTexID);

glTexSubImage2D(textureParameters.texTarget,0,0,0,nWidth,nHeight,textureParameters.texFormat,GL_FLOAT,pfInput);

//设置映射参数,替换原来的数据

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

最后是将输出纹理绑定到帧缓存对象上并激活输入纹理对象。

//绑定输出纹理缓存

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,textureParameters.texTarget,yTexID,0);

//激活当前输入的纹理单元

glActiveTexture(GL_TEXTURE0);

绑定的关联点就是GL_COLOR_ATTACHMENT0_EXT,它代表是帧缓存中的一个颜色缓存。

(3)设置渲染的对象

glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);

glPolygonMode(GL_FRONT,GL_FILL);

(4)通过绘制来调用“核函数”

这里是一个形象的比喻,就是通过绘制操作来实现对图像的处理,类似于CUDA和opencl里面的核函数调用。

//用绘制进行调用

glBegin(GL_QUADS);

glTexCoord2f(0,0);

glVertex2f(0,0);

glTexCoord2f(nWidth,0);

glVertex2f(nWidth,0);

glTexCoord2f(nWidth,nHeight);

glVertex2f(nWidth,nHeight);

glTexCoord2f(0,nHeight);

glVertex2f(0,nHeight);

glEnd();

glFinish();

(5)读取结果数据以及进一步处理

//从当前纹理缓存拷贝数据

void TransformFromTex(intnWidth,intnHeight,float *pfData)

{

//读取数据

glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);

glReadPixels(0,0,nWidth,nHeight,GL_RGB,GL_FLOAT,pfData);

}

这相当于将数据从显存拷贝到主机内存,然后可以写入文件等。

说了这么多,最后还剩下一个片段着色器的编写。上面相当于把框架已经搭建好,然后只需要更改片段着色器实现不同的图像处理效果了。

这边就以一副风景画为例子实现集中不同的效果。

原图如下:

1、对比度调整,代码如下:

[cpp] view plaincopy
  1. #version 400 compatibility
  2. #extension GL_ARB_texture_rectangle : enable
  3. uniform sampler2DRect uImageUint;
  4. float uT = 0.5;
  5. out vec4 outColor;
  6. //图像对比度增强
  7. void main()
  8. {
  9. vec2 pos = gl_TexCoord[0].st;
  10. vec3 irgb = texture(uImageUint,pos).rgb;
  11. //vec3 target = vec3(128.0,128.0,128.0);
  12. vec3 target = vec3(0.0,0.0,0.0);
  13. outColor = vec4(mix(target,irgb,uT),1.0);
  14. }

处理后效果如下:

2、浮雕效果代码如下:

[cpp] view plaincopy
  1. #version 400 compatibility
  2. #extension GL_ARB_texture_rectangle : enable
  3. uniform sampler2DRect tex;
  4. out vec4 outColor;
  5. //浮雕效果
  6. void main()
  7. {
  8. vec2 pos = gl_TexCoord[0].st;
  9. //获得纹理的尺寸
  10. ivec2 vecSize = textureSize(tex);
  11. float ResS = float(vecSize.s);
  12. float ResT = float(vecSize.t);
  13. vec3 irgb = texture(tex,pos).rgb;
  14. vec2 stpp = vec2(-1.0,-1.0);
  15. vec3 c00 = texture(tex,pos).rgb;
  16. vec3 cp1p1 = texture(tex,pos+stpp).rgb;
  17. vec3 diffs = c00 - cp1p1;
  18. float maxV = diffs.r;
  19. if(abs(diffs.g) > abs(maxV)) maxV = diffs.g;
  20. if(abs(diffs.b) > abs(maxV)) maxV = diffs.b;
  21. float gray = clamp(maxV + 128,0.0,255.0);
  22. outColor = vec4(gray,gray,gray,1.0);
  23. }

处理后的图像如下:

3、颠倒显示

[cpp] view plaincopy
  1. #version 400 compatibility
  2. #extension GL_ARB_texture_rectangle : enable
  3. uniform sampler2DRect tex;
  4. out vec4 outColor;
  5. //图像翻转效果
  6. void main()
  7. {
  8. vec2 pos = gl_TexCoord[0].st;
  9. //获得纹理的尺寸
  10. ivec2 vecSize = textureSize(tex);
  11. int nWidth = (vecSize.s);
  12. int nHeight = (vecSize.t);
  13. pos = vec2(nWidth- pos.x-1,nHeight - pos.y - 1);
  14. vec3 irgb = texture(tex,pos).rgb;
  15. outColor = vec4(irgb,1.0);
  16. }

处理后效果如下:

4、图像黑白化

[cpp] view plaincopy
  1. #version 400 compatibility
  2. #extension GL_ARB_texture_rectangle : enable
  3. uniform sampler2DRect tex;
  4. const vec3 W = vec3(0.2125,0.7154,0.0721);
  5. out vec4 outColor;
  6. void main()
  7. {
  8. vec2 pos = gl_TexCoord[0].st;
  9. vec3 color = texelFetch(tex,ivec2(pos.x+0.5,pos.y+0.5)).rgb;
  10. float luminace = dot(color,W);
  11. outColor = vec4(luminace,luminace,luminace,1.0);
  12. //gl_FragColor = fResult;
  13. }

处理后图片如下:

5、图像的卷积,这个稍微复杂一点,其实也很简单,基本图像处理的东西。

[cpp] view plaincopy
  1. #version 400 compatibility
  2. #extension GL_ARB_texture_rectangle : enable
  3. uniform sampler2DRect tex;
  4. float fRadius = 2;
  5. out vec4 outColor;
  6. void main()
  7. {
  8. vec2 pos = gl_TexCoord[0].st;
  9. vec4 fSum = vec4(0.0,0.0,0.0,0.0);
  10. vec4 fTotal = vec4(0.0,0.0,0.0,0.0);
  11. vec4 fResult = vec4(0.0,0.0,0.0,0.0);
  12. ivec2 vecSize = textureSize(tex);
  13. for (float i = pos.x - fRadius; i < pos.x + fRadius + 0.5; i += 1.0)
  14. for (float j = pos.y - fRadius; j < pos.y + fRadius + 0.5; j += 1.0)
  15. {
  16. if (i >=0 && j >= 0 && i < vecSize.x && j < vecSize.y)
  17. {
  18. fSum += texture2DRect(tex,vec2(i+0.5,j+0.5));
  19. fTotal += vec4(1.0,1.0,1.0,1.0);
  20. }
  21. }
  22. vec4 color = texelFetch(tex,ivec2(pos.x+0.5,pos.y+0.5));
  23. fResult = fSum/fTotal;
  24. outColor = fResult;
  25. //gl_FragColor = fResult;
  26. }

处理后的效果如下:

上面这些都是最基本的图像处理操作,使用shader其实就是利用了显卡的并行数据处理能力,在今天的 大数据时代以及资源不足的手机上,如果能充分利用GPU的优势,对于图像的处理将会有速度上的很大提升。

GLSL实现图像处理相关推荐

  1. c语言中文渲染库,GLSL渲染编程基础与实例 (C#版本) 中文pdf扫描版[136MB]

    本书介绍了用GLSL语言进行三维渲染的方法,以及用大量的实例来展示如何进行GLSL编程.本书详细讲述了GLSL渲染流程: GLSL着色器编程:顶点光照:像素光照:卡通渲染.影线渲染.分形渲染.Gooc ...

  2. CC++图形图像处理开源库

    Google三维APIO3D O3D 是一个开源的 WebAPI 用来在浏览器上创建界面丰富的交互式的 3D 应用程序.这是一种基于网页的可控3D标准.此格式期望真正的基于浏览器,独立于操作系统之外, ...

  3. GPU 加速下的图像处理

    Instagram,Snapchat,Photoshop. 所有这些应用都是用来做图像处理的.图像处理可以简单到把一张照片转换为灰度图,也可以复杂到是分析一个视频,并在人群中找到某个特定的人.尽管这些 ...

  4. GLSL实现滤镜效果

    http://blog.csdn.net/neng18/article/details/38083987 "浮雕"图象效果是指图像的前景前向凸出背景.常见于一些纪念碑的雕刻上,要实 ...

  5. ios图像处理第2部分:核心图形,核心图像,GPUImage

    原文地址:http://www.raywenderlich.com/71151/image-processing-ios-part-2-core-graphics-core-image-gpuimag ...

  6. 详解OS X和iOS图像处理框架Core Image

     详解OS X和iOS图像处理框架Core Image width="22" height="16" src="http://hits.sinaj ...

  7. FFmpeg图像处理深度应用

    Photo by Kyle Loftus from Pexels 本演讲主要讲解如何通过FFmpeg作为一个主要的接口,将OpenGL.OpenCV以及诸如Tensorflow等AI框架以第三方库的形 ...

  8. GLSL/C++ 实现滤镜效果

    入门效果之浮雕 "浮雕"图象效果是指图像的前景前向凸出背景.常见于一些纪念碑的雕刻上.要实现浮雕事实上很easy.我们把图象的一个象素和左上方的象素进行求差运算.并加上一个灰度.这 ...

  9. 深度学习(三十五)异构计算GLSL学习笔记(1)

    异构计算GLSL学习笔记(1) 原文地址:http://blog.csdn.net/hjimce/article/details/51475644 作者:hjimce 最近开始学习深度学习的一些gpu ...

最新文章

  1. 小程序之 转发/分享
  2. c语言宏定义_掌握C语言,中文编程不是梦
  3. 滴滴行程单用的什么字体_打车就送冰淇淋!滴滴出行放大招,限时19天
  4. Cannot start compilation:the output path is not specifired for module “xxx“.Specify the output path
  5. 米度教育零基础三个月学会机器学习视频总结
  6. 卫星为什么在那么高的太空能看清地面?
  7. IOS开发-TableView表视图基础
  8. UVALive 5135 Mining Your Own Business 双连通分量
  9. ufldl学习笔记与编程作业:Linear Regression(线性回归)
  10. 逆袭?或将掌舵万亿SaaS巨头的Taylor竟是“天选之人”
  11. 钉钉机器人智能提醒_利用钉钉机器人和语雀提高协同办公效率
  12. 单片机技术及应用:基于proteus仿真的c语言程序设计,《单片机的C语言程序设计与应用——基于Proteus仿真(第3版)》怎么样_目录_pdf在线阅读 - 课课家教育...
  13. 练习27——IO流的所有用法(二)
  14. 总结一下Android中主题(Theme)的正确玩法
  15. 双系统卸载不干净,导致无法进入系统的引导修复办法(不用pe)
  16. 【论文阅读】SISR综述:From Beginner to Master: A Survey for Deep Learning-based Single-Image Super-Resolution
  17. 基于vmware16 和 ubuntu20.04, 搭建单节点 kubernetes 1.22.2
  18. SQL Server修改表结构,添加约束
  19. iOS因“自动订阅”被拒N次,最终解决!!!
  20. iOS 各种图片大小

热门文章

  1. java acm 母牛的故事_acm母牛的故事 的问题
  2. 湘潭大学计算机科学与技术录取分数线,2016年湘潭大学计算机科学与技术专业在湖南录取分数线...
  3. android模拟器越狱,关于iOS Simulator(模拟器)是否可以越狱。
  4. win7只能管理计算机软件吗,win7可以管理多少内存,win7内存优化软件
  5. Linux更新了源无法打开终端,在Deepin系统中检测不到升级的解决,需要切换系统源...
  6. php7比php5垃圾回收,PHP5和PHP7的垃圾回收机制有什么不同
  7. plus rss.php,dedecms织梦rss输出改成全文输出
  8. .net移动端开发_移动端开发1(前端一)
  9. 新计算机教师工作随笔反思,信息技术反思随笔 (2)
  10. 字节跳动《算法中文手册》火了,完整版 PDF 开放下载