Numpy array of high-order interpolation fast (high-order push) algorithm to explore

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/xufive/article/details/94718525

In the field of scientific computing and data processing, data interpolation is a problem we often face. Although numpy itself provides numpy.interp interpolation function, but can only do one-dimensional linear interpolation, therefore, in practical work, we use more of scipy interpolate sub-modules. On the relationship numpy and scipy are interested, you can refer to my book "Mathematical Modeling Three Musketeers MSN" .

Unfortunately, scipy.interpolate provide only one-dimensional and two-dimensional interpolation algorithm, and the famous commercial software Matlab, there are three-dimensional interpolation function is available. In fact, three-dimensional and even higher order interpolation demand is still quite common. For example, when the three-dimensional volume data rendering, in order to enhance the display, so that the data body look more delicate, three-dimensional interpolation is essential. The figure is a three-dimensional display contrast before and after the data interpolation 3D (using pyopengl drawing).
Here Insert Picture DescriptionAnd even the three-dimensional higher order interpolation data, referred to as higher-order push, are usually linear interpolation. The most natural idea is circulating calling scipy.interpolate of interp1d or interp2d three-dimensional interpolation function, but calling the cycle of low efficiency unbearable, completely fail to reflect numpy broadcast and vectorization features.

Internet was proposed _bspleval () function uses _spline properties and low level in _fitpack module in order to achieve high-order push. For details, see "python - Fast interpolation on 3D array" . Text of the code I still went to great lengths not to run through.

So, we can help numpy characteristics of broadcasting and vectorization, to achieve high-order push it? After verification, this idea is feasible. We began to discuss start with a one-dimensional linear interpolation.

  1. Repeat use of function element repeat () is a length extended to a length of n-dimensional array is an array of 2n-1, the element row even positions in front of an element is repeated;
  2. All elements of the even-numbered positions minus half the difference between the front and rear elements.

Let's verify:

import numpy as np
>>> a = np.arange(5, dtype=np.float)
>>> a
array([0., 1., 2., 3., 4.])
>>> a = a.repeat(2)[:-1]
>>> a
array([0., 0., 1., 1., 2., 2., 3., 3., 4.])
>>> a[1::2] += (a[2::2]-a[1::2])/2
>>> a
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. ])

Results in line with expectations, fully vectorized! Further verification can also prove that the method of numpy.nan type of data processing in line with our expectations.

>>> a = np.arange(5, dtype=np.float)
>>> a[2] = np.nan
>>> a
array([ 0.,  1., nan,  3.,  4.])
>>> a = a.repeat(2)[:-1]
>>> a
array([ 0.,  0.,  1.,  1., nan, nan,  3.,  3.,  4.])
>>> a[1::2] += (a[2::2]-a[1::2])/2
>>> a
array([0. , 0.5, 1. , nan, nan, nan, 3. , 3.5, 4. ])

Next, we can try to achieve three-dimensional array of linear interpolation with this idea of. code show as below:

import numpy as np

def interp3d(arr_3d):
    """三维数组线性插值
    
    arr_3d      - numpyp.ndarray类型的三维数组
    """
    
    layers, rows, cols = arr_3d.shape
    
    arr_3d = arr_3d.repeat(2).reshape((layers*rows, -1))
    arr_3d = arr_3d.repeat(2, axis=0).reshape((layers, -1))
    arr_3d = arr_3d.repeat(2, axis=0).reshape((layers*2, rows*2, cols*2))[:-1, :-1, :-1]
    
    
    arr_3d[:,:,1::2] += (arr_3d[:,:,2::2]-arr_3d[:,:,1::2])/2
    arr_3d[:,1::2,:] += (arr_3d[:,2::2,:]-arr_3d[:,1::2,:])/2
    arr_3d[1::2,:,:] += (arr_3d[2::2,:,:]-arr_3d[1::2,:,:])/2
    
    return arr_3d

if __name__ == '__main__':
    import time
    
    arr_3d = np.random.randn(100, 200, 300)
    print(u'插值前数组的shape:', arr_3d.shape)
    
    t0 = time.time()
    arr_3d = interp3d(arr_3d)
    t1 = time.time()
    
    print(u'插值后数组的shape:', arr_3d.shape)
    print(u'耗时%.03f秒'%(t1-t0,))

Results are as follows:

PS D:\XufiveGit\interp3d> py -3 .\test.py
插值前数组的shape: (100, 200, 300)
插值后数组的shape: (199, 399, 599)
耗时1.281秒

Within the scope of my knowledge, this should be the fastest high-order interpolation algorithm of the fast. Although great care was then also Fugan professionals also, it will be to share in enthusiasts.

Guess you like

Origin blog.csdn.net/xufive/article/details/94718525