📜 ⬆️ ⬇️

Need more different Blur's

Blurring an image using a Gaussian Blur filter is widely used in a variety of tasks. But sometimes you want a little more variety than just one filter for all occasions, in which only one parameter can be adjusted - its size. In this article, we will look at several other blur implementations.


Introduction


The Gaussian Blur effect is a linear operation and is mathematically a convolution of an image with a filter matrix. In addition, each pixel in the image is replaced by the sum of nearby, taken with certain weight coefficients.

The filter is called Gaussian, because it is built from a function known as a Gaussian, ex2:
')


the two-dimensional version of which is obtained by its rotation about the ordinate axis, e(x2+y2):



Here for each pair of coordinates (x,y)the distance to the center is calculated by the formula  sqrtx2+y2which is passed as an argument to the function of the Gaussian - and, as is easy to see, e left( sqrtx2+y2 right)2reduced to e(x2+y2).

Matrix built on a segment [3.3]and with some level of discretization, it will look like this:

\ left (\ begin {array} {ccccccc} 1.52 \ times 10 ^ {- 8} & 2.26 \ times 10 ^ {- 6} & 0.0000454 & 0.000123 & 0.0000454 & 2.26 \ times 10 ^ {- 6} & 1.52 \ times 10 ^ {- 8} \\ 2.26 \ times 10 ^ {- 6} & 0.000335 & 0.00674 & 0.0183 & 0.00674 & 0.000335 & 2.26 \ times 10 ^ {- 6} 0.00 0.00454 & 0.00674 & 0.135 & 0.368 & 0.135 & 0.00674 & 0.0000454 \ 0.000123 & 0.0183 & 0.368 & 1.00 & 0.368 & 0.0183 & 0.000123 \ 0.0000454 & 0.00674 & 0.135 & 0.368 & 0.135 & 0.00674 & 0.0000454 \ 2.26 \ times 10 ^ {- 6} & 0.000335 & 0.00674 & 0.0183 & 0.00674 & 0.000335 & 2.26 \ times 10 ^ {- 6} \ 1.52 \ times 10 ^ {- 8} & 2.26 \ times 10 ^ {- 6} & 0.0000454 & 0.000123 & 0.0000454 & 2.26 \ times 10 ^ { -6} & 1.52 \ times 10 ^ {- 8} \\ \ end {array} \ right)


Or, if we consider the values ​​of the matrix elements as the brightness level, so:



In terms of signal processing, this is called impulse response, since this is exactly what the result of the convolution of a given filter with a single pulse (in this case, a pixel) will look like.

Initially, a Gaussian is defined on an infinite interval. But due to the fact that it rather quickly fades away, it is possible to exclude values ​​close to zero from the calculations, since they will not affect the result anyway. In real-world applications, normalization by value is also necessary so that after convolution the image brightness does not change; and in the case of blurring an image in which each pixel has the same color, the image itself should not change.

For convenience, the normalization is often used along the coordinates, by introducing an additional parameter  sigma(reads "sigma") - to treat an argument in the range [1,1], but  sigmadetermines the degree of compression of the Gaussians:

 frace fracx2+y22 sigma22 pi sigma2


Normalizing divider 2 pi sigma2here obtained analytically through a definite integral at infinity:

 int infty infty int infty inftye fracx2+y22 sigma2dxdy=2 pi sigma2


Due to the equality e left(x2+y2 right)=ex2ey2, the Gauss blur can be implemented sequentially, first in rows and then in columns - which allows you to save quite a lot on calculations. In this case, it is necessary to use the formula with normalization for the one-dimensional case -

 frace fracx22 sigma2 sqrt2 pi sigma2



Start


For an arbitrary filter, we first need to define our own decay function for one variable. ffrom which a function of two variables is obtained by rotation by replacing xon  sqrtx2+y2where xand ythese are the coordinates of the matrix element in the range (1,1), and which is further used to fill the elements of the matrix. We will consider normalization not analytically, but direct summation of all elements of the matrix — this is simpler and more accurate — because after sampling the function is “thinned”, and the normalization value will depend on the level of discretization.

If the matrix elements are numbered from zero, the coordinate xor yis calculated by the formula

 frac2indexsize11


Where index- the sequence number of the element in the row or column, and size- total number of items.

For example, for a 5 by 5 matrix, it would look like this:

