给定索引python

时间:2019-03-29 05:12:12

标签: python image numpy scipy interpolation

我有一个大约8000x9000大小的图像作为numpy矩阵。我也有一个在numpy 2xn矩阵中的索引列表。这些索引是分数,也可能超出图像大小。我需要对图像进行插值并找到给定索引的值。如果索引不在外面,我需要为它们返回numpy.nan。目前,我正在如下所示的for循环中进行操作

def interpolate_image(image: numpy.ndarray, indices: numpy.ndarray) -> numpy.ndarray:
    """

    :param image:
    :param indices: 2xN matrix. 1st row is dim1 (rows) indices, 2nd row is dim2 (cols) indices
    :return:
    """
    # Todo: Vectorize this
    M, N = image.shape
    num_indices = indices.shape[1]
    interpolated_image = numpy.zeros((1, num_indices))
    for i in range(num_indices):
        x, y = indices[:, i]
        if (x < 0 or x > M - 1) or (y < 0 or y > N - 1):
            interpolated_image[0, i] = numpy.nan
        else:
            # Todo: Do Bilinear Interpolation. For now nearest neighbor is implemented
            interpolated_image[0, i] = image[int(round(x)), int(round(y))]
    return interpolated_image

但是for循环要花费大量时间(如预期的那样)。如何将其向量化?我找到了scipy.interpolate.interp2d,但无法使用它。有人可以解释如何使用此方法或任何其他方法也可以。我还找到了this,但同样不符合我的要求。给定x和y索引,这些将生成插值矩阵。我不要对于给定的索引,我只需要插值,即我需要向量输出。不是矩阵。

我尝试过这样,但是如上所述,它给出了矩阵输出

f = interpolate.interp2d(numpy.arange(image.shape[0]), numpy.arange(image.shape[1]), image, kind='linear')
interp_image_vect = f(indices[:,0], indices[:,1])
RuntimeError: Cannot produce output of size 73156608x73156608 (size too large)

目前,我已经实现了最近邻插值。 scipy interp2d没有最近的邻居。如果该库充当最近的邻居,那会很好(因此我可以进行比较)。如果没有,那就还好。

1 个答案:

答案 0 :(得分:1)

看起来scipy.interpolate.RectBivariateSpline可以解决问题:

from scipy.interpolate import RectBivariateSpline
image = # as given
indices = # as given

spline = RectBivariateSpline(numpy.arange(M), numpy.arange(N), image)

interpolated = spline(indices[0], indices[1], grid=False)

这会为您提供插值,但不会在需要的地方提供nan。您可以使用where来实现:

nans = numpy.zeros(interpolated.shape) + numpy.nan
x_in_bounds = (0 <= indices[0]) & (indices[0] < M)
y_in_bounds = (0 <= indices[1]) & (indices[1] < N)
bounded = numpy.where(x_in_bounds & y_in_bounds, interpolated, nans)

我用2624x2624图像和indices中的100,000点对此进行了测试,所有结果都花了不到一秒钟。