I have been attempting to duplicate a bilateral filter effect (edge preserving, color-range aware) using the limited set of primitives in the existing toolbox of SVG filters. I've tried a number of approaches. My most successful to date is a three part operation that does Sobel edge detection, dilates the Sobel edges, extracts the pixels corresponding to those edges with a compositing operation, gaussian blurs the source image and then composites back the original edge pixels on top of the blurred image. The result preserves edges, but is not color-range aware.
<filter id="surfaceBlur" color-interpolation-filters="sRGB">
<!-- convert source image to luminance map-->
<feColorMatrix type="luminanceToAlpha" />
<!-- sober edge detection-->
<feConvolveMatrix order="3" kernelMatrix="-1 -2 -1
0 0 0
1 2 1 "
preserveAlpha="true"
/>
<feConvolveMatrix order="3" kernelMatrix="-1 0 1
-2 0 2
-1 0 1 "
preserveAlpha="true"
/>
<!-- dilate the edges to produce a wider mask-->
<feMorphology operator="dilate" radius="1"
result="mask"/>
<!-- extract just the detail from the source graphic using the dilated edges -->
<feComposite operator="in" in="SourceGraphic" in2="mask" result="detail" />
<!-- blur the source image -->
<feGaussianBlur stdDeviation="3" in="SourceGraphic" result="backblur"/>
<!-- slap the detail back on top of the blur! -->
<feComposite operator="over" in="detail" in2="backblur"/>
You can see the original, a gaussianBlur, this filter and in the bottom right, a true bilateral filter:
http://codepen.io/mullany/details/Dbyxt
As you can see, it's not an awful result, but it's not very close to a bilateral filter. This method also only works with greyscale images because it uses luminance differences to find edges - so edges between colors of similar luminance are not detected.
So the question is whether there is a algorithm variant of an edge preserving color range aware filter (guided edge view, bilateral etc.) - that can be constructed using the limited primitives available in SVG - which for those not familiar with SVG are:
Only the RGB color space is available. Multiple iterations are fine, and any directed graph of these operations can be constructed.
Update:
I successfully created a median filter using feBlend lighten and darken as Max and Min operators in a bubble sort (thanks to help from cs.stackexchange.com). However this is inefficient: http://codepen.io/mullany/pen/dmbvz, and lacks the color range awareness of a bilateral filter.
I should qualify this by saying I have no experience in graphics whatsoever, but from a maths perspective I think this would work to emulate the equation that defines the bilateral filter:
Given your image I
, use the color matrix to produce an image Intensity
which holds the intensity of each pixel in a single channel, say R. Channels G and B are zeroed out.
For each non-central pixel in your bilateral filter window, construct a convolution matrix which takes the difference between the specific pixel and the central pixel. For example, for a 3x3 window you'd have matrices
0 0 0 -1 0 0 0-1 0 0 0-1 0 0 0 0 0 0 0 0 0 0 0 0
-1 1 0 0 1 0 0 1 0 0 1 0 0 1-1 0 1 0 0 1 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-1 0-1 0 -1 0 0
You can scale the 1
s and -1
s here as necessary to emulate the spatial kernel of the bilateral filter.
Apply each convolution matrix to the Intensity
map, getting (in the 3x3 example) 8 images which represent the change in intensity between a central pixel and its neighbours.
For each of the 8 images, apply a component transfer primative to R with a table that emulates the range kernel of the bilateral filter.
Use another color matrix to set the G and B channels to match the R channel in all 8 images.
Use the multiply operator on each of the 8 and the original image to get 8 new images which represent the 8 terms in the bilateral filter's sum.
Use the Porter-Duff operators to superimpose the 8 images, effectively taking a sum of the 8 terms in the bilateral filter. This gives you the final image.
Have a look at the guided filter.
http://research.microsoft.com/en-us/um/people/kahe/eccv10/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With