QT

推荐列表 站点导航

当前位置:首页 > 脚本编程 > QT >

Qt3D的研究(九):尝试另外一种边缘检测方法

来源:网络整理  作者:  发布时间:2020-12-26 16:36
Qt3D的研究(九):尝试另外一种边缘检测方法三维应用程序,通过FBO,将3D图像渲染成纹理,然后对渲染成的纹理进...
Qt 3D的研究(九):尝试另外一种边缘检测方法

三维应用程序,通过FBO,将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,最终显示在屏幕上的,是风格化后的图案。上一次我使用了一种普通的图像处理方法:索贝尔边缘检测法,与我们的卡通渲染结合起来,实现了这样的效果,接着,我将采用另外一种边缘检测方法——普雷维特(Prewitt)边缘检测方法来重新渲染图案。

蒋彩阳原创文章,首发地址:。欢迎同行前来探讨。

首先让我们看看上一次的截图:

Qt3D的研究(九):尝试另外一种边缘检测方法

我们看到,本不应该是边缘的机身部分,由于离散的调色,被索贝尔算子边缘检测一算,也被误认为是边缘了,同时,在背景与机身颜色不明显的部分,也由于采用不适当的阈值,不被认为是边缘。所以我想有没有一种方法能够解决这个问题呢?于是我采取了这样的方法:

1、 第一遍的render pass,取的不是卡通着色的颜色图,而是深度图;

2、 将深度图渲染至纹理;

3、 对该纹理进行边缘检测;

Qt3D的研究(九):尝试另外一种边缘检测方法

4、 与卡通着色的图进行叠加,做成效果图。

Qt3D的研究(九):尝试另外一种边缘检测方法

如何在GLSL中将片元的深度信息提取出来?这里我参考了前辈的博客,然后写出了这样的GLSL代码:

// Depth.vert #version 100 // Qt 3D默认提供的参数 attribute vec3 vertexPosition; uniform mat4 modelView; uniform mat4 mvp; void main( void ) { gl_Position = mvp * vec4( vertexPosition, 1.0 ); } // Depth.frag #version 110 // 自己提供的参数 bool inBetween( float v, float min, float max ) { return v > min && v < max; } void main( void ) { float exp = 256.0; gl_FragColor = vec4( vec3( pow( gl_FragCoord.z, exp ) ), 1.0); }

因为gl_FragCoord.z表示的片元深度信息相互之间非常接近,我们需要一个指数乘幂操作将这样的区别放大,这样才能区分不同的深度的值。

紧接着,我们将Prewitt算子替换掉Sobel算子,最终的着色器代码如下:

// Ouput.vert #version 100 // Qt 3D默认提供的参数 attribute vec4 vertexPosition; uniform mat4 modelMatrix; // 自己提供的参数 void main( void ) { gl_Position = modelMatrix * vertexPosition; } // Output.frag #version 100 // 自己提供的参数 uniform sampler2D colorAttachTex; //uniform sampler2D depthAttachTex; uniform vec2 texSize; uniform float texOffsetX; uniform float texOffsetY; float gray( vec4 color ) { return dot( color.xyz, vec3( 0.299, 0.587, 0.114 ) ); } void main( void ) { vec4 texColor[9]; texColor[0] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, texOffsetY ) ); texColor[1] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) ); texColor[2] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, texOffsetY ) ); texColor[3] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, 0 ) ); texColor[4] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, 0.0 ) ); texColor[5] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, 0 ) ); texColor[6] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, -texOffsetY ) ); texColor[7] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) ); texColor[8] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, -texOffsetY ) ); // 普雷维特算子 float prewitt_x[9]; prewitt_x[0] = -1.0; prewitt_x[1] = 0.0; prewitt_x[2] = 1.0; prewitt_x[3] = -1.0; prewitt_x[4] = 0.0; prewitt_x[5] = 1.0; prewitt_x[6] = -1.0; prewitt_x[7] = 0.0; prewitt_x[8] = 1.0; float prewitt_y[9]; prewitt_y[0] = 1.0; prewitt_y[1] = 1.0; prewitt_y[2] = 1.0; prewitt_y[3] = 0.0; prewitt_y[4] = 0.0; prewitt_y[5] = 0.0; prewitt_y[6] = -1.0; prewitt_y[7] = -1.0; prewitt_y[8] = -1.0; // 卷积操作 vec4 edgeX = vec4( 0.0 ); vec4 edgeY = vec4( 0.0 ); for ( int i = 0; i < 9; ++i ) { edgeX += texColor[i] * prewitt_x[i]; edgeY += texColor[i] * prewitt_y[i]; } vec4 edgeColor = sqrt( ( edgeX * edgeX ) + ( edgeY * edgeY ) ); float edgeIntensity = gray( edgeColor ); const float threshold = 0.05; if ( edgeIntensity > threshold ) gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); else discard; }

由于代码比较长,我已经将其放至github中。有需要同行朋友们,可以从github中获取代码。

https://github.com/jiangcaiyang/Test-Qt-3D-8

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://www.juheyunku.com/jiaob/qt/9404.shtml

相关文章
最新文章
Qt之QCustomPlot绘图(一)配 Qt之QCustomPlot绘图(一)配

时间:2020-12-27

QStandardItemModel角色控制及 QStandardItemModel角色控制及

时间:2020-12-27

物联网MQTT协议分析和开源 物联网MQTT协议分析和开源

