高斯模糊

高斯模糊应用领域我就不过多讲解,想了解自己去了解
高斯模糊有
一维公式
在这里插入图片描述

二维公式
在这里插入图片描述

当然我们图像是二维的
但是实际上二维公式用于计算那是消耗大量的算力的,所以往往
通过执行水平方向的一维 跟 垂直方向上的一维公式进行处理的

废话不多说,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使用的场景是多变的
所以,如果有遇到不同硬件渲染引擎的问题的可以分析到这里

更多推荐