Home > Software design >  Sobel edge detection without offset
Sobel edge detection without offset

Time:08-09

I am interested in the Sobel function for edge detection. I would like to return the exact position of horizontal and vertical edges. However the sobel operator values are offset. As I understand, the sobel operation give the variation along an axis. Thus, a negative sobel value would mean that the edge is located before and a positive sobel value would mean that the edge is located after.

Is there a standart method to retrieve the exact location of an edge?

current input:

import pandas as pd
import numpy as np
import cv2 as cv2

df = pd.DataFrame(np.array([[1,0,0,0],
                           [1,0,0,0],
                           [1,1,1,1],
                           [1,0,0,0]]), columns=list('ABCD'), index = list('ABCD'))
 

img = pd.DataFrame.to_numpy(df) #create a numpy array from the df
img = img.astype(np.uint8)

# Sobel Edge Detection
sobelx = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=3) # Sobel Edge Detection on the X axis
sobely = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=3) # Sobel Edge Detection on the Y axis

print(sobelx)
print(sobely)

current output for x direction and y direction:

#x_dir
[[ 0. -4.  0.  0.]
 [ 0. -3.  0.  0.]
 [ 0. -2.  0.  0.]
 [ 0. -2.  0.  0.]]
#y_dir
[[0. 0. 0. 0.]
 [2. 3. 4. 4.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]

CodePudding user response:

First to decouple the x, and y axis, try the Sobel operator on two different arrays.


import cv2 as cv2

import numpy as np

#create numpy array of 10 by 10 with zeros
arr_1 = np.zeros((10,10))
arr_2 = np.zeros((10,10))
#set third row to 1
arr_1[2,:] = 1 
# and fourth column to 1
arr_2[:,3] = 1


img_1 = arr_1.astype(np.uint8) 
img_2 = arr_2.astype(np.uint8) 


# Sobel Edge Detection

sobely = cv2.Sobel(src=img_1, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=3) # Sobel Edge Detection on the Y axis

print(img_1, '\n')
print(sobely)

sobelx = cv2.Sobel(src=img_2, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=3) # Sobel Edge Detection on the X axis

print(img_2, '\n')
print(sobelx,'\n')

The output would be:

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

[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 4.  4.  4.  4.  4.  4.  4.  4.  4.  4.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [-4. -4. -4. -4. -4. -4. -4. -4. -4. -4.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]
[[0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0]]

[[ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]
 [ 0.  0.  4.  0. -4.  0.  0.  0.  0.  0.]]

According to Wikipedia:

Technically, it is a discrete differentiation operator, computing an approximation of the gradient of the image intensity function

As you can see in the y-axis array. The sobel filter which is a 3X3 matrix, starts to respond to the third row already in the second row. This is because convolving the filter over the pixels gives us the gradient in the vicinity depending on the filter.

CodePudding user response:

The Laplacian Operator can help. It computes the second order derivative for a given array. In doing so the exact location of the edge can be determined.

For the following array c:

>>> c
array([[0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0]], dtype=uint8)

This is the Laplacian result:

>>> dst = cv2.Laplacian(c, cv2.CV_64F, ksize=3)
>>> dst
array([[ 0.,  4., -8.,  4.,  0.],
       [ 0.,  4., -8.,  4.,  0.],
       [ 0.,  4., -8.,  4.,  0.],
       [ 0.,  4., -8.,  4.,  0.]])
  • Related