OpenGL高斯模糊

简介

描述

高斯模糊:使用高斯函数求出的值来作为卷积核进行图像的卷积运算。

卷积核总结

  1. 对图像进行降维以及特征提取,一般用于人工智能。
  2. 行数和列数均为奇数的矩阵。
  3. 卷积核元素的总和体现出输出的亮度。

高斯分布

在这里插入图片描述
f ( x ) = 1 2 π σ 2 e − ( x − μ ) 2 2 σ 2 f(x)=\frac{1}{\sqrt{2\pi\sigma^2}} {e^{-\frac{(x-\mu)^2}{2\sigma^2}}} f(x)=2πσ2 1e2σ2(xμ)2

高斯函数

G ( r ) = 1 2 π σ 2 N e − r 2 2 σ 2 G(r)=\frac{1}{\sqrt{2\pi\sigma^2}^{N}} {e^{-\frac{r^2}{2\sigma^2}}} G(r)=2πσ2 N1e2σ2r2
σ \sigma σ是正态函数的标准差, r r r代表模板中元素到模板中心的距离,又称为模糊半径 N N N代表处于 N N N维空间。
在这里插入图片描述

模糊半径

定义:欧式距离(N维向量的模)

欧几里得度量(euclidean metric)也称欧氏距离,是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。

卷积运算

卷积核

在这里插入图片描述

原图像

在这里插入图片描述

卷积结果

在这里插入图片描述

从原图像中提取与卷积同等大小的矩阵卷积核进行矩阵相乘运算。
6 = ( 0 − 2 + 0 ) + ( − 2 + 20 − 8 ) + ( 0 − 2 + 0 ) 6=(0-2+0)+(-2+20-8)+(0-2+0) 6=(02+0)+(2+208)+(02+0)

细节

卷积处理后,图像的每条边少了一个像素

解决:将已有的点拷贝到另一面的对应位置,也就是填充边。

高斯函数卷积核

假设 σ = 1.5 \sigma=1.5 σ=1.5,高斯卷积核如下。
在这里插入图片描述

实现

Python计算卷积核

import math

pi = 3.1415926
sigma = 1.5
e = 2.7182804

def G(r):
    return (1 / pow(math.sqrt(2 * pi * pow(sigma, 2)), 2)) * pow(e, -((r*r) / (2 * pow(sigma, 2))))

print("G(2) = %.7f" % G(2)) # G(2) = 0.0290803
print("G(1) = %.7f" % G(1)) # G(1) = 0.0566406
print("G(0) = %.7f" % G(0)) # G(0) = 0.0707355

OpenGL卷积核实现

#iChannel0 "file://images/img.jpg"      // 与shader脚本文件在同级目录下

// 高斯函数用到的常量
const float pi = 3.1415926;
const float sigma = 1.5;
const float e = 2.7182804;

// 高斯函数, r为欧式距离
float G(float r) {
    return (1.0 / pow(sqrt(2.0 * pi * pow(sigma, 2.0)), 2.0)) * pow(e, -((r*r) / (2.0 * pow(sigma, 2.0))));
}

// 主函数
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    // 计算uv, iResolution.xy是screen大小
    vec2 uv = fragCoord.xy / iResolution.xy;
    // 模拟像素
    vec2 pixed = 2.0 / iResolution.xy;
    // 相邻像素的uv
    vec2 texcoords[9];
    texcoords[0] = uv + vec2(-1.0, -1.0) * pixed;
    texcoords[1] = uv + vec2(0.0, -1.0) * pixed;
    texcoords[2] = uv + vec2(1.0, -1.0) * pixed;
    texcoords[3] = uv + vec2(-1.0, 0.0) * pixed;
    texcoords[4] = uv + vec2(0.0, 0.0) * pixed;
    texcoords[5] = uv + vec2(1.0, 0.0) * pixed;
    texcoords[6] = uv + vec2(-1.0, 1.0) * pixed;
    texcoords[7] = uv + vec2(0.0, 1.0) * pixed;
    texcoords[8] = uv + vec2(1.0, 1.0) * pixed;
    // 相邻像素对应的权重, 卷积核
    float w[9];
    w[0] = w[2] = w[6] = w[8] = G(2.0);
    w[1] = w[3] = w[5] = w[7] = G(1.0);
    w[4] = G(0.0);
    // 权重总和, 用来归一化卷积核
    float totalWeight = w[0] * 4.0 + w[1] * 4.0 + w[4];
    // 卷积运算
    vec4 gaussColor = vec4(0.0);
    for (int i = 0; i < 9; i++) {
        gaussColor += texture2D(iChannel0, texcoords[i]) * w[i] / totalWeight;
    }
    // 原图
    vec4 originalColor = texture2D(iChannel0, uv);
    // sin + time动态变化
    float normalTime = abs(sin(iTime));
    // mix输出颜色
    fragColor = mix(originalColor, gaussColor, normalTime);
}

OpenGL高斯模糊优化

优化点

  • 在片元着色器会重复计算卷积核,比较耗时;可以放在CPU计算,传给shader。
  • 3 × 3 3 \times 3 3×3卷积就需要在片元中纹理采样9次,可以降低为6次。
    1. 先进行横向模糊,采样3次,存储横向结果texture。
    2. 横向结果texture再进行纵向模糊,采样3次。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值