如何使用 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.convolve2d
和 mode='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 个邻居的平均值,硬编码内核将无法正确处理角和边界像素。也许,设置不除法的内核,并存储三个不同的卷积结果,每个结果除以 2
、3
或 4
,然后选择正确的值 w.r.t。存在角、边界或规则像素。
我有一张图片,为了解决这个问题,它只是一个 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.convolve2d
和 mode='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 个邻居的平均值,硬编码内核将无法正确处理角和边界像素。也许,设置不除法的内核,并存储三个不同的卷积结果,每个结果除以 2
、3
或 4
,然后选择正确的值 w.r.t。存在角、边界或规则像素。