Page 1 of 1

selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T14:48:01-07:00
by HugoRune
I am trying to replicate the effects of the Gimp filter "selective gaussian blur".
I find it very useful in removing noise from scans.
Reference:
http://docs.gimp.org/en/plug-in-sel-gauss.html
http://www.gimp.org/tutorials/Selective_Gaussian_Blur/

I tried the "adaptive-blur" switch, but I am not sure what it is supposed to do
"convert -adaptive-blur 0x20" ran for allmost an hour, and seemed to actually increase the noise, rather than blurring anything.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T15:16:52-07:00
by fmw42
HugoRune wrote:I am trying to replicate the effects of the Gimp filter "selective gaussian blur".
I find it very useful in removing noise from scans.
Reference:
http://docs.gimp.org/en/plug-in-sel-gauss.html
http://www.gimp.org/tutorials/Selective_Gaussian_Blur/

I tried the "adaptive-blur" switch, but I am not sure what it is supposed to do
"convert -adaptive-blur 0x20" ran for allmost an hour, and seemed to actually increase the noise, rather than blurring anything.

You might want to try my gaussianedge script and see if that helps. see http://www.fmwconcepts.com/imagemagick/index.php

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T15:50:11-07:00
by HugoRune
fmw42 wrote: You might want to try my gaussianedge script and see if that helps. see http://www.fmwconcepts.com/imagemagick/index.php
I am using windows, but I may be able to figure out the equivalent windows commands from the script.

However, as far as I can make out, the script blurs or sharpens near edges, while I want to blur the opposite region

I could apply a -negate to the edge mask, but I am not sure that would give the same results as Gimp.

in Gimp "blur is applied only if the difference between its value and the value of the surrounding pixels is less than a defined Delta value", and I am not sure how to translate that delta for imagemagick.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T17:07:30-07:00
by fmw42
HugoRune wrote:
fmw42 wrote: You might want to try my gaussianedge script and see if that helps. see http://www.fmwconcepts.com/imagemagick/index.php
I am using windows, but I may be able to figure out the equivalent windows commands from the script.

However, as far as I can make out, the script blurs or sharpens near edges, while I want to blur the opposite region

I could apply a -negate to the edge mask, but I am not sure that would give the same results as Gimp.

in Gimp "blur is applied only if the difference between its value and the value of the surrounding pixels is less than a defined Delta value", and I am not sure how to translate that delta for imagemagick.
Yes, sorry, I have not looked at the script in a while and was not sure exactly what you wanted. Also it is true that converting from unix bash script to windows is not trivial. Take a look at my isonoise script. That may be closer to what you want.

Alternately, if I understand your selective gaussian goal, you might try the following:

What you seem to want is to get a mix of the image. Where a pixel is close to the average of its neighbors by some threshold, you want to do a gaussian blur (-blur) and where it is not close, you want to leave the image alone. That is not hard. You create a mask image to control whether to use the original image or the gaussian blurred image. You can create the mask image by doing a local average on the image by using a convolution with equal weights. Lets say for argument a 3x3 neighborhood average is equivalent to -convolve "1,1,1,1,1,1,1,1,1". Then you take the difference (-compose difference -composite) of the convolved image and the original and threshold it using -threshold.

Steps:

1. Create gaussian blurred image (select larger sigma for more blurring)
convert image -blur 0xsigma gaussianimage

2. Create local average image (use larger kernel, say 5x5 or 25 ones with commas between if desired for a larger neighborhood average)
convert image -convolve "1,1,1,1,1,1,1,1,1" averageimage

3. Create mask image (negate threshold so that small differences are white and large differences are black)
convert image averageimage -compose difference -composite -threshold XX% -negate maskimage

4 Combine image and gaussian using mask image
convert image gaussianimage maskimage -composite resultimage

You will have to play with the various parameters. I have not tested this and I may have some misconception about what you are trying to do, but let us know how that works.