时间:2020-12-27

PyQt5学习笔记14 初识pyqt多 PyQt5学习笔记14 初识pyqt多

时间:2020-12-26

创建一个QtQuickUI项目 创建一个QtQuickUI项目

时间:2020-12-26

Qt3D的研究(九):尝试另 Qt3D的研究(九):尝试另

时间:2020-12-26

Qt3D的研究(二) Qt3D的研究(二)

时间:2020-12-26

Qt UserInfo Qt UserInfo

时间:2020-12-26

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

Qt3D的研究(九):尝试另外一种边缘检测方法

2020-12-26 编辑:

Qt 3D的研究(九):尝试另外一种边缘检测方法

三维应用程序,通过FBO,将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,最终显示在屏幕上的,是风格化后的图案。上一次我使用了一种普通的图像处理方法:索贝尔边缘检测法,与我们的卡通渲染结合起来,实现了这样的效果,接着,我将采用另外一种边缘检测方法——普雷维特(Prewitt)边缘检测方法来重新渲染图案。

蒋彩阳原创文章,首发地址:。欢迎同行前来探讨。

首先让我们看看上一次的截图:

Qt3D的研究(九):尝试另外一种边缘检测方法

我们看到,本不应该是边缘的机身部分,由于离散的调色,被索贝尔算子边缘检测一算,也被误认为是边缘了,同时,在背景与机身颜色不明显的部分,也由于采用不适当的阈值,不被认为是边缘。所以我想有没有一种方法能够解决这个问题呢?于是我采取了这样的方法:

1、 第一遍的render pass,取的不是卡通着色的颜色图,而是深度图;

2、 将深度图渲染至纹理;

3、 对该纹理进行边缘检测;

Qt3D的研究(九):尝试另外一种边缘检测方法

4、 与卡通着色的图进行叠加,做成效果图。

Qt3D的研究(九):尝试另外一种边缘检测方法

如何在GLSL中将片元的深度信息提取出来?这里我参考了前辈的博客,然后写出了这样的GLSL代码:

// Depth.vert #version 100 // Qt 3D默认提供的参数 attribute vec3 vertexPosition; uniform mat4 modelView; uniform mat4 mvp; void main( void ) { gl_Position = mvp * vec4( vertexPosition, 1.0 ); } // Depth.frag #version 110 // 自己提供的参数 bool inBetween( float v, float min, float max ) { return v > min && v < max; } void main( void ) { float exp = 256.0; gl_FragColor = vec4( vec3( pow( gl_FragCoord.z, exp ) ), 1.0); }

因为gl_FragCoord.z表示的片元深度信息相互之间非常接近,我们需要一个指数乘幂操作将这样的区别放大,这样才能区分不同的深度的值。

紧接着,我们将Prewitt算子替换掉Sobel算子,最终的着色器代码如下:

// Ouput.vert #version 100 // Qt 3D默认提供的参数 attribute vec4 vertexPosition; uniform mat4 modelMatrix; // 自己提供的参数 void main( void ) { gl_Position = modelMatrix * vertexPosition; } // Output.frag #version 100 // 自己提供的参数 uniform sampler2D colorAttachTex; //uniform sampler2D depthAttachTex; uniform vec2 texSize; uniform float texOffsetX; uniform float texOffsetY; float gray( vec4 color ) { return dot( color.xyz, vec3( 0.299, 0.587, 0.114 ) ); } void main( void ) { vec4 texColor[9]; texColor[0] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, texOffsetY ) ); texColor[1] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) ); texColor[2] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, texOffsetY ) ); texColor[3] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, 0 ) ); texColor[4] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, 0.0 ) ); texColor[5] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, 0 ) ); texColor[6] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, -texOffsetY ) ); texColor[7] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) ); texColor[8] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, -texOffsetY ) ); // 普雷维特算子 float prewitt_x[9]; prewitt_x[0] = -1.0; prewitt_x[1] = 0.0; prewitt_x[2] = 1.0; prewitt_x[3] = -1.0; prewitt_x[4] = 0.0; prewitt_x[5] = 1.0; prewitt_x[6] = -1.0; prewitt_x[7] = 0.0; prewitt_x[8] = 1.0; float prewitt_y[9]; prewitt_y[0] = 1.0; prewitt_y[1] = 1.0; prewitt_y[2] = 1.0; prewitt_y[3] = 0.0; prewitt_y[4] = 0.0; prewitt_y[5] = 0.0; prewitt_y[6] = -1.0; prewitt_y[7] = -1.0; prewitt_y[8] = -1.0; // 卷积操作 vec4 edgeX = vec4( 0.0 ); vec4 edgeY = vec4( 0.0 ); for ( int i = 0; i < 9; ++i ) { edgeX += texColor[i] * prewitt_x[i]; edgeY += texColor[i] * prewitt_y[i]; } vec4 edgeColor = sqrt( ( edgeX * edgeX ) + ( edgeY * edgeY ) ); float edgeIntensity = gray( edgeColor ); const float threshold = 0.05; if ( edgeIntensity > threshold ) gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); else discard; }

由于代码比较长,我已经将其放至github中。有需要同行朋友们,可以从github中获取代码。

https://github.com/jiangcaiyang/Test-Qt-3D-8

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://www.juheyunku.com/jiaob/qt/9404.shtml

相关文章

风云图片

推荐阅读

返回QT频道首页