Python:快速离散插值

leo*_*leo 5 python interpolation numpy scipy

给定一个表示离散坐标变换函数的 4D 数组,使得

arr[x_in, y_in, z_in] = [x_out, y_out, z_out]

我想插值arr到具有更多元素的网格(假设中的样本arr最初是从高元素立方体的规则间隔网格中提取的)。我已经尝试过RegularGridInterpolator来自 scipy,但是这相当慢:

import numpy as np
from scipy.interpolate import RegularGridInterpolator
from time import time

target_size   = 32
reduced_size  = 5

small_shape = (reduced_size,reduced_size,reduced_size,3)
cube_small  = np.random.randint(target_size, size=small_shape, dtype=np.uint8)

igrid = 3*[np.linspace(0, target_size-1, reduced_size)]
large_shape = (target_size, target_size, target_size,3)
cube_large  = np.empty(large_shape)

t0 = time()
interpol = RegularGridInterpolator(igrid, cube_small)
for x in np.arange(target_size):
    for y in np.arange(target_size):
        for z in np.arange(target_size):
            cube_large[x,y,z] = interpol([x,y,z])
print(time()-t0)
Run Code Online (Sandbox Code Playgroud)

有没有想到更适合该任务的算法?也许有一些东西可以利用这样一个事实,即在这种情况下,我只对每个点的离散整数值感兴趣。

Cri*_*lla 1

我真的不能说网格的生成,因为我不完全确定你想要做什么。但就提高效率而言,使用三重 for 循环而不是使用广播会大大减慢代码速度

import itertools
import numpy as np
from scipy.interpolate import RegularGridInterpolator
from time import time

target_size   = 32
reduced_size  = 5

small_shape = (reduced_size,reduced_size,reduced_size,3)
cube_small  = np.random.randint(target_size, size=small_shape, dtype=np.uint8)


igrid = 3*[np.linspace(0, target_size-1, reduced_size)]


large_shape = (target_size, target_size, target_size,3)
cube_large  = np.empty(large_shape)

def original_method():
    t0 = time()

    interpol = RegularGridInterpolator(igrid, cube_small)
    for x in np.arange(target_size):
        for y in np.arange(target_size):
            for z in np.arange(target_size):
                cube_large[x,y,z] = interpol([x,y,z])

    print('ORIGINAL METHOD: ', time()-t0)
    return cube_large

def improved_method():
    t1 = time()
    interpol = RegularGridInterpolator(igrid, cube_small)

    arr = np.arange(target_size)
    grid = np.array(list(itertools.product(arr, repeat=3)))
    cube_large = interpol(grid).reshape(target_size, target_size, target_size, 3)

    print('IMPROVED METHOD:', time() - t1)

    return cube_large


c1 = original_method()
c2 = improved_method()

print('Is the result the same?  ', np.all(c1 == c2))
Run Code Online (Sandbox Code Playgroud)

输出

ORIGINAL METHOD:  6.9040000438690186
IMPROVED METHOD: 0.026999950408935547
Is the result the same?   True
Run Code Online (Sandbox Code Playgroud)