为什么在非均匀间隔样本上,MATLAB interp2比SciPy快得多?

时间:2019-06-04 00:04:36

标签: python matlab image-processing scipy interpolation

我有一个图像投影问题,在最后一步中,我需要在源图像上使用双线性插值法,以到达目标点的间距不均匀。 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方法似乎都希望目标是等距点的2D网格,而不是点的随机散布。 (例如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])

正如您可能期望的那样,循环需要很长时间(strongstrong)。我相信一定有更好的方法。我找到的最接近的东西是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。它仍然插值到这些值。然后,这需要找到凸包,并手动消除该包之外的值,这很慢。

1 个答案:

答案 0 :(得分:1)

问题是您正在使用的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中并查看其性能。

有关思想和概念,请参见herehere