我正在尝试使用 scipy.ndimage.convolve 计算2d字段 A 的拉普拉斯。
stencil = numpy.array([[0, 1, 0],[1, -4, 1], [0, 1, 0]])
scipy.ndimage.convolve(A, stencil, mode='wrap')
但这似乎并没有给我正确答案。我出错的任何想法,还是有更好的方法来计算numpy中的laplacian?
答案 0 :(得分:2)
我有另一个想法:你是否考虑到你的模板,为了接近拉普拉斯算子,应该除以步骤** 2,其中步长是你的网格的步长?只有这样才能将ndimage.convolve结果与分析结果进行比较。
事实上,使用Gaussian,我得到的结果表明ndimage.convolve工作得很好:
from scipy import ndimage
stencil = numpy.array([[0, 1, 0],[1, -4, 1], [0, 1, 0]])
x = linspace(-10, 10, 100)
y = linspace(-10, 10, 100)
xx, yy = meshgrid(x, y)
image = exp(-xx**2-yy**2) # Standard deviation in x or y: 1/sqrt(2)
laplaced = ndimage.convolve(image, stencil)/(x[1]-x[0])**2 # stencil from original post
expected_result = -4*image + 8*(xx**2+yy**2)*image # Very close to laplaced, in most points!
答案 1 :(得分:1)
您是否尝试过其他laplace卷积内核,例如[[1,1,1][1,-8,1][1,1,1]]
?
答案 2 :(得分:1)
5年前,我想知道还有人在乎......
我认为这是因为卷积方法只是一种近似,模板基本上是通过有限离散微分逼近二阶导数。增量越小,数值逼近越接近。
我已根据其他人做过一些测试'信息。以下是代码和结果图:
import numpy
import scipy.ndimage.filters as filters
import scipy.signal as signal
import matplotlib.pyplot as plt
stencil=numpy.array([[0,1,0],[1,-4,1],[0,1,0]])
fig=plt.figure(figsize=(10,10),dpi=100)
for ii,jj in enumerate([10,100,1000,10000]):
x=numpy.linspace(-5,5,jj)
xx,yy=numpy.meshgrid(x,x)
step=x[1]-x[0]
image=numpy.exp(-xx**2-yy**2)
lap1=filters.laplace(image)/step**2
#lap2=filters.convolve(image,stencil,mode='wrap')/step**2
#lap3=signal.convolve2d(image,stencil,mode='same')/step**2
lap4=4*image*(xx**2+yy**2)-4*image
ax=fig.add_subplot(2,2,ii+1)
img=ax.imshow(lap1-lap4)
ax.set_title('stencil - analytical (dx=%.4f)' %step)
plt.colorbar(img)
fig.tight_layout()
plt.show()
filters.laplace()
,filters.convolve()
和signal.convolve2d()
都会给出非常接近的结果(事实上,如果你查看filters.laplace()的源代码,它实际上是做同样的事情作为一个模板内核的卷积,所以我只包括filters.laplace()
个。
请注意,上述所有内容都没有除以步长的平方。
该图显示增量步长越小,越接近分析解(即4z(x^2+y^2)-4z
)。
答案 3 :(得分:0)
我尝试了你的例子,它可以在我的机器上使用最新的SciPy。
我建议你绘制image-ndimage.convolve(…)
以便了解卷积如何改变你的形象。
示例:
image = vstack(arange(-10, 10)**2 for _ in range(20))
ndimage.convolve(image, stencil, mode='wrap')
产量
array([[-38, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...)
这是非常正确的(x ** 2的二阶导数为2) - 除了左边界。