Sobel filter kernel of large size

2019-01-13 04:16发布

I am using a sobel filter of size 3x3 to calculate the image derivative. Looking at some articles on the internet, it seems that kernels for sobel filter for size 5x5 and 7x7 are also common, but I am not able to find their kernel values.

Could someone please let me know the kernel values for sobel filter of size 5x5 and 7x7? Also, if someone could share a method to generate the kernel values, that will be much useful.

Thanks in advance.

8条回答
萌系小妹纸
2楼-- · 2019-01-13 05:06

As Adam Bowen explained in his answer, the Sobel kernel is a combination of a smoothing along one axis, and a central difference derivative along the other axis:

sob3x3 = [1 2 1]' * [1 0 -1]

The smoothing adds regularization (reduces sensitivity to noise).

(I'm leaving out all factors 1/8 in this post, as did Sobel himself, meaning that the operator determines the derivative up to scaling. Also, * always means convolution in this post.)

Let's generalize this:

deriv_kernel = smoothing_kernel * d/dx

One of the properties of the convolution is that

d/dx f = d/dx * f

That is, convolving an image with the elemental derivative operator yields the derivative of the image. Noting also that the convolution is commutative,

deriv_kernel = d/dx * smoothing_kernel = d/dx smoothing_kernel

That is, the derivative kernel is the derivative of a smoothing kernel.

Note that applying such a kernel to an image by convolution:

image * deriv_kernel = image * smoothing_kernel * d/dx = d/dx (image * smoothing_kernel)

That is, with this generalized, idealized derivative kernel we can compute the true derivative of the smoothed image. This is of course not the case with the Sobel kernel, as it uses a central difference approximation to the derivative. But choosing a better smoothing_kernel, this can be achieved. The Gaussian kernel is the ideal option here, as it offers the best compromise between compactness in the spatial domain (small kernel footprint) with compactness in the frequency domain (good smoothing). Furthermore, the Gaussian is perfectly isotropic and separable. Using a Gaussian derivative kernel yields the best possible regularized derivative operator.

Thus, if you are looking for a larger Sobel operator, because you need more regularization, use a Gaussian derivative operator instead.


Let's analyze the Sobel kernel a little bit more.

The smoothing kernel is triangular, with samples [1 2 1]. This is a triangular function, which, sampled, leads to those three values:

      2 + x ,   if -2 < x < 0
h = { 2     ,   if x = 0
      2 - x ,   if 0 < x < 2

Its derivative is:

            1 ,   if -2 < x < 0
d/dx h = {  0 ,   if x = 0        (not really, but it's the sensible solution)
           -1 ,   if 0 < x < 2

So, we can see that the central difference derivative approximation can be seen as a sampling of the analytical derivative of the same triangular function used for smoothing. Thus we have:

sob3x3 = [1 2 1]' * d/dx [1 2 1] = d/dx ( [1 2 1]' * [1 2 1] )

So, if you want to make this kernel larger, simply enlarge the smoothing kernel:

sob5x5 = d/dx ( [1 2 3 2 1]' * [1 2 3 2 1] ) = [1 2 3 2 1]' * [1 1 0 -1 -1]

sob7x7 = d/dx ( [1 2 3 4 3 2 1]' * [1 2 3 4 3 2 1] ) = [1 2 3 4 3 2 1]' * [1 1 1 0 -1 -1 -1]

This is quite different from the advice given by Adam Bowen, who suggests convolving the kernel with the 3-tab triangular kernel along each dimension: [1 2 1] * [1 2 1] = [1 4 6 4 1], and [1 2 1] * [1 0 -1] = [1 2 0 -2 -1]. Note that, due to the central limit theorem, convolving this triangular kernel with itself leads to a filter that approximates the Gaussian a little bit more. The larger the kernel we create by repeated convolutions with itself, the more we approximate this Gaussian. So, instead of using this method, you might as well directly sample the Gaussian function.

Daniel has a long post in which he suggests extending the Sobel kernel in yet another way. The shape of the smoothing kernel here diverges from the Gaussian approximation, I have not tried to study its properties.

Note that none of these three possible extensions of the Sobel kernel are actually Sobel kernels, since the Sobel kernel is explicitly a 3x3 kernel (see an historical note by Sobel about his operator, which he never actually published).

Note also that I'm not advocating the extended Sobel kernel derived here. Use Gaussian derivatives!

查看更多
做个烂人
3楼-- · 2019-01-13 05:10

Other sources seem to give different definitions of the larger kernels. The Intel IPP library, for example, gives the 5x5 kernel as

1  2 0  -2 -1
4  8 0  -8 -4
6 12 0 -12 -6
4  8 0  -8 -4
1  2 0  -2 -1

Intuitively, this makes more sense to me because you're paying more attention to the elements closer to the centre. It also has a natural definition in terms of the 3x3 kernel which is easy to extend to generate larger kernels. That said, in my brief search I've found 3 different definitions of the 5x5 kernel - so I suspect that (as Paul says) the larger kernels are ad hoc, and so this is by no means the definitive answer.

The 3x3 kernel is the outer product of a smoothing kernel and a gradient kernel, in Matlab this is something like

sob3x3 = [ 1 2 1 ]' * [1 0 -1]

the larger kernels can be defined by convolving the 3x3 kernel with another smoothing kernel

sob5x5 = conv2( [ 1 2 1 ]' * [1 2 1], sob3x3 )

you can repeat the process to get progressively larger kernels

sob7x7 = conv2( [ 1 2 1 ]' * [1 2 1], sob5x5 )
sob9x9 = conv2( [ 1 2 1 ]' * [1 2 1], sob7x7 )
...

there are a lot of other ways of writing it, but I think this explains exactly what is happening best. Basically, you start off with a smoothing kernel in one direction and a finite differences estimate of the derivative in the other and then just apply smoothing until you get the kernel size you want.

Because it's just a series of convolutions, all the nice properties hold, (commutativity, associativity and so forth) which might be useful for your implementation. For example, you can trivially separate the 5x5 kernel into its smoothing and derivative components:

sob5x5 = conv([1 2 1],[1 2 1])' * conv([1 2 1],[-1 0 1])

Note that in order to be a "proper" derivative estimator, the 3x3 Sobel should be scaled by a factor of 1/8:

sob3x3 = 1/8 * [ 1 2 1 ]' * [1 0 -1]

and each larger kernel needs to be scaled by an additional factor of 1/16 (because the smoothing kernels are not normalised):

sob5x5 = 1/16 * conv2( [ 1 2 1 ]' * [1 2 1], sob3x3 )
sob7x7 = 1/16 * conv2( [ 1 2 1 ]' * [1 2 1], sob5x5 )
...
查看更多
登录 后发表回答