我对用于边缘检测的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.]]
首先要解耦x
和y
轴,请在两个不同的数组上尝试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.]])