我有一个图像投影问题,在最后一步中,我需要在源图像上使用双线性插值到间隔不均匀的目标点。 MATLAB 可以很好地处理这个问题,并使用 interp2
非常快速地计算答案。 MATLAB 示例:
img = imread('ngc6543a.jpg');
img = double(rgb2gray(img)) / 256;
[img_col, img_row] = meshgrid(1:size(img, 2), 1:size(img, 1));
interp_rows = 325+200*randn(1, 100000);
interp_cols = 300*200*randn(1, 100000);
tic
img_interp = interp2(img_col, img_row, omg, interp_rows, interp_cols)
toc
>Elapsed time is 0.011680 seconds.
据我所知,在 Python 中,没有办法以几乎同样快的速度插值到非均匀采样点。所有典型的 SciPy 方法似乎都希望目标也是等距点的二维网格,而不是随机散布的点。 (例如scipy.interpolate.interp2d
)。在 SciPy 中执行相同的操作需要 for 循环:
from scipy.interpolate import interp2d
import numpy as np
% Does NOT interpolate to points outside the convex hull (which is good)
interpolator = interp2d(img_col, img_row, img)
interp_rows = 325+200*np.random.randn(1, 100000);
interp_cols = 300*200*np.random.randn(1, 100000);
result = np.empty((100000,), dtype=np.float)
for i in range(100000):
result[i] = interpolator(interp_cols[i], interp_rows[i])
正如人们所期望的那样,这需要一个非常长的时间的循环。我确信一定有更好的方法。我发现的最接近的是 scipy.interpolate.RectBivariateSpline 。有了这个,我几乎可以以与 MATLAB 几乎相同的速度完成我想要的事情:
from scipy.interpolate import RectBivariateSpline
% DOES interpolate to points outside the convex hull (which is bad)
interpolator = RectBivariateSpline(img_col, img_row, img)
img_interp = interpolator(interp_cols, interp_rows, grid=False)
此方法的问题在于,它不会将源凸包之外的值设置为 NaN。它仍然插入到这些值。然后,这需要手动找到凸包并消除凸包之外的值,这很慢。
最佳答案
问题是您正在使用的 for 循环:
for i in range(100000):
result[i] = interpolator(interp_cols[i], interp_rows[i])
在 MATLAB 代码中,您使用的是矢量化方法:
img_interp = interp2(img_col, img_row, omg, interp_rows, interp_cols)
使用 scipy 也可以实现同样的效果:
result = interpolator(interp_cols, interp_rows)
这应该会给你带来相当好的加速。
避免在 Python 中使用 for 循环。通常 Numpy/Scipy 中有一种向量化方法。
MATLAB 可能仍然稍快一些,但是当您发现计算时间可能慢 2 到 100 倍时,您在 Python 中做错了什么。
为了进行比较,您可以尝试将 for 循环添加到 MATLAB 中并查看其执行情况。
关于python - 为什么 MATLAB interp2 在非均匀间隔样本上比 SciPy 快得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56435870/