【问题标题】:Python: Efficiently interpolate from an irregular grid to a regular grid in 2DPython:在 2D 中有效地从不规则网格插值到规则网格
【发布时间】:2018-08-14 21:48:49
【问题描述】:

我在不规则间隔的二维网格中有一些数据点,我想将其插入到规则网格中。例如,假设源数据来自鱼眼相机:
不规则源网格示例。注意...这些只是示例 - 一般来说,源数据也可能以不同的方式扭曲 - 但仍然来自网格。

# Source Data
x_src  # A (n_src_rows, n_src_cols) array of x-coordinates of points
y_src  # A (n_src_rows, n_src_cols) array of y-coordinates of points
       # (x_src, y_src) form an irregular grid.  i.e. if you were to plot the lines connecting neighbouring points, no lines would ever cross.
f_src  # A (n_src_rows, n_src_cols) array of values.

# Interpolation Points: 
x_dst  # An (n_dest_cols) sorted array of x-coordinates of columns in a regular grid
y_dst  # An (n_dest_rows) sorted array of y-coordinates of rows in a regular grid.

# Want to calculate:
f_dst  # An (n_dest_rows, n_dest_cols) array of interpolated data on the regular grid defined by x_dst, y_dst

到目前为止,我一直在使用scipy.interpolate.griddata,并将源点展平为一维数组,但速度有点慢,因为它没有利用源数据点的网格结构(只有目标数据点)。它还会在不在相邻源网格点内的区域中进行插值(如果源网格的边界是凹的(如左图所示),则会发生这种情况。

SciPy/opencv 或类似库中是否有一个函数可以在源数据进入不规则间隔的网格时有效地进行插值?

【问题讨论】:

  • 从优化的角度来看:如果不规范问题(或者它是病态的),就没有(好的)方法。你需要定义关于你可能的扭曲的假设。
  • 有一个相当强的假设——源数据以网格形式出现。没有其他点会落在(xy[i,j], xy[i+1,j], xy[i,j+1]) 之间的三角形中。 Scipy 的griddata 没有使用这些知识(它对源数据的结构没有事先假设)。

标签: python opencv image-processing scipy interpolation


【解决方案1】:

【讨论】:

  • 来自the Documentation,它要么要求源点位于规则网格中,要么只需要源点的平面向量。所以它不能利用不规则的源点网格。这个功能我已经试过了,运行很慢。
  • 你能定义一个函数将你的不规则点映射到规则网格吗?如果是这样,您可以映射 x_src、y_src 和 x_dst、y_dst 并使用常规网格执行插值。
  • 你的意思是一个函数x_newsrc, y_newsrc = f(x_src, y_src) 其中(x_newsrc, y_newsrc) 形成一个规则网格?也许我可以,但为了正确起见,我必须将相同的功能应用于我的目标网格,然后我最终得到一个规则的源网格和一个不规则的目标网格......以及同样的问题。
  • 是的,您还需要应用 x_dsty_dst 的功能。具有不规则的目标网格不是同样的问题。
  • 有一点值得注意的是,这个想要的函数,如果应用于地理坐标数据(即:经度和纬度),它必须考虑到测地距离。因此,线性(甚至是多项式、样条等)函数不会返回正确的插值结果。
【解决方案2】:

嗯,它仍然不是最优的,因为它没有利用源数据已知位于网格中这一事实,但到目前为止我发现的最佳方法是使用 SciPy 的 NearestNDInterpolator,它基于KDTree:

import scipy.interpolate 

def fast_interp_irregular_grid_to_regular(
        x_dst,  # type: ndarray(dst_size_x)  # x-values of columns in the destination image.
        y_dst,  # type: ndarray(dst_size_y)  # y-values of rows in the destination image
        x_src,  # type: ndarray(src_size_y, src_sixe_x)   # x-values of data points
        y_src,  # type: ndarray(src_size_y, src_size_x)   # y-values of data points
        f_src,  # type: ndarray(src_size_y, src_size_x, n_dim)  # values of data points.
        fill_value = 0,  # Value to fill in regions outside pixel hull
        zero_edges = True,  # Zero the edges (ensures that regions outside source grid are zero)
    ):  # type: (...) -> array(dst_size_y, dst_size_x, n_dim)  # Interpolated image
    """
    Do a fast interpolation from an irregular grid to a regular grid.  (When source data is on a grid we can interpolate
    faster than when it consists of arbitrary points).

    NOTE: Currently we do not exploit the fact that the source data is on a grid.  If we were to do that, this function
    could be much faster.
    """
    assert zero_edges in (False, True, 'inplace')

    univariate = f_src.ndim==1
    if univariate:
        f_src = f_src[:, None]
    else:
        assert f_src.ndim==3

    if zero_edges:
        if zero_edges is True:
            f_src = f_src.copy()
        f_src[[0, -1], :] = fill_value
        f_src[:, [0, -1]] = fill_value
    interp = scipy.interpolate.NearestNDInterpolator(
        x = np.hstack([x_src.reshape(-1, 1), y_src.reshape(-1, 1)]),
        y = f_src.reshape(-1, f_src.shape[-1]),
    )
    grid_x, grid_y = np.meshgrid(x_dst, y_dst)
    z = interp((grid_x, grid_y)).reshape((len(y_dst), len(x_dst), f_src.shape[-1]))
    return z

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-13
    • 2014-03-08
    • 2023-03-10
    • 2011-12-03
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2013-08-26
    相关资源
    最近更新 更多