简体   繁体   English

Numpy 数组的快速插值/重采样 - Python

[英]Fast Interpolation / Resample of Numpy Array - Python

Currently, I have written some Python code that is inserted into a pipeline.目前,我已经编写了一些插入管道的 Python 代码。

The incoming data comes in in a numpy array of shape (1,512,19,25).传入的数据以形状为 (1,512,19,25) 的 numpy 数组形式出现。 I use the scipy.ndimage.interpolation.zoom to bring the array up to shape (1,512,38,50).我使用scipy.ndimage.interpolation.zoom将数组调整为形状(1,512,38,50)。 This can be accomplished with one call to the function.这可以通过对函数的一次调用来完成。 Basically, it resizes each (19,25) piece to size (38,50).基本上,它将每个 (19,25) 块的大小调整为 (38,50)。

Later in the code, when the data is moving the other way, different data is again resized the in the other direction (38,50) to (19,25).在代码的后面,当数据以另一种方式移动时,不同的数据再次从另一个方向 (38,50) 调整为 (19,25)。

Everything works as implemented, however I am finding that this is really slow.一切都按实施进行,但是我发现这真的很慢。 For example, I tested the scipy.ndimage.interpolation.zoom function to resize an image file and it was way slower than Matlab's imresize function.例如,我测试了scipy.ndimage.interpolation.zoom函数来调整图像文件的大小,它比 Matlab 的imresize函数慢得多。

What are faster ways to do this in Python?在 Python 中执行此操作的更快方法是什么?

TLDR; TLDR; Check out Skimage's pyramid_gaussian .查看 Skimage 的pyramid_gaussian On a single image of (512, 512) it shows an order of 0.3M times speed-up.在 (512, 512) 的单个图像上,它显示了 0.3M 倍的加速。 (163 ms/471 ns = 346072). (163 毫秒/471 纳秒 = 346072)。 Pillow-SIMD does super-fast resamples/resize but requires you to uninstall PIL, Pillow before you install it. Pillow-SIMD执行超快速重新采样/调整大小,但需要您在安装之前卸载 PIL、Pillow。 It uses parallel processing (single instruction, multiple data - SIMD) and better algorithms such as replacing a convolution-based Gaussian blur with a sequential-box one.它使用并行处理(单指令、多数据 - SIMD)和更好的算法,例如用顺序框模糊替换基于卷积的高斯模糊。 Advice to use this for production environments after setting up a separate venv .建议在设置单独的venv后将其用于生产环境。


There are multiple ways of upsampling and downsampling your image.有多种方法可以对图像进行上采样和下采样。 I will add some benchmarks of the methods that I have worked with.我将添加一些我使用过的方法的基准。 I will keep updating this answer as I come across more methods so that this can act as a reference for others on SO.当我遇到更多方法时,我会不断更新这个答案,以便这可以作为其他人的参考。

#Utility function for plotting original, upsampled, and downsampled image

def plotit(img, up, down):
    fig, axes = plt.subplots(1,3, figsize=(10,15))
    axes[0].imshow(img)
    axes[1].imshow(up)
    axes[2].imshow(down)
    axes[0].title.set_text('Original')
    axes[1].title.set_text('Upsample')
    axes[2].title.set_text('Downsample')

IIUC, this is somewhat your pipeline - IIUC,这有点像你的管道 -

from scipy.ndimage import zoom
from skimage.data import camera

img = camera() #(512,512)
up = zoom(img,2) #upsample image

#some code
...

down = zoom(up,0.5) #downsample the upsampled image

plotit(img, up, down)

在此处输入图片说明


Methods & Benchmarks (in no specific order)方法和基准(in no specific order)

1. Scipy zoom (order=3) 1. Scipy 缩放(order=3)

The array is zoomed using spline interpolation of a given order, in this case, the default is order = 3.使用给定顺序的样条插值对数组进行缩放,在这种情况下,默认值为 order = 3。

%%timeit
#from scipy.ndimage import zoom
up = zoom(img,2)
down = zoom(up,0.5)

#163 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

2. Scipy zoom (order=0) 2. Scipy 缩放(order=0)

The array is zoomed using spline interpolation of a given order, in this case, order = 0.使用给定顺序的样条插值对数组进行缩放,在本例中,order = 0。

%%timeit
#from scipy.ndimage import zoom
up = zoom(img,2, order=0)
down = zoom(up,0.5, order=0)

#18.7 ms ± 950 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

3. Skimage pyramid_gaussian 3. Skimage pyramid_gaussian

In a Gaussian pyramid, subsequent images are weighted down using a Gaussian average (Gaussian blur) and scaled-down.在高斯金字塔中,后续图像使用高斯平均值(高斯模糊)进行加权并按比例缩小。 Applying a Gaussian blur to an image is the same as convolving the image with a Gaussian function.对图像应用高斯模糊与使用高斯函数对图像进行卷积相同。 The amount of blur depends on the standard deviation size (sigma).模糊量取决于标准偏差大小 (sigma)。

