目录
- 高斯模糊
- sigma获取
- 加权均值获取
- 高斯二维公式实现
- 高斯一维公式实现
- 使用
- 总结
高斯模糊
高斯模糊应用领域我就不过多讲解,想了解自己去了解
高斯模糊有
一维公式
二维公式
当然我们图像是二维的
但是实际上二维公式用于计算那是消耗大量的算力的,所以往往
通过执行水平方向的一维 跟 垂直方向上的一维公式进行处理的
废话不多说,qml怎么实现搞图像处理效果呢?
import QtGraphicalEffects 1.15
直接使用官方提供的GaussianBlur就可以了, 但是本章不是将怎么用这个
而是怎么用shadereffect 实现 自己的MGaussianBlur.qml
通过设置其属性
source要处理的对象,radius模糊半径
sigma获取
sigma = (radius * 2 + 1) *0.5
加权均值获取
[(模糊半径*2 + 1)上的每个像素 * 各自权重)] 的 累加值 / 总权重值
高斯二维公式实现
MGaussianBlur.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Item {
id: control
property int radius: 2
property var source
property color color: "#00ff00"
property bool cache: true //缓存
property bool alphaOnly: false //只用透明度, 则color生效
property bool surround: true //环绕对象
// 缓存输入对象
ShaderEffectSource {
id: proxySource
sourceItem: control.source
hideSource: false
smooth: true
visible: false
sourceRect: surround? Qt.rect(-control.radius,
-control.radius,
parent.width + 2* control.radius,
parent.height+ 2* control.radius):
Qt.rect(0, 0, 0, 0)
}
// 缓存模糊后对象
ShaderEffectSource{
anchors.fill: blur
sourceItem: blur
hideSource: visible
smooth: true
visible: cache
}
ShaderEffect{
id: blur
x: surround? -control.radius: 0
y: surround? -control.radius: 0
width: surround? parent.width + 2*control.radius: parent.width
height: surround? parent.height + 2*control.radius: parent.height
property Item source: proxySource
property real qt_Radius: control.radius //扩散半径
property real qt_sigma: (2.0 * control.radius + 1.0) * 0.5
property vector2d qt_Size : Qt.vector2d(width,height);
property real qt_pi: Math.PI
property bool qt_AlphaOnly: control.alphaOnly
property vector4d qt_Color: Qt.vector4d(control.color.r,
control.color.g,
control.color.b,
control.color.a)
fragmentShader: "
#define pow2(x) (x * x)
varying vec2 qt_TexCoord0;
uniform sampler2D source;
uniform float qt_Radius;
uniform float qt_sigma;
uniform float qt_pi;
uniform vec2 qt_Size;
uniform vec4 qt_Color;
uniform bool qt_AlphaOnly;
float gaussian(vec2 i) {
return 1.0 / (qt_pi * pow2(qt_sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(qt_sigma))));
}
void main() {
vec4 color;
float total = 0.0;
float weight;
vec2 offset;
vec2 scale = vec2(1.0) / qt_Size;
vec2 texCoord = qt_TexCoord0;
for (float x = -qt_Radius; x <= qt_Radius; x++) {
for (float y = -qt_Radius; y <= qt_Radius; y++) {
offset = vec2(x,y);
weight = gaussian(offset);
color += texture2D(source, texCoord + offset * scale) * weight;
total += weight;
}
}
color = color / total;
if(qt_AlphaOnly && color != vec4(0.0)){
gl_FragColor = vec4(qt_Color.rgb,color.a);
}else{
gl_FragColor = color;
}
}
"
}
}
高斯一维公式实现
import QtQuick 2.12
import QtQuick.Window 2.12
Item {
id: control
property int radius: 2
property var source
property color color: "#00ff00"
property bool cache: true //缓存
property bool alphaOnly: false //只用透明度, 则color生效
property bool surround: true //环绕对象
// 缓存输入对象
ShaderEffectSource {
id: proxySource
sourceItem: control.source
hideSource: false
smooth: true
visible: false
sourceRect: surround? Qt.rect(-control.radius,
-control.radius,
parent.width + 2* control.radius,
parent.height+ 2* control.radius):
Qt.rect(0, 0, 0, 0)
}
// 缓存模糊后对象
ShaderEffectSource{
anchors.fill: vertical_Blur
sourceItem: vertical_Blur
hideSource: visible
smooth: true
visible: cache
}
ShaderEffect{
id: horizontal_Blur
x: surround? -control.radius: 0
y: surround? -control.radius: 0
width: surround? parent.width + 2*control.radius: parent.width
height: surround? parent.height + 2*control.radius: parent.height
property Item source: proxySource
property real qt_Radius: control.radius //扩散半径
property real qt_sigma: (2.0 * control.radius + 1.0) * 0.5
property vector2d qt_Size : Qt.vector2d(width,height);
property real qt_pi: Math.PI
property bool qt_AlphaOnly: control.alphaOnly
property vector2d qt_Direction: Qt.vector2d(1.0,0.0)
property vector4d qt_Color: Qt.vector4d(control.color.r,
control.color.g,
control.color.b,
control.color.a)
layer.enabled: true
layer.smooth: true
visible: false
blending: false
fragmentShader: "
#define pow2(x) (x * x)
varying vec2 qt_TexCoord0;
uniform sampler2D source;
uniform float qt_Radius;
uniform float qt_sigma;
uniform float qt_pi;
uniform vec2 qt_Size;
uniform vec4 qt_Color;
uniform bool qt_AlphaOnly;
uniform vec2 qt_Direction;
float gaussian(float i) {
return 1.0 / sqrt(qt_pi * pow2(qt_sigma)) * exp(-pow2(i) / (2.0 * pow2(qt_sigma)));
}
void main() {
vec4 color;
float total = 0.0;
float weight;
float offset;
vec2 scale = vec2(1.0) / qt_Size;
vec2 texCoord = qt_TexCoord0;
weight = gaussian(0.0);
color += texture2D(source, texCoord) * weight;
total += weight;
for (float x = 1.0; x <= qt_Radius; ++x) {
offset = x;
weight = gaussian(offset);
color += texture2D(source, texCoord + offset * scale * qt_Direction ) * weight;
color += texture2D(source, texCoord - offset * scale * qt_Direction ) * weight;
total += weight * 2.0;
}
color = color / total;
gl_FragColor = color;
}
"
}
ShaderEffect{
id: vertical_Blur
x: surround? -control.radius: 0
y: surround? -control.radius: 0
width: surround? parent.width + 2*control.radius: parent.width
height: surround? parent.height + 2*control.radius: parent.height
property Item source: horizontal_Blur
property real qt_Radius: control.radius //扩散半径
property real qt_sigma: (2.0 * control.radius + 1.0) * 0.5
property vector2d qt_Size : Qt.vector2d(width,height);
property real qt_pi: Math.PI
property bool qt_AlphaOnly: control.alphaOnly
property vector2d qt_Direction: Qt.vector2d(0.0,1.0)
property vector4d qt_Color: Qt.vector4d(control.color.r,
control.color.g,
control.color.b,
control.color.a)
fragmentShader: "
#define pow2(x) (x * x)
varying vec2 qt_TexCoord0;
uniform sampler2D source;
uniform float qt_Radius;
uniform float qt_sigma;
uniform float qt_pi;
uniform vec2 qt_Size;
uniform vec4 qt_Color;
uniform bool qt_AlphaOnly;
uniform vec2 qt_Direction;
float gaussian(float i) {
return 1.0 / sqrt(qt_pi * pow2(qt_sigma)) * exp(-pow2(i) / (2.0 * pow2(qt_sigma)));
}
void main() {
vec4 color;
float total = 0.0;
float weight;
float offset;
vec2 scale = vec2(1.0) / qt_Size;
vec2 texCoord = qt_TexCoord0;
weight = gaussian(0.0);
color += texture2D(source, texCoord) * weight;
total += weight;
for (float x = 1.0; x <= qt_Radius; ++x) {
offset = x;
weight = gaussian(offset);
color += texture2D(source, texCoord + offset * scale * qt_Direction ) * weight;
color += texture2D(source, texCoord - offset * scale * qt_Direction ) * weight;
total += weight * 2.0;
}
color = color / total;
if(qt_AlphaOnly && color != vec4(0.0)){
gl_FragColor = vec4(qt_Color.rgb,color.a) * qt_Color.a;
}else{
gl_FragColor = color;
}
}
"
}
}
使用
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column{
spacing: 10
Row{
SpinBox{
onValueModified: {
blur.radius = value
}
}
}
Row{
Image {
id: img
width: 100
height: 100
source: "qrc:/firefox-logo.svg"
}
MGaussianBlur{
id: blur
width: 100
height: 100
source: img
radius: 4
//alphaOnly: true
}
}
}
}
总结
复杂我的代码,电脑应该是正常使用的,但是qt使用的场景是多变的
所以,如果有遇到不同硬件渲染引擎的问题的可以分析到这里