Sobel Gradient Angle Resolution

3.3k views Asked by At

When applying a Sobel operator to an image in X and Y direction and computing an angle (atan2) from the resulting X/Y vector, I seem to get gradient directions in 45 degree steps. Does a Sobel only produce 8 directions in 45 degree steps or should I get exact angles or could it be a rounding error?

I use the sobel convolution for Gx and Gy mentioned here https://en.wikipedia.org/wiki/Sobel_operator

1

There are 1 answers

3
Ander Biguri On BEST ANSWER

Yes using the classing Sobel operators. Lets try to understand what you are doing here:

A Sobel operator to detect vertical lines looks like:

[-1 0 1
 -2 0 2
 -1 0 1]

If you apply this to a pixel (put this on top of the pixel, and use the values in neighbor pixels, then add up everything), it will only have a non-zero value if pixels in the right have different values as pixels in the left. If that is the case it meas there is a vertical edge.

Following, the 45 degree Sobel operator:

[-2 -1  0
 -1  0  1
 0   1  2]

If you understood how the vertical one works, this should be easy to understand. the biggest values will happen when the diagonal of this matrix has different values, thus a 45 degrees edge.

Before continuing, lets note a thing, mentioned by @ImanolLuengo in the comments: The 45 degree Sobel operator will actually see a 30 degree slope, it will just give it a smaller value. It will enhance it less. You can test this by yourself if you want to.

Now, with a 3x3 matrix, you can see that its going to be quite hard to get a 30 degree edge, basically because the fact that the kernel we use is discreet and small (3x3) doesn't allow us to create a kenrel that enhances other angles.

However, using the same logic as in the Sobel operator, we can think of a bigger sized kernel that can enhance any arbitrary angle.

For example the following kernel will enhance 30 degrees mostly:

[1  1  1  1  0 
 1  1  0  0  0 
 0  0  0 -1 -1 
 0 -1 -1 -1 -1]

It is a "by hand approximation of the kenrel, because as you note in Sobel, some kernel elements have bigger numbers than others. The rule for this numbers is: Higher value in the direction of the edge you want to detect, and higher value in the ones that actually go trough the center of the kernel.

This will not be a Sobel operator, but you can just make up any kernels that will do the job you want.