\ left (\ begin {array} {ccccc} f (-1, -1) & f \ left (- \ frac {1} {2}, - 1 \ right) & f (0, -1) & f \ left (\ frac {1} {2}, - 1 \ right) & f (1, -1) \\ f \ left (-1, - \ frac {1} {2} \ right) & f \ left (- \ frac {1} {2}, - \ frac {1} {2} \ right) & f \ left (0, - \ frac {1} {2} \ right) & f \ left (\ frac { 1} {2}, - \ frac {1} {2} \ right) & f \ left (1, - \ frac {1} {2} \ right) \\ f (-1,0) & f \ left (- \ frac {1} {2}, 0 \ right) & f (0,0) & f \ left (\ frac {1} {2}, 0 \ right) & f (1,0) \\ f \ left (-1, \ frac {1} {2} \ right) & f \ left (- \ frac {1} {2}, \ frac {1} {2} \ right) & f \ left (0, \ frac {1} {2} \ right) & f \ left (\ frac {1} {2}, \ frac {1} {2} \ right) & f \ left (1, \ frac {1} {2 } \ right) \\ f (-1,1) & f \ left (- \ frac {1} {2}, 1 \ right) & f (0,1) & f \ left (\ frac {1} { 2}, 1 \ right) & f (1,1) \\ \ end {array} \ right)


Or, if we exclude the boundary values ​​that are still zero, then the coordinates will be calculated by the formula

 frac2indexsize+1size


and the matrix, respectively, takes the form

\ left (\ begin {array} {ccccc} f \ left (- \ frac {4} {5}, - \ frac {4} {5} \ right) & f \ left (- \ frac {2} { 5}, - \ frac {4} {5} \ right) & f \ left (0, - \ frac {4} {5} \ right) & f \ left (\ frac {2} {5}, - \ frac {4} {5} \ right) & f \ left (\ frac {4} {5}, - \ frac {4} {5} \ right) \\ f \ left (- \ frac {4} {5 }, - \ frac {2} {5} \ right) & f \ left (- \ frac {2} {5}, - \ frac {2} {5} \ right) & f \ left (0, - \ frac {2} {5} \ right) & f \ left (\ frac {2} {5}, - \ frac {2} {5} \ right) & f \ left (\ frac {4} {5}, - \ frac {2} {5} \ right) \\ f \ left (- \ frac {4} {5}, 0 \ right) & f \ left (- \ frac {2} {5}, 0 \ right ) & f (0,0) & f \ left (\ frac {2} {5}, 0 \ right) & f \ left (\ frac {4} {5}, 0 \ right) \\ f \ left ( - \ frac {4} {5}, \ frac {2} {5} \ right) & f \ left (- \ frac {2} {5}, \ frac {2} {5} \ right) & f \ left (0, \ frac {2} {5} \ right) & f \ left (\ frac {2} {5}, \ frac {2} {5} \ right) & f \ left (\ frac {4} {5}, \ frac {2} {5} \ right) \\ f \ left (- \ frac {4} {5}, \ frac {4} {5} \ right) & f \ left (- \ frac {2} {5}, \ frac {4} {5} \ right) & f \ left (0, \ frac {4} {5} \ right) & f \ left (\ frac {2} {5}, \ frac {4} {5} \ right) & f \ left (\ frac {4} {5}, \ frac {4} {5} \ right) \\ \ end {array} \ right)


After the matrix elements have been calculated by the formula, it is necessary to calculate their sum and divide the matrix into it. For example, if we have a matrix

\ left (\ begin {array} {ccc} 1 & 4 & 1 \\ 4 & 20 & 4 \\ 1 & 4 & 1 \\ \ end {array} \ right)


then the sum of all its elements will be 40, and after normalization it will take the form

\ left (\ begin {array} {ccc} \ frac {1} {40} & \ frac {1} {10} & \ frac {1} {40} \\ \ frac {1} {10} & \ frac {1} {2} & \ frac {1} {10} \\ \ frac {1} {40} & \ frac {1} {10} & \ frac {1} {40} \\ \ end {array } \ right)


and the sum of all its elements will be 1.

Linear attenuation


First, take the simplest function - the line:

