paf*_*afi 4 python numpy scipy
环境
我目前正在尝试使用索贝尔滤波器计算图像梯度。起初我scipy.ndimage.sobel通过以下方式使用函数
sx = ndimage.sobel(im, axis=0,mode="constant")
sy = ndimage.sobel(im, axis=1,mode="constant")
sobel = np.hypot(sx,sy)
sobel *= 255 / np.max(sobel)
Run Code Online (Sandbox Code Playgroud)
然而,这仅将 (3x3) 索贝尔滤镜应用于我的图像,但我想尝试更大的滤镜。numpy因此我尝试用和计算图像梯度scipy.signal。首先我再次尝试了(3x3)过滤器。
filter_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]], dtype=np.float)
filter_y = np.array([[1,2,1], [0,0,0], [-1,-2,-1]], dtype = np.float)
sx = signal.convolve2d(im,filter_x,mode="same",boundary="symm", fillvalue=0)
sy = signal.convolve2d(im,filter_y,mode="same",boundary="symm", fillvalue=0)
sobel = np.hypot(sx,sy)
sobel *= 255 / np.max(sobel)
Run Code Online (Sandbox Code Playgroud)
正如这篇文章中的建议。
问题
不幸的是,这两种方法会导致完全不同的结果,这在这个问题中已经提到过。所以我更深入地挖掘了一下,发现scipy.ndimage.sobel使用该correlate1d函数而不是convolve2d或类似的东西(源代码)。不幸的是,无法查看该函数的源代码correlate1d,因为它的功能隐藏在_nd_image.pyd我的 conda 环境的 site-packages 文件夹中已编译的文件内。所以我的问题来了:
问题
有谁明确知道,到底是由什么计算的correlate1d以及它以什么方式与 进行比较convolve2d?
编辑
正如 Florian Drawitsch 的回答中已经提到的,应该能够用相关性来代替卷积。但话又说回来,这些不同的结果是怎么出现的呢?!
从方法名称来看correlate1d,convolve2d我强烈怀疑前者计算相关性,而后者计算卷积。有什么不同?
一般来说,信号f与内核的卷积g涉及在操作之前翻转内核:f*g(-t)
相反,信号f与内核的相关g是在不翻转内核的情况下进行的:f*g(t)
因此,与使用相关的结果相比,使用卷积应用定向边缘检测内核(如索贝尔内核)应该会导致反转边缘。让我们在代码中测试一下:
import numpy as np
from scipy import signal
from PIL import Image
from matplotlib import pyplot as plt
img = Image.open('lena.png')
plt.imshow(img)
Run Code Online (Sandbox Code Playgroud)
首先,我们定义一个 sobel 边缘检测内核:
g = np.asarray([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
Run Code Online (Sandbox Code Playgroud)
现在让我们首先使用 sicpy 将图像与内核进行卷积signal.convolve2d
img_convolved = signal.convolve2d(img, g)
plt.imshow(img_convolved, cmap='gray')
Run Code Online (Sandbox Code Playgroud)
...并放大边缘:
plt.imshow(img_convolved[100:150,100:150], cmap='gray')
Run Code Online (Sandbox Code Playgroud)
现在,让我们使用 sicpy 将图像与内核相关联signal.correlate2d
img_correlated = signal.correlate2d(img, g)
plt.imshow(img_correlated, cmap='gray')
Run Code Online (Sandbox Code Playgroud)
...并放大边缘:
plt.imshow(img_correlated[100:150,100:150], cmap='gray')
Run Code Online (Sandbox Code Playgroud)
最后,让我们将相关结果与使用翻转内核进行卷积时发生的情况进行比较:
img_convolved_flipped = signal.convolve2d(img, np.fliplr(g))
plt.imshow(img_convolved, cmap='gray')
Run Code Online (Sandbox Code Playgroud)
...并放大边缘:
plt.imshow(img_convolved_flipped[100:150,100:150], cmap='gray')
Run Code Online (Sandbox Code Playgroud)
所以,scipy的signal.correlate2d(img, g)相当于signal.convolve2d(img, np.fliplr(g))
编辑(二维代码示例的说明):
请注意,在 2D 情况下,信号f与内核的卷积g涉及围绕两个基轴翻转内核:f*g(-t,-u)。
因此,在我的代码中,我实际上应该翻转过滤器两次:np.flipud(np.fliplr(g))。我省略了这一点,因为对于垂直对称索贝尔滤波器来说这不是必需的,但请记住这是一个特殊情况。
| 归档时间: |
|
| 查看次数: |
5654 次 |
| 最近记录: |