python scipy convolve2d似乎不正确

use*_*445 4 python convolution scipy python-2.7

我的目标是创建和可视化图像的偏导数(2D).我将使用第一个有限中心差分方程 维基百科.

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
Run Code Online (Sandbox Code Playgroud)

首先,我通过scolveyd(短路)的convolve2d函数为x和y 创建第一个中心有限差分

kernel=array([[-1,0,1]])     #create first central finite difference kernel
pdx=sg.convolve2d(myImage,kernel,"same")   #dI(x,y)/dx 
Run Code Online (Sandbox Code Playgroud)

现在我创建相同的使用循环

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))
Run Code Online (Sandbox Code Playgroud)

我们来看看结果:

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.]])
Run Code Online (Sandbox Code Playgroud)

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.]])
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*ton 8

差异的原因有两方面:

  1. 你已经忘记了在卷积的数学定义中内核的翻转.
  2. 你假设边界条件不同于 scipy.signal

而且,对于你正在做的事情,你几乎肯定想要scipy.ndimage.convolve而不是scipy.signal.convolve2d.默认值设置为ndimage使用图像,对于有限精度的整数数据更有效,这是图像的标准.


要重现你的循环版本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)


ask*_*han 3

fg的卷积是f(x') g(x - x')dx'的积分。这样做的结果是内核被翻转。要么使用翻转的内核,要么使用scipy.ndimage.correlate执行f(x') g(x + x') 的函数,以便内核保持与输入相同的方向。

有关更多信息,请参阅卷积;有关有限差分的一些信息,请参阅Python 有限差分函数?