Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Sobel operator?

I tried 5 different implementations of the Sobel operator in Python, one of which I implemented myself, and the results are radically different.

My question is similar to this one, but there are still differences I don't understand with the other implementations.

Is there any agreed on definition of the Sobel operator, and is it always synonymous to "image gradient"?

Even the definition of the Sobel kernel is different from source to source, according to Wikipedia it is [[1, 0, -1],[2, 0, -2],[1, 0, -1]], but according to other sources it is [[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]].

Here is my code where I tried the different techniques:

from scipy import ndimage
import numpy as np
import cv2 as cv
from scipy import ndimage
from PIL import Image, ImageFilter

img = np.random.randint(0, 255, [10, 10]).astype(np.uint8)

def sobel_x(img) :
    return ndimage.convolve(img, np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]))

my_sobel = sobel_x(img)
_, numpy_sobel = np.gradient(img)
opencv_sobel = cv.Sobel(img, cv.CV_8UC1, 1, 0)
ndimage_sobel = ndimage.sobel(img, axis=0, mode="constant")
pil_sobel = np.array(Image.fromarray(img).filter(ImageFilter.Kernel((3, 3), (-1, 0, 1, -2, 0, 2, -1, 0, 1), 1, 0)))

print(my_sobel)
print(numpy_sobel)
print(opencv_sobel)
print(ndimage_sobel)
print(pil_sobel)

enter image description here

like image 402
nexide Avatar asked Jun 15 '21 13:06

nexide


People also ask

What does Sobel operator do?

The Sobel operator performs a 2-D spatial gradient measurement on an image and so emphasizes regions of high spatial frequency that correspond to edges. Typically it is used to find the approximate absolute gradient magnitude at each point in an input grayscale image.

What is Sobel in image processing?

The Sobel method, or Sobel filter, is a gradient-based method that looks for strong changes in the first derivative of an image. The Sobel edge detector uses a pair of 3 × 3 convolution masks, one estimating the gradient in the x-direction and the other in the y-direction.

What is use of Sobel operator in Opencv?

The Sobel Operator is a discrete differentiation operator. It computes an approximation of the gradient of an image intensity function. The Sobel Operator combines Gaussian smoothing and differentiation.


2 Answers

The Sobel operator estimates the derivative.

The correct definition of the Sobel operator to estimate the horizontal derivative is:

  | 1  0 -1 |
  | 2  0 -2 | / 8
  | 1  0 -1 |

The division by 8 is important to get the right magnitude. People often leave it out because they don't care about the actual derivative, they care about comparing the gradient in different places of the same image. Multiplying everything by 8 makes no difference there, and so leaving out the /8 keeps things simple.

You will see the kernel defined with the inverse signs some places. These are cases where the kernel is applied by correlation instead of convolution (which differ by a mirroring of the kernel), such as the case of OpenCV. These can also be cases where people copy stuff without understanding them, resulting in a gradient with the wrong sign.

But then again, the Sobel operator is mostly applied to obtain the gradient magnitude (the square root of the sum of the squares of the horizontal and vertical derivatives). In this case, reversing the signs doesn't matter any more.


Note that np.gradient(img) is comparable to convolving with [1,0,-1]/2. This is another way to estimate the derivative. Sobel adds a regularization (==smoothing) in the perpendicular direction.


You will get a better understanding of each implementation if you use a more meaningful test image. Try for example a black image with a white square in the middle. You will be able to compare the strength of the estimated gradients, their direction (I assume some libraries use a different definition of x and y axes), and you will be able to see the effect of the regularization.

like image 160
Cris Luengo Avatar answered Oct 21 '22 03:10

Cris Luengo


according to wikipedia it's [[1, 0, -1],[2, 0, -2],[1, 0, 1]] but according to other sources it's [[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]

Both are used for detecting vertical edges. Difference here is how these kernels mark "left" and "right" edges.

For simplicity sake lets consider 1D example, and let array be

[0, 0, 255, 255, 255]

then if we calculate using padding then

  • kernel [2, 0, -2] gives [0, -510, -510, 0, 0]
  • kernel [-2, 0, 2] gives [0, 510, 510, 0, 0]

As you can see abrupt increase in value was marked with negative values by first kernel and positive values by second. Note that is is relevant only if you need to discriminate left vs right edges, when you want just to find vertical edges, you might use any of these 2 aboves and then get absolute value.

like image 33
Daweo Avatar answered Oct 21 '22 01:10

Daweo