将numpy中的Sobel运算符应用于简单的二值图像
Applying Sobel operator in numpy to simple binary image
我正在尝试将 Sobel 运算符应用于简单的二值图像,但生成的梯度被翻转(与 scipy 的 signal.convolve2d
函数的输出相比。
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
def sobelx_homemade(arr, kx):
offset = 1
sx = np.zeros(arr.shape)
for y in range(offset, arr.shape[0] - offset):
for x in range(offset, arr.shape[1] - offset):
rstart, rend = y-offset, y+offset+1
cstart, cend = x-offset, x+offset+1
w = arr[rstart:rend, cstart:cend]
Ix = kx * w
sx[y, x] = Ix.sum()
return sx
A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 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, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 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]])
kx = np.array([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
], dtype=np.float)
ky = np.array([
[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]
], dtype = np.float)
Gx = signal.convolve2d(A, kx, boundary='symm', mode='same')
Gy = signal.convolve2d(A, ky, boundary='symm', mode='same')
# calculate homemade sobel x gradient
myGx = sobelx_homemade(A, kx)
plt.subplot(131)
plt.title("Original")
plt.imshow(A, cmap="gray")
plt.subplot(132)
plt.title("Gx")
plt.imshow(Gx, cmap="gray")
plt.subplot(133)
plt.title("My Gx")
plt.imshow(myGx, cmap="gray")
我希望标记为 "Gx" 和 "My Gx" 的图像是相同的。
所以,事实证明 true 卷积翻转了 kernel/filter 矩阵,这解释了翻转的结果。
这段来自 Andrew Ng 的视频解释了机器学习风格图像处理中常用的教科书卷积和互相关之间的区别:
https://youtu.be/tQYZaDn_kSg?t=308
我正在尝试将 Sobel 运算符应用于简单的二值图像,但生成的梯度被翻转(与 scipy 的 signal.convolve2d
函数的输出相比。
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
def sobelx_homemade(arr, kx):
offset = 1
sx = np.zeros(arr.shape)
for y in range(offset, arr.shape[0] - offset):
for x in range(offset, arr.shape[1] - offset):
rstart, rend = y-offset, y+offset+1
cstart, cend = x-offset, x+offset+1
w = arr[rstart:rend, cstart:cend]
Ix = kx * w
sx[y, x] = Ix.sum()
return sx
A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 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, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 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]])
kx = np.array([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
], dtype=np.float)
ky = np.array([
[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]
], dtype = np.float)
Gx = signal.convolve2d(A, kx, boundary='symm', mode='same')
Gy = signal.convolve2d(A, ky, boundary='symm', mode='same')
# calculate homemade sobel x gradient
myGx = sobelx_homemade(A, kx)
plt.subplot(131)
plt.title("Original")
plt.imshow(A, cmap="gray")
plt.subplot(132)
plt.title("Gx")
plt.imshow(Gx, cmap="gray")
plt.subplot(133)
plt.title("My Gx")
plt.imshow(myGx, cmap="gray")
我希望标记为 "Gx" 和 "My Gx" 的图像是相同的。
所以,事实证明 true 卷积翻转了 kernel/filter 矩阵,这解释了翻转的结果。
这段来自 Andrew Ng 的视频解释了机器学习风格图像处理中常用的教科书卷积和互相关之间的区别: https://youtu.be/tQYZaDn_kSg?t=308