Simple image filters using convolution matrix

Monkey Forums/Monkey Code/Simple image filters using convolution matrix

Beaker(Posted 2013) [#1]
Here is some nice code that can apply realtime (but sometimes slow) filters to images. Including blur, sharpen, emboss, edge detect, median blur, gaussian blur etc.

The Median function is particularly slow.

See an example here:
Example

Enjoy. If you make any improvements, please post them here.

example.monkey


convmatrix.monkey



Beaker(Posted 2013) [#2]
I forgot to mention that it currently doesn't handle image edges very elegantly. I will probably fix this at some point.


semar(Posted 2013) [#3]
Nice !


Difference(Posted 2013) [#4]
2x Nice !


Gerry Quinn(Posted 2013) [#5]
What should one do with edges? I'm thinking two options: average the colour near an edge and treat outside pixels as being that colour, or wrap around (useful for tiled graphics).


slenkar(Posted 2013) [#6]
gimp offers a choice for tiled/nontiled

this opens the possibility for monkey to do an elite style game with procedurally generated planet images ^_^


muddy_shoes(Posted 2013) [#7]
I've done a little tweaking to improve performance a bit. The speed-up ranges from a little to a lot depending on target and build settings. I only tried HTML5, Flash, XNA and GLFW but the techniques are mostly transferable. Going native with this sort of thing would be the natural end-game though.

The output may not be exactly the same as the original but it looks visually equivalent.




Beaker(Posted 2013) [#8]
The only problem (and a quite major one) that I can see with your nice optimised code is that it will be much harder (if not impossible) to adjust it to handle image edges. Or am I missing something?


muddy_shoes(Posted 2013) [#9]
You're missing a description of how you would handle edges.


Beaker(Posted 2013) [#10]
Like this:



muddy_shoes(Posted 2013) [#11]
What's that meant to be doing? It looks like it wraps the pixel values to the right and bottom and repeats the border values to the left and top.


Beaker(Posted 2013) [#12]
It doesn't wrap them, instead it clamps the edges, which works great.


muddy_shoes(Posted 2013) [#13]
[monkeycode]
For Local x2:Int = -halfSize To halfSize
Local newx:Int = (x+x2) Mod image.Width()
If newx < 0 newx = 0
For Local y2:Int = -halfSize To halfSize
Local newy:Int = (y+y2) Mod image.Height()
If newy < 0 newy = 0

[/monkeycode]

If you put (x+x2) = width and (y+y2) = height into that you get 0,0 out. It wraps.

If you put (x+x2) = -1 and (y+y2) = -1 into that you get 0,0 out. It clamps.


muddy_shoes(Posted 2013) [#14]
Anyway, I believe this does what you intend:




Beaker(Posted 2013) [#15]
Oops. Sorry, I'm an idiot. In my defense it's been a very long day. How about this:



Beaker(Posted 2013) [#16]
muddy_shoes - looks great.


NoOdle(Posted 2013) [#17]
thank you for posting this, I have never heard of convolution matrices before, very interesting reading up on them and their uses. I saw this as an interesting programming challenge and decided to try writing my own now. After a few hours I managed to get mine working correctly, It's always easier implementing something when there is reference code to help!

I believe I have a working Sobel edge filter although I need to read up on it some more to make sure, the output seems to match but it was a weird one.

Is there a list or website showing kernel values or filter names that can be used with this method? I have about 14 so far, would be good to get a complete collection.