我认为 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 的值矩阵,要进行插值以获得新的像素值。