我的目标是创建和可视化图像(2D)的偏导数。我将用第一个有限的中心差分方程来实现
wikipedia

F关于x的偏导数是

df(x,y)/dx = f(x + 1,y)-f(x-1,y)

我们可以将其写为卷积核H = [-1,0,1]并应得到相同的结果
通过将图像与内核进行卷积

dfx = F * H

这是我的源代码:

from numpy import *
from pylab import *
from PIL import *
from scipy import signal as sg

#create artifical image with constant positive slope
myImage=zeros((5,5),dtype=float)
for y in range(5):
    for x in range(5):
        myImage[y,x]=y+x

首先,我通过convolve2d-函数从 scipy 模块创建了x和y的第一个中心有限差分(简称)
kernel=array([[-1,0,1]])     #create first central finite difference kernel
pdx=sg.convolve2d(myImage,kernel,"same")   #dI(x,y)/dx

现在我使用循环创建相同的
H,W=myImage.shape[0:2]
pdx=zeros((H,W),dtype=float)
for y in range(1,H-1):
    for x in range(1,W-1):
        pdx.itemset(y,x,im.item(y,x+1)-im.item(y,x-1))

让我们看一下结果:

pdx-convolve2d的内核方法
array([[-1., -2., -2., -2.,  3.],
   [-2., -2., -2., -2.,  4.],
   [-3., -2., -2., -2.,  5.],
   [-4., -2., -2., -2.,  6.],
   [-5., -2., -2., -2.,  7.]])

pdx-循环的有限差分
array([[ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  2.,  2.,  2.,  0.],
   [ 0.,  2.,  2.,  2.,  0.],
   [ 0.,  2.,  2.,  2.,  0.],
   [ 0.,  0.,  0.,  0.,  0.]])

我对结果感到困惑。为什么核方法具有负斜率?
为了获得相同的结果,我必须将内核翻转为H = [1,0,-1],但这在数学上是不正确的。
有人能帮我吗 ?

最佳答案

差异的原因有两个:

  • 您已经在卷积的数学定义中忘记了内核的翻转。
  • 您假设的边界条件与scipy.signal
  • 不同

    另外,对于您正在做的事情,您几乎肯定需要scipy.ndimage.convolve而不是scipy.signal.convolve2dndimage的默认设置设置为适用于图像,并且对于有限精度的整数数据(这是图像的标准)更有效。

    要使用scipy.signal来复制循环版本,您已经注意到需要反转内核。

    这是卷积的数学定义。内核在被“扫掠”之前就被翻转了。例如:http://en.wikipedia.org/wiki/File:Convolution3.PNG

    其次,默认情况下,scipy.signal.convolve2d用零填充边界,而您根本不对边界进行操作。要使用scipy.signal.convolve2d再现边界条件,请使用boundary='symm'(无论如何,对于此特定内核……通常,您只是忽略了边界,而convolve2d对此没有选择。)

    最后,出于您的目的(图像处理),使用scipy.ndimage.convolve效率更高。在这种情况下(一维内核),使用scipy.ndimage.convolve1d效率最高。例如。 scipy.ndimage.convolve1d(data, [1, 0, -1], axis=0)

    关于python scipy convolve2d似乎不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20077378/

    10-16 01:04