Numpy inpaint nans интерполировать И экстраполировать

Я работаю над проектом, используя numpy и scipy, и мне нужно заполнить nanvalues. В настоящее время я использую scipy.interpolate.rbf, но он продолжает вызывать сбой python, так что попытка/исключение даже не спасет его. Однако после нескольких запусков кажется, что он может продолжать давать сбой в тех случаях, когда в середине есть данные, окруженные всеми нанами, например остров. Есть ли лучшее решение для этого, которое не будет продолжать падать?

Кстати, это МНОГО данных, которые мне нужно экстраполировать. Иногда до половины изображения (70 x 70, оттенки серого), но оно не обязательно должно быть идеальным. Это часть программы сшивания изображений, поэтому, пока она похожа на фактические данные, она будет работать. Я пробовал ближайший сосед заполнить nans, но результаты слишком разные.

ИЗМЕНИТЬ:

Изображение, на котором он всегда кажется неудачным. Изоляция этого образа позволила передать его ОДИН РАЗ перед сбоем. Неверное изображение

Я использую как минимум версии NumPy 1.8.0 и SciPy 0.13.2.


person wbest    schedule 11.02.2014    source источник
comment
Не могли бы вы опубликовать небольшой пример, демонстрирующий сбой?   -  person perimosocordiae    schedule 11.02.2014
comment
Какую версию scipy вы используете?   -  person Warren Weckesser    schedule 11.02.2014
comment
Я обновил свой вопрос с изображением и версией.   -  person wbest    schedule 11.02.2014


Ответы (2)


Использование SciPy LinearNDInterpolator. Если все изображения имеют одинаковый размер, координаты сетки могут быть предварительно вычислены и использованы повторно.

import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate

x = np.linspace(0, 1, 500)
y = x[:, None]
image = x + y

# Destroy some values
mask = np.random.random(image.shape) > 0.7
image[mask] = np.nan

valid_mask = ~np.isnan(image)
coords = np.array(np.nonzero(valid_mask)).T
values = image[valid_mask]

it = interpolate.LinearNDInterpolator(coords, values, fill_value=0)

filled = it(list(np.ndindex(image.shape))).reshape(image.shape)

f, (ax0, ax1) = plt.subplots(1, 2)

ax0.imshow(image, cmap='gray', interpolation='nearest')
ax0.set_title('Input image')
ax1.imshow(filled, cmap='gray', interpolation='nearest')
ax1.set_title('Interpolated data')
plt.show()

Интерполированные отсутствующие значения

person Stefan van der Walt    schedule 11.02.2014
comment
Это не совсем решает мою проблему (хотя отчасти это моя вина, что я не включил изображение), так как мне нужно больше экстраполировать, чем интерполировать. Но предварительное вычисление координат сетки — хороший выбор. - person wbest; 11.02.2014
comment
Как будет выглядеть правильная экстраполяция? Почему бы просто не отразить изображение? Практически любая экстраполяция действительна за пределами данного изображения. - person Stefan van der Walt; 12.02.2014
comment
Подход с ближайшим соседом был бы в порядке, за исключением того, что этот метод приводит к полосам, которые мне не нужны. Я думаю, что на самом деле у меня есть метод, работающий сейчас, который дает разумные результаты, когда я заполняю края средним значением всего квадрата, а затем использую данные сетки для линейной интерполяции. - person wbest; 12.02.2014

Этого оказалось достаточно для моих нужд. Это на самом деле довольно быстро и дает разумные результаты:

ipn_kernel = np.array([[1,1,1],[1,0,1],[1,1,1]]) # kernel for inpaint_nans

def inpaint_nans(im):
    nans = np.isnan(im)
    while np.sum(nans)>0:
        im[nans] = 0
        vNeighbors = scipy.signal.convolve2d((nans==False),ipn_kernel,mode='same',boundary='symm')
        im2 = scipy.signal.convolve2d(im,ipn_kernel,mode='same',boundary='symm')
        im2[vNeighbors>0] = im2[vNeighbors>0]/vNeighbors[vNeighbors>0]
        im2[vNeighbors==0] = np.nan
        im2[(nans==False)] = im[(nans==False)]
        im = im2
        nans = np.isnan(im)
    return im
person wbest    schedule 18.02.2014
comment
Похоже, что это похоже на один метод вставки в OpenCV (INPAINT_TELEA): docs .opencv.org/3.4.0/df/d3d/tutorial_py_inpainting.html - person moi; 27.01.2019