给定索引的图像插值 Python

6

我有一个大小约为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没有最近邻插值。如果库函数有最近邻插值(这样我就可以进行比较),那将是很好的。如果没有,也没关系。

2个回答

3

看起来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的图片和100,000个点在indices中进行了测试,总共不到一秒钟。


1
非常感谢。同时,我的代码有点改变了。我正在进行起点的移动和其他操作。现在,直接应用你的代码,结果全部都是NaN。我会尝试适当地设置并检查。之后我会接受这个回答。非常感谢! - Nagabhushan S N
一些原始图像中的“nan”值会导致问题。 “interpolated”全是“nan”。相反,如果我用“0”或“-1”替换图像中的所有“nan”,那么它就可以工作了。 image1 = numpy.where(numpy.isnan(image), -1, image) 有什么想法吗?或者如何在这种插值中使用“nan”? - Nagabhushan S N
不清楚使用“nan”进行插值会意味着什么——毕竟,它不是一个数字。我认为将原始图像中的“nan”值替换为零是有意义的,尽管这可能取决于它们存在的原因。 - Nathan Vērzemnieks
我正在实现全景图。因此,我需要将图像叠加在一起。在每个像素处,如果存在2个或更多的图像,则需要取它们的平均值。现在每个图像的大小可能不同。因此,我将所有图像放入足够大的矩阵中。在像素处,如果图像不存在,则用“nan”表示,以便稍后可以使用“numpy.nanmean”。 - Nagabhushan S N

0
或许可以尝试使用OpenCV中的cv.remap来解决这个问题。
import cv2 as cv
image = # as given
indices = # as given   

interpolated = cv.remap(image, indices[0], indices[1], cv.INTER_LINEAR, borderValue=np.nan)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接