Jump to content


image "glow" effect ... smooth distance field?


2 replies to this topic

#1 Bernie

    New Member

  • Members
  • Pip
  • 6 posts

Posted 20 January 2009 - 12:13 AM

Hey all,

I'm trying to find an efficient way of creating a "glow" effect around a monochrome image such that the gradient is smooth. I know this sounds vague, just bear with me ... The standard approach to this is to blur the image and add the original image to the blurred result, but then small and/or thin structures in the image disappear - this is explicitly what I'm trying to avoid. I want to use this effect for stylistic image postprocessing, not the traditional HDR/tonemapping/bloom type of stuff (where blur+add is more appropriate).

For simplicity, let's say the input pixels are either 0 or 1, where 0 represents the background (exterior) and 1 represents the interior of the shape. What I want is a glow effect that brightens the 0 pixels near the shape's boundary and leaves the 1 pixels unaffected. This should be a "smooth distance field" type of effect, where the output value of each pixel is proportional to the minimum distance to an interior pixel. However, the actual Euclidean Distance Transform (EDT) is generally not smooth, at least not C1-smooth - there are "creases" in the gradient that are very significant visually.

Here's a paper on the Euclidean Distance Transform:
2D Euclidean Distance Transform Algorithms

Currently I have a solution for that works fairly well, but it requires hundreds or even thousands of passes over the image. Basically, I save a copy of the input image, then repeatedly perform a small (3x3) box blur followed by a MAX with the saved input image. Here is a 1D example:


void Glow1D(float *dst, const float *src, int w, int numPasses)

{

    memcpy(dst, src, w*sizeof(float));


    for (int pass = 0; pass < numPasses; ++pass)

    {

        float v0 = dst[0];

        float v1 = v0;


        for (int x = 0; x < w; ++x)

        {

            float v2 = dst[(x + 1) < w ? (x + 1) : (w - 1)];


            dst[x] = Max(src[x], (v0 + v2)/2.0f);


            v0 = v1;

            v1 = v2;

        }

    }

}


If you set w=512 and initialize the array with {1,0,0,0,0,....,0} and set numPasses=2000 and then graph the result, you'll get what looks like almost straight linear falloff from 1 down to 0.5 over the first 32 elements, followed by a smooth tapering off that reaches near zero (visually at least) at around the 150th element.

The standard ways of accelerating large-radius Gaussian blur don't seem to apply to this repeated "blur+MAX" method, unfortunately. I've implemented this algorithm using 8x16-bit fixed-point vectors in SSE but it's still orders of magnitude too slow.

Does anyone have any suggestions for how I can make this (or something visually similar) much much faster? Maybe there's some way to start with an EDT and somehow "relax" or smooth the image so that the pixels near the interior don't change and the gradient only changes near the creases in the EDT's gradient?

#2 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 20 January 2009 - 01:25 AM

Do you have a screenshot or photo of the effect that you're trying to archive. Must not be computer generated...
My music: http://myspace.com/planetarchh <-- my music

My stuff: torus.untergrund.net <-- some diy electronic stuff and more.

#3 Bernie

    New Member

  • Members
  • Pip
  • 6 posts

Posted 20 January 2009 - 02:38 AM

Nils Pipenbrinck said:

Do you have a screenshot or photo of the effect that you're trying to archive. Must not be computer generated...

Here are the results of my current algorithm .. I'm also trying to use an IIR filter which is giving me results in less iterations but it is still requiring hundreds of passes.

(all images are inverted)

input image:
Posted Image

output image (2000 passes):
Posted Image

output image using IIR filter (500 passes):
Posted Image

this is what the EDT gives in a single pass, mapping distances [0..50] to intensity values [0..1]:
Posted Image





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users