1

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.]]
D.L
  • 4,339
  • 5
  • 22
  • 45
sam47
  • 11
  • 2
  • what do you mean by exact ? the function itself looks for a **change** which is the purpose of `dx` and `dy`.... the function is seeking this. You could set `ksize=1`, but this would lose accuracy elsewhere. – D.L Aug 08 '22 at 13:20
  • I try to retrieve the position of the edges: here the horizontal line is located on the third row, thus I would like the sobel function to return a high value for this row. – sam47 Aug 08 '22 at 13:25

2 Answers2

0

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.

YScharf
  • 1,638
  • 15
  • 20
0

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.]])
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87