1

我正在与您核实是否有一个简洁的 numpy 解决方案来使用双线性过滤来调整 2D numpy 数组(这是一个图像)的大小?

更具体地说,我的数组具有形状(宽度,高度,4)(如在 rgba 图像中)。缩小比例也只在“偶数”步骤上进行:即从 (w, h, 4) 到 (w/2, h/2, 4) 到 (w/4, h/4, 4) 等。

我已经浏览了很长一段时间,但似乎每个人都指的是 imresize 的 scipy/PIL 版本。

我想尽量减少对 python 包的依赖数量,因此只有 numpy 的要求。

我只是想在我用 C++ 实现它之前先检查一下 SO。

4

1 回答 1

3

我认为 numpy 中没有任何特定的解决方案,但是您应该能够在不离开 python 的舒适性的情况下有效地实现它。如果我错了,请纠正我,但是当图像的大小可以被 2 整除时,双线性滤波器基本上与将原始图像的 4 个像素平均得到新图像的 1 个像素相同,对吧?好吧,如果您的图像大小是 2 的幂,那么下面的代码:

from __future__ import division
import numpy as np
from PIL import Image

def halve_image(image) :
    rows, cols, planes = image.shape
    image = image.astype('uint16')
    image = image.reshape(rows // 2, 2, cols // 2, 2, planes)
    image = image.sum(axis=3).sum(axis=1)
    return ((image + 2) >> 2).astype('uint8')

def mipmap(image) :
    img = image.copy()
    rows, cols, planes = image.shape
    mipmap = np.zeros((rows, cols * 3 // 2, planes), dtype='uint8')
    mipmap[:, :cols, :] = img
    row = 0
    while rows > 1:
        img = halve_image(img)
        rows = img.shape[0]
        mipmap[row:row + rows, cols:cols + img.shape[1], :] = img
        row += rows
    return mipmap

img = np.asarray(Image.open('lena.png'))
Image.fromarray(mipmap(img)).save('lena_mipmap.png')

产生这个输出:

在此处输入图像描述

使用 512x512 的原始图像,它在我的系统上运行:

In [3]: img.shape
Out[3]: (512, 512, 4)

In [4]: %timeit mipmap(img)
10 loops, best of 3: 154 ms per loop

如果出现奇数长度的边,这将不起作用,但取决于您希望如何处理这些情况下的下采样,您应该能够摆脱整行(或列)像素,重塑您的图像到(rows // 2, 2, cols // 2, 2, planes),所以这img[r, :, c, :, p]是一个 2x2 的值矩阵,要进行插值以获得新的像素值。

于 2013-01-28T08:31:16.440 回答