无偏移的Sobel边缘检测



我对用于边缘检测的Sobel函数感兴趣。我想返回水平和垂直边缘的确切位置。但是sobel运算符值是偏移的。据我所知,索贝尔运算给出了沿一个轴的变化。因此,负sobel值将意味着边缘位于之前,而正sobel值则意味着边缘处于之后。

有没有一种标准的方法来检索边缘的确切位置?

电流输入:

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)

x方向和y方向的电流输出:

#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.]]

首先要解耦xy轴,请在两个不同的数组上尝试Sobel运算符。


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')

输出为:

[[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.]]

根据维基百科:

从技术上讲,它是一个离散微分算子,计算图像强度函数的梯度近似

如您在y-axis数组中所见。作为3X3矩阵的sobel filter开始响应已经在第二行中的第三行。这是因为在像素上卷积滤波器会根据滤波器给出附近的梯度。

拉普拉斯算子可以提供帮助。它计算给定数组的二阶导数。通过这样做,可以确定边缘的确切位置。

对于以下阵列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)

这是拉普拉斯结果:

>>> 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.]])

相关内容

  • 没有找到相关文章

最新更新