Note an alternate and perhaps more flexible alternate to -convolve is to use -blur radiusx65000. That will give a similar equal weight average, but you have easier control over the distance (radius) of the average as you can use fractional values. Something like radius=1 or 1.5 should be nearly equivalent to a 3x3 convolve.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T18:44:47-07:00
by HugoRune
What you seem to want is to get a mix of the image. Where a pixel is close to the average of its neighbors by some threshold, you want to do a gaussian blur (-blur) and where it is not close, you want to leave the image alone.
I am not absolutely sure what I want either :)
What you describe is somewhat close, but not exactly what I mean

Imagine a noisy image of a checkerboard: i want to blur each square without mixing colors between the squares.
(noisy in the sense of slight variations in brightness and hue, like you get from a CCD sensor, not salt&pepper noise)

What I want is this:
Blur each pixel, but only use nearby pixels that are close in brightness/color for calculating the blurred value.
At least that is what I think the gimp filter does.

Looking at the source of the selective gaussion blur filter
(http://www.koders.com/c/fid95016D3A30DD ... spx?s=suck)
I think the effect in gimp works like this:

Code: Select all

For each pixel A
  for each pixel B near pixel A // for a blur with radius R check all pixels within that radius
    sum=0
    fact=0
    if |A-B| < max_delta  // the pixels are close in value
       sum += gaussian_factor(pos(A)-pos(B)) * B
       fact ++
  if fact > 0
    new_A = sum / fakt
  else
    new_A = A
it is quite effective in removing certain noise, as shown here, at the bottom of the page:
http://www.gimp.org/tutorials/Selective_Gaussian_Blur/

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-18T19:09:35-07:00
by fmw42
What I want is this:
Blur each pixel, but only use nearby pixels that are close in brightness/color for calculating the blurred value.
At least that is what I think the gimp filter does.
I don't think this is easy in IM scripting. You probably need to write a new function.

I wrote some similar script functions that were rather complex and slow in my statsfilt (http://www.fmwconcepts.com/imagemagick/ ... /index.php). I thought of doing something similar to what you want, but could not figure out how to do that effectively and efficiently as a script. You may be able to do better scripting with PerlMagick.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-19T10:48:18-07:00
by fmw42
This is another selective average approach, but won't do the gaussian, only a simple average.

1) Create 8 shifted versions of the image, each shifted 1 pixel in each x and/or y direction (replicating the edge pixels as needed)
2) For each shifted image, find the difference between the image and shifted image and threshold to make a mask image.
3) Composite the image and shifted version using the mask image so that if the difference is low, you use the shifted image and if the difference is high, you use the original image.
4) Use -average on these 8 or 9 (including the original) images to create your result.

If IM had a weighted average function, you could manually compute the gaussian weights to use when doing the average for each offset location. But I don't know if that is currently possible. Can someone tell me if composite -blend allows an arbitrary number of images. If not, then this could be used to do the averaging 2 at a time, with the appropriate calculation of the weights that takes into account both the sequential nature and the gaussian weights.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-19T11:28:08-07:00
by magick
We have a new -selective-blur option coded up and we're testing now. It will take a few days before its ready to test.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-19T15:48:42-07:00
by HugoRune
magick wrote:We have a new -selective-blur option coded up and we're testing now. It will take a few days before its ready to test.
very cool, did you implement that just now, or was that a coincidence?

There is one improvement I thought of in comparison to the gimp algorithm:
Maybe instead of a fixed threshold for selecting close colors, use a gaussian for this too.
I.e. blur each pixel, but weight nearby pixels by their spatial distance and their colorspace distance.

Code: Select all