\ left \ {\ begin {array} {ll} 1-x, & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.




Piecewise-continuous definition here requires that the function is guaranteed to go to zero and during rotation there are no artifacts at the corners of the matrix. In addition, since the rotation uses the root of the sum of squares of coordinates, which is always positive, it is sufficient to determine the function only in the positive part of the values. As a result, we get:



Soft linear attenuation


The abrupt transition from a sloping line to zero functions can cause a contradiction with a sense of beauty. The function will help us to eliminate it.

1 fracnxxnn1


wherein ndefines the “hardness” of the docking, n>1. For example n=3will get

\ left \ {\ begin {array} {ll} 1- \ frac {3 xx ^ 3} {2}, & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.




and the filter itself will look like



Hyperbolic attenuation


The filter can be made more “sharp” and more smoothly going to zero, taking another function as a generator, for example, hyperbola, and providing a smooth transition to zero by summing with a parabola.



After all the calculations and simplifications, we obtain the formula

\ left \ {\ begin {array} {ll} \ frac {(x-1) ^ 2 (k x + k + 1)} {(k + 1) (k x + 1)}, & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.


in which parameter k>0determines the nature of the attenuation:



and the filter itself will look (for k=5) as



Bokeh effect imitation


You can go the other way - to make the top of the filter is not sharp, but stupid. The easiest way to do this is to set the attenuation function as a constant:

\ left \ {\ begin {array} {ll} 1, & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.




But in this case we get a strong pixelation, which contrasts with the sense of beauty. To make it smoother at the edges, a parabola of higher orders will help us, from which by its displacement along the ordinate axis and squaring we get

\ left \ {\ begin {array} {ll} \ left (1-x ^ n \ right) ^ 2, & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.


Varying the parameter nYou can get a wide range of filter options:

n=0.5


n=2


n=10


n=50



And slightly modifying the attenuation function, you can make a more pronounced ring at the edges of the filter, for example:

\ left \ {\ begin {array} {ll} \ left (1-x ^ n \ right) ^ 2 \ left (d + x ^ m \ right), & x <1 \\ 0, & x \ geqslant 1 \\ \ end {array} \ right.


Here is the parameter ddetermines the height of the center, and m- the sharpness of the transition to the edges.
For d=0.2,m=2,n=10will get



and for d=0,m=12,n=2



Variations of Gaussians


You can modify directly the function of the Gaussians. The most obvious way to do this is to parameterize the exponent — we are not going to consider it now, but take a more interesting option:

\ left \ {\ begin {array} {ll} e ^ {\ frac {kx ^ 2} {x ^ 2-1}}, & -1 <x <1 \\ 0, & otherwise \\ \ end { array} \ right.


Due to the fact that xtending to unit denominator x21tends to zero fraction  frackx2x21tends to minus infinity, and the exponent itself also tends to zero. Thus, the division by x21allows you to compress the domain of a function with ( infty, infty)before (1,1). At the same time, with x= pm1by dividing by zero ( 121=0) the value of the function is not defined, but it has two limits - the limit on the one hand (from the inside) is zero, and on the other hand - infinity:

\ underset {x \ to 1 ^ -} {\ text {lim}} e ^ {\ frac {k x ^ 2} {x ^ 2-1} = 0


 undersetx to1+ textlime frackx2x21= infty


Since the boundary values ​​are not included in the interval, then zero in the limit on one side only is sufficient. Interestingly, this property extends to all derivatives of this function, which provides an ideal connection with zero.

Parameter kdetermines the similarity with the Gaussian - the more it is, the stronger the similarity is obtained - due to the fact that an increasingly linear segment  frac1x21fall at the center of the function. One would assume that due to this in the limit one can get the original Gaussian - but, unfortunately, no - the functions are still different.



Now you can see what happened:

k=5


k=2


k=0.5


k=0.1


k=0.01



Form variations


Changing the transition function from two coordinates to one  sqrtx2+y2, you can get other shapes, not just a disk. For example:

f left( frac left|xy right|+ left|x+y right|2 right)




f( left|x right|+ left|y right|)




Turning to complex numbers, you can construct more complex shapes:

f left( frac left| Re left((x+iy)(1) frac03 right) right|+ left| Re left((x+iy)(1) frac13 right) right|+ left| Re left((x+iy)(1) frac23 right) right| sqrt3 right)





f biggl(10 left| Re left((x+iy)(1) frac18 right) right| biggr) cdotf( left|x+iy right|)




f biggl( biggl|5 left|x+iy right|(x+iy) Re biggl( cos left( frac52 arg(x+iy) right) biggr) biggr| biggr) cdotf( left|x+iy right|)





At the same time, it is necessary to ensure that when converting coordinates not to go beyond the interval (0,1)- well, or vice versa, to define the damping function for negative values ​​of the argument.

Some specific examples


An article would not be complete without practical testing on specific images. Since we don’t have a scientific work, we won’t take Lena’s image, but take something soft and fluffy:



Gaussiana




Hyperbolic attenuation




Cross




Ring




One-way attenuation




Same filters, but for text:








Conclusion


Similarly, you can build more complex filters, including with sharpening or contouring; as well as modify the already considered.

Of particular interest is nonlinear filtering, when the values ​​of the filter coefficients depend on the coordinates or the directly filtered image itself - but this is a subject for other studies.

In more detail, the derivation of functions for docking with a constant is discussed here . As a damping function, the window functions discussed here can also be used — all that is needed is to scale the argument c (0,1) to (  frac12, 1) or initially consider window functions by the formula  frac12 left(f left( fractx+1t1 right)f left( fractx1t1 right) right).

The original Wolfram Mathematica document for this article can be downloaded here .

Source: https://habr.com/ru/post/432622/


All Articles