13

I find on the OpenCV documentation for cvSmooth that sigma can be calculated from the kernel size as follows: sigma = 0.3(n/2 - 1) + 0.8

I would like to know the theoretical background of this equation.

Thank you.

2 Answers 2

6

Using such a value for sigma, the ratio between the value at the centre of the kernel and on the edge of the kernel, found for y=0 and x=n/2-1, is:

g_edge / g_center = exp(-(x²+y²)/(2σ²))
                  = exp(-(n/2-1)²/(2*(0.3(n/2-1)+0.8)²))

The limit of this value as n increases is:

exp(-1/(2*0.3²)) = 0.00386592

Note that 1/256 is 0.00390625. Images are often encoded in 256-value ranges. The choice of 0.3 ensures that the kernel considers all pixels that may significantly influence the resulting value.

I am afraid I do not have an explanation for the 0.8 part, but I imagine it is here to ensure reasonable values when n is small.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very much for your answer. Please forgive my ignorance, I cannot see the effect of having exp(-1/(2*0.3²)) = 0.00386592, which corresponds to 1/256. I would be very grateful if you could give an easier explanation. Besides, shouldn't we take the farthest pixel at (x=n/2-1, y=n/2-1) instead of (x=n/2-1, y=0)? Thank you.
Why are you dropping the first part of the gaussian bell equation? 1/(2pi sigma^2)
@filip because it gets cancelled in g_edge / g_center, as it appears on both sides of the division.
Also, could you maybe explain @AimingHigh 's comment too? :)
Rule of thumb: Multiply or divide by 6 depending on which of the two you want to generate. Works well with 8bit precision kernels.
|
0

We can see if the radius is big enough, it is actually 0.3r, match the sigma assumption: we need the filter radius to be 3sigma

the radius is (ksize-1)/2, thus in another words we need sigma = (ksize-1)/6. which is roughly 0.15*(ksize-1).

However, why we need the +0.5 ?

It is very simple. If we make the edge to be 0 for the small kernels, then only the centre has relatively big value. It becomes a per pixel scaling instead of filtering. For radius of 2, It looks like a triangle filter instead of gaussian

Thus we need an offset to make sure the small filter do have low pass effect.

enter image description here

size=3                 : tensor([0.0109, 0.9783, 0.0109])
size=3 with +0.5 offset: tensor([0.2466, 0.5067, 0.2466])
size=5                 : tensor([0.0066, 0.1942, 0.5983, 0.1942, 0.0066])
size=5 with +0.5 offset: tensor([0.0809, 0.2434, 0.3515, 0.2434, 0.0809])
size=7                 : tensor([0.0044, 0.0540, 0.2420, 0.3991, 0.2420, 0.0540, 0.0044])
size=7 with +0.5 offset: tensor([0.0366, 0.1113, 0.2167, 0.2707, 0.2167, 0.1113, 0.0366])
size=9                 : tensor([0.0033, 0.0238, 0.0972, 0.2260, 0.2994, 0.2260, 0.0972, 0.0238, 0.0033])
size=9 with +0.5 offset: tensor([0.0204, 0.0578, 0.1216, 0.1900, 0.2205, 0.1900, 0.1216, 0.0578, 0.0204])

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.