如何使用 Numpy 高效地执行最近邻插值

How to efficiently perform closest neighbor interpolation with Numpy

我有一张图片,为了解决这个问题,它只是一个 numpy 数组。我想过滤图像以去除孤立透明像素形式的噪声(更一般地说,我也想去除线条,但这是下一个问题)。

让我们举一个可玩的例子:

a = np.ones((10, 10), np.uint8)
a[5,5] = 0    # isolated hole
a[5,6] = 2    # the neighbour to clone

通往这个矩阵:

       [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 0, 2, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

好吧,问题是当矩阵中有一个0时,我希望它被最近的邻居替换(在这种情况下为2,但也许是四个的平均值,如果容易实现,将会更好)。

这可以在没有显式循环的情况下完成吗?

使用 boolean array indexing. To calculate the described average, use scipy.signal.convolve2dmode='same' 以及以下内核检测 a 中的 0 条目:

kernel = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / 4

最后,将a中找到的0项替换为卷积结果中的相应项。请参阅此代码段:

import numpy as np
from scipy.signal import convolve2d

a = np.ones((10, 10), np.uint8)
a[5, 5] = 0
a[5, 6] = 2
print(a)

kernel = np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) / 4
b = convolve2d(a, kernel, mode='same')
a[a == 0] = b[a == 0]
print(a)

结果是:

[[1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 2 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]]

由于您将 a 初始化为 np.uint8,实际替换值 1.25 被截断为 1。如果将 a 初始化为 np.float32,您会看到 1.25 正确放置在那里。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.1
SciPy:         1.6.0
----------------------------------------

编辑: 如果您只是想计算仅有的 two/three 个邻居的平均值,硬编码内核将无法正确处理角和边界像素。也许,设置不除法的内核,并存储三个不同的卷积结果,每个结果除以 234,然后选择正确的值 w.r.t。存在角、边界或规则像素。