【问题标题】:Calculating offset of linear gaussian blur based on variable amount of weights基于可变权重计算线性高斯模糊的偏移量
【发布时间】:2012-08-31 01:18:25
【问题描述】:

我最近一直在研究通过使用线性采样方法而不是离散方法来优化高斯模糊着色器。

我读了一篇内容丰富的文章:

Efficient Gaussian Blur With Linear Sampling

在这样的两个纹素合并的情况下,我们必须调整坐标,使确定的坐标到纹素#1 中心的距离应该等于纹素#2 的权重除以两个权重的总和。在同一种风格下,确定的坐标到 texel#2 中心的距离应该等于 texel#1 的权重除以两个权重之和。

虽然我理解这背后的逻辑,但我不确定他们是如何得出给定权重的偏移量数字的。有没有人愿意为我阐明这一点,并解释一下,给定统一的权重变量,我们如何计算正确的偏移量?

关于非硬编码偏移,我发现另一篇文章推荐了一种计算偏移的方法,但是没有针对可变数量的样本发布解决方案。我怎样才能做到这一点?

vec2 offsets[3];
offsets[0] = vec2(0.0, 0.0);

offsets[1] = vec2(dFdx(gl_TexCoord[0].s), dFdy(gl_TexCoord[0].t));

offsets[2] = offsets[1] + offsets[1];

【问题讨论】:

  • 对于任何阅读本文的人,我最终计算出我的体重值如下:exp(-(ii)/(2*sigmasigma))/(sqrt(2 *常数::pi)*sigma);

标签: glsl blur gaussian sampling


【解决方案1】:

我刚刚看到同一篇文章,发现它也非常有用。其中给出了计算权重和偏移量的公式:


(来源:rastergrid.com

作者使用帕斯卡三角形中的第 12 行得出权重。因此,例如第二个偏移量是通过以下方式计算的:

1.3846153846 = (1 * 792 + 2 * 495) / (792 + 495)

第二个权重的计算公式:

0.1945945946 = (792 + 495) / 4070

我不确定你通过计算给定统一权重变量的偏移量是什么意思,但如果有帮助,我在这篇文章的末尾包含了一个 C++ 程序,它输出帕斯卡中任意行的偏移量和权重三角形。

如果我了解您关于非硬编码偏移量的问题,那么您希望能够在 GLSL 中即时计算偏移量吗?您可以通过移植下面的程序来做到这一点,但您仍然需要对二项式系数进行硬编码,或者还需要即时计算这些系数。然而,这将是昂贵的,因为它必须为每个像素完成。我认为更好的选择是预先计算 C(或您使用的任何编程语言)中的偏移量和权重,然后将它们绑定到 GLSL 中的统一数组值。这是我的意思的 GLSL sn-p:

    uniform float offset[5];
    uniform float weight[5];"
    uniform int numOffsets;

您需要将“5”替换为您计划使用的最大偏移量/权重数,并将 numOffsets 设置为您用于特定操作的数字。

这是输出权重和偏移量的程序。 “coeffs”应替换为帕斯卡表中所需行的二项式系数。此处包含的来自第 22 行

#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  float coeffs[] = { 705432, 646646, 497420, 319770, 170544, 74613, 26334, 7315, 1540, 231 };
  double total = coeffs[0];
  for (int i = 1; i < sizeof(coeffs) / sizeof(float); i++)
    {
      total += 2 * coeffs[i];
    }
  vector<float> offsets;
  vector<float> weights;

  offsets.push_back(0);
  weights.push_back(coeffs[0] / total);

  for (int i = 1;  i <= (sizeof(coeffs) / sizeof(float) - 1) / 2; i++) 
    {
      int index = (i - 1) * 2 + 1;
      float weight = coeffs[index] + coeffs[index + 1]; 
      offsets.push_back((coeffs[index] * index + coeffs[index + 1] * (index + 1)) /  weight);
      weights.push_back(weight / total);
    }

  for (int i = 0; i < offsets.size(); i++)
    {
      cout << offsets[i] << ", ";
    }
  cout << "\n";

  for (int i = 0; i < weights.size(); i++)
    {
      cout << weights[i] << ", ";
    }
  cout << "\n";
}

【讨论】:

  • 感谢史蒂夫解决了我最初的困惑。请问你为什么选择第22行?
  • 我使用第 22 行来试验 19 抽头过滤器。本文将第 12 行用于 9 抽头过滤器。通常,对于 N-tap 过滤器,您希望使用第 (N + 3) 行。
  • 只是想补充一点,我不确定一般的经验法则是否是使用第 N+3 行,但如果你想像文章建议的那样忽略边缘系数,那就是遵循的方法。
  • 这似乎是一个很好的经验法则。我已经比较了差异,非常值得减少这些额外的迭代。
  • 我也觉得使用第 22 行而不是 FBO 之间的“乒乓”是有益的。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
相关资源
最近更新 更多