Log in

View Full Version : Bilateral filtering


MfA
24th January 2004, 05:02
Just put up a link in usage for a denoiser based on bilateral filtering (well either a denoiser or a special effects filter depending on who you ask).

http://forum.doom9.org/showthread.php?s=&threadid=69428

Source code is there, if anyone has any suggestions I would be interested ... mainly for speeding it up.

Also it accentuates jaggies on cartoon type stuff, this might be a lingering bug in my code ... if not, the fact that the intensity difference is taken in gamma corrected space might have something to do with it.

Manao
24th January 2004, 13:15
Use the function Bitblt to make the copy of the chroma plane.

Process the pixel of the border outside your main loop, it avoid useless tests ( but make the code a lot longer ).

Do not calculate each time the offset when accesing an element of the array :

- When you calculate the sum of your weighted pixels, calculate the offset once and for all for the upperleft most pixel, define a pointer on this position, and then use only this pointer by incresing it by one in the x loop, and by src_pitch - radius * 2 + 1 in the y loop.
- Do the same in the main loops with the destination pointer.

With that, you should then be around two times faster.

**Edited :

Also, instead of precomputing the weights for positive value of radius, calculate them for positive and negative values. Hence you won't need three loops for calculate the final pixel, and what I said above will apply better.

MfA
24th January 2004, 17:01
Ya the chroma plane code was a bit of a quick hack, filtering the chroma planes makes the oilpainting effect visible faster.

Branch prediction should be pretty much 100% on the border code, Ill keep that inline ... 1 cycle to skip across a branch wont kill me.

I guess I will have to try increasing the LUT to the full window size and do a more straightforward walk through the window ... I was trying to keep it small (using it for taking inverse gamma corrected intensity differences will make it quite big).

Thanks.

sh0dan
24th January 2004, 17:21
You must be sure your functions are inlined by the compiler otherwise it will be VERY slow! (See in the compiler settings which it is inlining - changing "inline" to "__inline" might very well help you.

- Matrixbased algorithms are often very slow. Completely unrolling inner loops may give some percent better performance (especially on P4).

- Avoid jumps in code ("if"s and "(xonething)? a : b"). Again you code kills P4 (and partially K7), if it cannot predict the jump.

- Using BitBlt is easier, but it probably wont be measurable faster in your filter.

- Looks a lot like SmoothHiQ. :)

MfA
24th January 2004, 17:39
SmoothHiQ is a little more like G-Neighbour filtering, you can look at bilateral filtering as the bayesian version of SmoothHiQ.

I think Ill just leave this code as it is and make a fixed mask size (7x7) version using all the suggestions ... within the generic filter optimization will make the code get messy.

Or on second thought ... I might try to brush up on my template programming to construct unrolled loop versions.

MfA
26th January 2004, 11:46
Well the template code was a bit of a failure performance wise, it needs far too much pointer indirection although I was hoping the compiler could deal with it, but hell ... at least I learned how to unroll loops with templates.

http://home.student.utwente.nl/m.f.al/bilateral/templateExperiment/
If anyone is interested, I think it's a bit faster but I havent done much testing since its still far too slow for my liking. Ill try to do a fixed size version with inline assembly.

The defaults are now (2, 1, 15, true) and I use the scaled difference of the squared intensity values now for the lookup in the intensity deviation table (square is pretty close to inverse gamma correction).