对图像进行积分的有效方法

efficient way of performing integral on an image

我有一个二维数组(典型大小约为 400x100),如图所示(它看起来像一个梯形,因为右下角的元素是 nan)。对于数组中的每个元素,我想对几个元素(约 10 个元素)的列进行数值积分。在物理语言中,将颜色视为力的大小,我想通过计算 Fdz 的积分来找到所做的功。我可以使用双 for 循环并使用 trap 来完成这项工作,但是还有其他更有效的方法(可能是使用数组和矢量化)在 Matlab 或 python 中完成吗?我的最终目标是找到评估积分最大的点。所以从黄色代表大值的图像来看,我们期望积分最大的地方在虚线上方的右侧。

另外,如果我要积分的点数是整数的话,还是比较容易的,但是如果我要积分,比如7.5分呢?我正在考虑使用 fit 来插入点,但我不确定这是否会使任务过于复杂。

您可以使用 cumsum 来加速 trap。计算累计和(@Benjamin提出的一维积分图像)

>>> import numpy as np
>>> csdata = np.cumsum(data, axis=1)

与离散长度积分

>>> npoints = 6
>>> result = np.zeros_like(data)
>>> result[:-npoints, :]  = csdata[npoints:, :] - csdata[:-npoints, :]

result 是图像中每个 i, jcumdata[i+npoints, j] - cumdata[i, j] 的矢量化。最后 npoints 行将用零填充。如果你想防止这种情况,你可以 reflect 边界 np.pad

对于非离散区间,您可以使用插值法:

>>> from scipy.interpolate import interp2d
>>> C = 0.5   # to interpolate every npoints+C pixels
>>> y, x = np.mgrid[:data.shape[0], :data.shape[1]]
>>> ynew, xnew = np.mgrid[C:data.shape[0]+C, :data.shape[1]]
>>> f = interp2d(x, y, csdata)
>>> csnew = f(xnew, ynew)

上面在 y 方向上移动了一个规则的网格 C 像素,并在这些点上对累积数据 csdata 进行了插值(实际上,它对每个像素进行矢量插值)。

npoints+C长度的积分可得

>>> npoints = 6
>>> result = np.zeros_like(data)
>>> result[:-npoints, :]  = csnew[npoints:, :] - csdata[:-npoints, :]

请注意,上限现在是 csnew(移动 6 实际上得到 6.5 个元素),使其在实践中每 6.5 个点积分一次。

然后您可以找到最大点作为

>>> idx = np.argmax(result.ravel()) # ravel to get the 1D maximum point
>>> maxy, maxx = np.unravel_index(idx, data.shape) # get 2D coordinates of idx