For each pixel A
  sum=0
  fact=0
  for each pixel B near pixel A // for a blur with radius R check all pixels within that radius
    if |value(A)-value(B)| < max_delta  // the pixels are close in value
       sum += gaussian_factor(sigma1, pos(A)-pos(B)) * gaussian_factor(sigma2, value(A)-value(B)) * value(B)
       fact += gaussian_factor(sigma2, value(A)-value(B)) 
  new_A = sum / fact

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-19T17:58:20-07:00
by magick
Whenever we implement a new option there is a period of review where we fix bugs and improve based on feedback. Look for the option in ImageMagick 6.5.0-3 in the next few days and report back here if you feel there is room for improvement.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-21T18:11:52-07:00
by fmw42
Here are some tests of the new -selective-blur in IM 6.5.0-3

original:
Image

GIMP selective gaussian blur result:
Image


IM results:
convert taj_orig.jpg -selective-blur 0x1+10% taj_sblur_0x1_10.jpg
Image

convert taj_orig.jpg -selective-blur 0x1+15% taj_sblur_0x1_15.jpg
Image

convert taj_orig.jpg -selective-blur 0x1+20% taj_sblur_0x1_20.jpg
Image

convert taj_orig.jpg -selective-blur 0x3+10% taj_sblur_0x3_10.jpg
Image

convert taj_orig.jpg -selective-blur 0x3+15% taj_sblur_0x3_15.jpg
Image

convert taj_orig.jpg -selective-blur 0x3+20% taj_sblur_0x3_20.jpg
Image


Seems like the smaller sigma value (for smaller distance) 0x1 gives better (less over-blurred) result than the larger sigma value (larger distance) 0x3. The 0x1+15% seems closest to the GIMP result.

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-22T06:49:08-07:00
by HugoRune
The new selective blur works nicely! Thanks a lot!

I'd like to test if a gaussian distribution for choosing 'close' colors could give a bit better results than a hard contrast threshold, and am currently struggling with the code. (something like -selective-blur 0x10+0x20%, where the influence of each pixel depends on the spatial distance as well as the colorspace distance)
It might avoid the problem of 'quantizing' colors in a smooth gradient, and thereby creating new edges.
I do not really have any facts to back up this assumption so far.

Image -> Image
Image -> Image
with -selective-blur 0x10+10%



The selective blur is of course currently much slower than a regular blur, especially for larger radii > 5-10 and megapixel photos. I was wondering how to speed this up.

I am not sure whether the standard equivalency of one horizontal + one vertical blur being equivalent to one 2D gaussian blur could be modified to apply to the selective blur.

I tested the other equivalency, one big blur being equivalent to several smaller blurs, but there are some differences, I am not sure how much is due to rounding, or whether the contrast threshold needs to be changed in the smaller blurs for the equivalency to hold.

Image -> Image -> Image -> Image
original --> 1x selective-blur 0x10+10% -> 2x selective-blur 0x5+10% -> 5x selective-blur 0x2+10%

Image -> Image -> Image ->Image
original ----> 1x selective-blur 0x10+10% ----> 2x selective-blur 0x5+10% ----> 5x selective-blur 0x2+10%

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-22T11:21:19-07:00
by HugoRune
I have been looking trough the source of the selective-blur algorithm to understand the results, and it is somewhat confusing:

As far as i can make out, the algorithm does not perform a gaussian blur, but a square box-blur, i.e. the image is convolved with a 1,...,1 kernel, limited by the contrast threshold, and the sigma value is only used in calculating the width of the kernel?

Is that how it is supposed to work?
There seems to be little point for a sigma in a box blur.

Example: effect.c:3817

Code: Select all

                  pixel.red+=(p+u+j)->red;
For a gaussian blur this would have to be something like

Code: Select all

                  pixel.red+=(p+u+j)->red * gaussian_kernel(u,v);
I think a gaussian blur might give nicer results, and especially with the current implementation would be just as fast. Of course I might be reading the source totally wrong.

Is this the right forum to discuss this, or should I rather post in the bug or developer forum?

Re: selective gaussian blur /adaptive-blur?

Posted: 2009-03-22T12:41:43-07:00
by magick
We'll add the gaussian kernel in the next point release.