Интерполировать изображение для заданных индексов python - PullRequest
3 голосов
/ 29 марта 2019

У меня есть изображение размером около 8000x9000 в виде матрицы. У меня также есть список индексов в матрице 2xn Numpy. Эти индексы являются дробными, а также могут не соответствовать размеру изображения. Мне нужно интерполировать изображение и найти значения для заданных индексов. Если индексы выходят за пределы, мне нужно вернуть numpy.nan для них. В настоящее время я делаю это для цикла, как показано ниже

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 , но я не могу его использовать. Может кто-нибудь объяснить, как использовать этот или любой другой метод тоже хорошо. Я также нашел это , но, опять же, это не соответствует моим требованиям. С учетом индексов 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 Ответ

1 голос
/ 30 марта 2019

Похоже, что 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, и все сказали, что это заняло менее секунды.

...