%%timeit
#from skimage.transform import import pyramid_gaussian
up = pyramid_gaussian(img,2)
down = pyramid_gaussian(up,0.5)

#471 ns ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

4. Skimage pyramid_expand and pyramid_reduce 4. Skimage pyramid_expandpyramid_reduce

An image pyramid is a type of multi-scale image representation in which an image is subject to repeated smoothing and subsampling.图像金字塔是一种多尺度图像表示,其中对图像进行重复平滑和二次采样。 The first function smooths and then upsamples the image, while the second does the same but instead downsamples, both of these use spline order=1 by default.第一个函数对图像进行平滑然后上采样,而第二个函数执行相同但下采样,默认情况下这两个函数都使用样条顺序=1。

%%timeit
#from skimage.transform import import pyramid_expand, pyramid_reduce
up = pyramid_expand(img,2)
down = pyramid_reduce(up,2)

#120 ms ± 3.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

5. Skimage rescale 5. Skimage 重新缩放

Scales an image by a certain factor.按特定因子缩放图像。 Performs spline interpolation (order=1 by default) to up-scale or down-scale N-dimensional images.对放大或缩小 N 维图像执行样条插值(默认为 1 阶)。 Note that anti-aliasing should be enabled when down-sizing images to avoid aliasing artifacts.请注意,在缩小图像尺寸时应启用抗锯齿以避免锯齿伪影。

%%timeit
#from skimage.transform import import rescale
up = rescale(img,2)
down = rescale(up,0.5)

#83 ms ± 3.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

6. PIL resize with Nearest pixel filter for resampling 6. PIL 使用最近像素过滤器调整大小以进行重采样

Returns a resized copy of this image.返回此图像的调整大小副本。 Picks one nearest pixel from the input image.从输入图像中选择一个最近的像素。 Ignores all other input pixels.忽略所有其他输入像素。

%%timeit
#from PIL import Image
im = Image.fromarray(img)
up = im.resize((im.width*2, im.height*2),resample=Image.NEAREST)
down = up.resize((up.width//2, up.height//2),resample=Image.NEAREST)

#704 µs ± 29.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

7. PIL resize with BILINEAR filter for resampling 7. 使用 BILINEAR 过滤器调整PIL大小以进行重采样

Returns a resized copy of this image.返回此图像的调整大小副本。 For resize calculates the output pixel value using linear interpolation on all pixels that may contribute to the output value.对于调整大小,对可能对输出值有贡献的所有像素使用线性插值计算输出像素值。 For other transformations, linear interpolation over a 2x2 environment in the input image is used.对于其他转换,使用输入图像中 2x2 环境的线性插值。

%%timeit
#from PIL import Image
im = Image.fromarray(img)
up = im.resize((im.width*2, im.height*2),resample=Image.BILINEAR)
down = up.resize((up.width//2, up.height//2),resample=Image.BILINEAR)

#10.2 ms ± 877 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

8. PIL resize with BICUBIC filter for resampling 8. 使用 BICUBIC 过滤器调整PIL大小以进行重采样

Returns a resized copy of this image.返回此图像的调整大小副本。 For resize calculates the output pixel value using cubic interpolation on all pixels that may contribute to the output value.对于调整大小,对可能对输出值有贡献的所有像素使用三次插值计算输出像素值。 For other transformations cubic interpolation over a 4x4 environment in the input image is used.对于其他转换,使用输入图像中 4x4 环境的三次插值。

%%timeit
#from PIL import Image
im = Image.fromarray(img)
up = im.resize((im.width*2, im.height*2),resample=Image.BICUBIC)
down = up.resize((up.width//2, up.height//2),resample=Image.BICUBIC)

#12.3 ms ± 326 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

9. PIL resize with Lanczos filter for resampling 9. 使用 Lanczos 过滤器调整PIL大小以进行重采样

Returns a resized copy of this image.返回此图像的调整大小副本。 Calculates the output pixel value using a high-quality Lanczos filter (a truncated sinc) on all pixels that may contribute to the output value.使用高质量 Lanczos 滤波器(截断的 sinc)对可能对输出值有贡献的所有像素计算输出像素值。

%%timeit
#from PIL import Image
im = Image.fromarray(img)
up = im.resize((im.width*2, im.height*2),resample=Image.LANCZOS)
down = up.resize((up.width//2, up.height//2),resample=Image.LANCZOS)

#15.7 ms ± 184 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Check the benchmarks in https://python-pillow.org/pillow-perf/检查https://python-pillow.org/pillow-perf/ 中的基准

TL;DR: for most scenarios the fastest way in Python is using pillow-simd . TL;DR:对于大多数情况,Python 中最快的方法是使用Pillow-simd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM