我的目标是创建和可视化图像的偏导数(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
首先,我通过来自 scipy 模块(短路)的convolve2d函数为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],但这在数学上是不正确的。 有人能帮我吗 ?
答案 0 :(得分:8)
差异的原因有两方面:
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)
答案 1 :(得分:3)
f 和 g 的卷积是 f(x')g(x - x')的积分 DX' 。这样做的结果是内核翻转。要么使用翻转的内核,要么使用 f(x')g(x + x')的scipy.ndimage.correlate
,因此内核保持与输入相同的方向
有关详细信息,请参阅Convolution,有关有限差异的一些信息,请参阅Python finite difference functions?。