0
$\begingroup$

what is the fastest algorithm to compute the gradient of the Gaussian blur of a (grayscale) image, with a blur radius of around 100 pixels, where smoothness of the result is important to me, i.e. no edges or discontinuities? I run the code on the GPU, if that makes any difference. What I'm currently doing, is the following:

vec2 gradOfBlur(sampler2D image, vec2 coord) {
  vec2 grad = vec2(0, 0);
  base = radius * floor(coord + 0.5);
  for(int dx = -10; dx <= 10; dx++) {
    for(int dy = -10; dy <= 10; dy++) {
      vec2 pos = base + vec2(dx, dy);
      vec2 diff = (pos - coord);
      float bell = exp(-0.1 * dot(diff, diff));
      float hgt = texture2D(texture, pos).a;
      grad.x += hgt * diff.x * bell;
      grad.y += hgt * diff.y * bell;
      sum += bell;
    }
  }
  return grad / sum;
}

I assumed the blur radius here to be 1, for simplicity, but the coordinates are not necessarily pixels. Also, it's OK if the gradient is scaled by some scalar, as I play around with a scalar in front of it anyway.

What I do is basically sampling the image at the 100 integer coordinates closest to my coordinate input, summing up the gradients (evaulated at the coordinate input) of the bell curves centered at those integer coordinates weighted by the image luminance, and dividing this sum of gradients by the sum of the values of the bell curves at my coordinate input.

The 0.1 parameter, which is the radius of the bell curves, is empirically estimated. I'm not sure if the division at the end is necessary, but it looks somehow reasonable. Using this method, my result is definitely very smooth, only when the coordinate input contains an integer value, there might be a very small step as new bell curves drop in and out of the sum.

What could I improve here?

$\endgroup$
6
  • 1
    $\begingroup$ Related: math.stackexchange.com/q/3766971/14578 $\endgroup$
    – D.W.
    Commented Feb 20, 2022 at 21:46
  • $\begingroup$ What do you mean by "smoothness"? $\endgroup$
    – D.W.
    Commented Feb 20, 2022 at 21:47
  • $\begingroup$ I mean that I want no steps, even at high resolution. The reason for this is that I use the result as some kind of bump map, which reflects a texture, so small discontinuities would be far more visible that if I look only at the blurred image. Will look at your link, many thanks! $\endgroup$
    – fweth
    Commented Feb 20, 2022 at 22:06
  • $\begingroup$ I should have specified that I want to look hat very large radii, not like $r=3$ as in this linked question but more like $r=100$. Which doesn't mean that I want to look at $10,000$ samples, but I look for a nice way to approximate the result from fewer samples. $\endgroup$
    – fweth
    Commented Feb 20, 2022 at 22:10
  • 1
    $\begingroup$ You can get good results by performing three or four steps of box filtering (say n), with sizes r/n. Use the fact that the filter is separable and use the integral image trick. In the end, take the gradient. $\endgroup$
    – user16034
    Commented Feb 21, 2022 at 15:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.