,.
. :%%%. .%%%.
__%%%(\ `%%%%% .%%%%%
/a ^ '% %%%% %: ,% %%"`
'__.. ,'% .-%: %-' %
~~""%:. ` % ' . `.
%% % ` %% .%: . \.
%%:. `-' ` .%% . %: :\
%(%,%..." `%, %%' %% ) )
%)%%)%%' )%%%.....- ' "/ (
%a:f%%\ % / \`% "%%% ` / \))
%(%' % /-. \ ' \ |-. '.
`' |% `() \| `()
|| / () /
() 0 | o
\ /\ o /
o ` /-|
___________ ,-/ ` _________ ,-/ _________________ INCLUDES _ OCAML _ SOURCE _ CODE _ EXAMPLES _____________________________________________

Monday, June 2, 2014

The Blurring Filters

Another interesting image processing topic... the blurring filters. As you may know, it exists many blurring methods simply because of the different types of result we want to get when we try to blur an image. For example, we generally use the pixelation when we want to anonymize a person or for censoring nudity. We can use the famous gaussian blur when we want to reduce the image noise and reduce detail. There is also a blurring filter named motion blur which can create a movement effect or lens blur which allows you to set the depth-of-field of the blur.
I found an article from Research at Google which talks about this last one :
Lens Blur in the new Google Camera app (by Carlos Hernández, Software Engineer).
So I think the blurring filters that I am going present will be the classic uniform blur, the pixelation, the Gaussian blur, the motion blur, the glass filter and an extra filter that we will name the progressive pixelation. I had the idea to try to implement this last filter when I found these images by chance :
 

Uniform blur :
n = 3
The uniform blur (also named the mean filter) is the easiest way to blur an image. The procedure to follow consists in replacing the pixels of your image by the average of the current pixel and the neighboring pixels during the browsing of your image matrix representation. So you will have to calculate the averages of the Red, Green and Blue pixel components of the current pixel and its 8 neighbors. I assume you know how to calculate an average so the only useful information I can give you is the following one. If the location of the current pixel on your image is (i,j), the locations of its 8 neighbors are
(i-1, j-1)
(i, j-1)
(i+1, j-1)
(i-1, j)
(i, j)
(i+1, j)
(i-1, j+1)
(i, j+1)
(i+1, j+1)
The most difficult part is to make sure the location of the neighbor pixel that you try to access isn't outside the image matrix representation (basically, this corresponds to the case of the image edges). One of the solutions that I decided to use is to browse the matrix from (1,1) to (width-2,height-2) and not from (0,0) to (width-1,height-1) where, in this case, my function would have try to access to pixel locations (-1,-1), ..., (width,height) which are out of bounds. Here is an example of source code :

This function takes an extra parameter n which determines the number of time this blurring method will be applied to an image. The higher the parameter n, the more intensive the uniform blur will be. Finally, as you may notice on my illustration, you can also try to blur only a certain region of your image with different forms like a circle, a rectangle, ...

Pixelation :
n = 16
The pixelation, like the uniform blur, is all about averaging but the procedure to follow is obviously different. Firstly, you will have to choose the size n of the future pixelated blocks.
Note that in my example, these blocks have a width and a height equal and that the size n should verify image width % n = 0 and image height % n = 0 (where % is the modulus operator) in order to have to same number of blocks horizontally and vertically (see the illustration). Then you have to browse your image matrix representation not pixel by pixel but block by block. And inside every blocks, all pixels must be replaced by the average of these same pixels. So you will have to browse every blocks one time to calculate the sums of the Red, Green and Blue pixel components and a second time to replace the pixels of each block by the final (Red,Green,Bluevalues.

Here again, you can try to pixelate only a certain region of your image like a person's face.

Gaussian blur :
The Gaussian blur filter that I am going to present is based on the use of a kernel (more known under the name of convolution matrix). The convolution matrices can have different dimensions and the most important is the values they contain. Here is an example on how to apply a convolution matrix (on the right of the operator X) to an image matrix representation (note that in this case, the image matrix representation, on the left of the operator X, doesn't contain (Red,Green,Blue) values in each index but a single value. It's the matrix of the Green channel). The idea is to determine what is the value that will replace the current pixel component circled in red (50) if we apply the following convolution matrix. The answer is 42.
How we got this new value? Here is the method used :
new value = 40*0 + 42*1 + 46*0 + 46*0 + 50*0 + 55*0 + 52*0 + 56*0 + 58*0 = 42.
We calculate the sum of products of the current pixel component and its 8 neighbors by the corresponding values, location based, in the convolution matrix (as a pixel has 3 channels : Red, Green and Blue, there are 3 sums to calculate). In some cases, the new value must be divided by what we call a normalization factor as you will see. Now let's apply the convolution matrix of the Gaussian blur filter. The dimensions of this convolution matrix are 5x5, its normalization factor is 115 and it must be filled with these values :
2
4
5
4
2
4
9
12
9
4
5
12
15
12
5
4
9
12
9
4
2
4
5
4
2
The function can be written like that (note that like the uniform blur, you will have to find a solution for the case of the pixels which are on the image edges, these pixels haven't their 8 neighbors) :



Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur : Motion blur :
The motion blur filter is also the result of the use of a special convolution matrix. As you know what is a convolution matrix now, I can directly give you what you will need in order to apply this new filter but before, you just have to know that its particularity is that it can be applied with 3 different movement effects : "left to right", "right to left" and both at the same time. The dimensions of the convolution matrix are 9x9, its normalization factor is 9 and for the filling, it's very simple, put the value 0 everywhere except on the diagonal which goes from (0,0) to (8,8) and which must be filled with the value 1 for the "left to right" movement effect or the diagonal which goes from (8,0) to (0,8) for the "right to left" movement effect. Finally, the last movement effect is obtained by the combination of these 2 diagonals (this creates a X cross of 1 in the convolution matrix). I used the "left to right" movement effect :


Glass filter :
n = 4
The glass filter can create the same effect as your shower window which is probably opaque (see the illustration). And like the uniform blur, the function that I am going to present has an extra parameter n which determines the strengh of the opacity. To get this effect, you have to replace the pixels of your image by another pixel located at a random location within a certain fixed distance (3 in my example) so that the image remains distinguishable. Note that the get_random_neighbor function just returns a random value (corresponding to a horizontal/vertical random location) between values min and max.


Progressive pixelation :
n = 32
As we already saw the pixelation, the progressive pixelation function won't be difficult to implement. The idea is to choose a starting value which will correspond to the size n of the initial pixelated blocks. Note that here again, the initial pixelated blocks have a width and a height equal and that the size n should verify image width % n = 0 and image height % n = 0 (where % is the modulus operator) in order to have to same number of initial pixelated blocks horizontally and vertically. Then we will pixelate our image column by column using the previous pixelation function (each column has a width equal to n and a height equal to the image height) and at every x columns (x=3 in my example),  n  or rather a temporary copy of n will be divided by 2 and send to the pixelation function. The consequence is that it will create more smaller pixelated blocks at every x columns (see the illustration).
Finally, here is the last example of source code :



Next time, we will do some mathematics.