更新的答案
自从我写下这个答案以来,John Cupitt(pyvips
的作者)已经提出了一些改进和修正,还有更公平的代码和时间,并且很友好地在这里分享了他们。请查看他改进的版本,与我的代码并列或者甚至更优先。
原始答案
JPEG库有一个"加载时缩小"的功能,可以避免大量的I/O和解压缩。您可以使用PIL/Pillow的Image.draft()
函数来利用这一功能,所以不必像这样读取完整的4032x3024像素:
from PIL import Image
im = Image.open('image.jpg')
px = im.load()
在我的Mac上,这需要297毫秒,你可以执行以下操作并读取1008x756像素,即宽度的1/4和高度的1/4。
im = Image.open('image.jpg')
im.draft('RGB',(1008,756))
px = im.load()
只需要75毫秒,即快了4倍。
为了好玩,我尝试了以下各种技术的比较:
import numpy as np
import pyvips
import cv2
from PIL import Image
def usingPIL(f):
im = Image.open(f)
return np.asarray(im)
def usingOpenCV(f):
arr = cv2.imread(f,cv2.IMREAD_UNCHANGED)
return arr
def usingVIPS(f):
image = pyvips.Image.new_from_file(f, access="sequential")
return imgnp.numpy()
def usingPILandShrink(f):
im = Image.open(f)
im.draft('RGB',(1008,756))
return np.asarray(im)
def usingVIPSandShrink(f):
image = pyvips.Image.new_from_file(f, access="sequential", shrink=4)
return imgnp.numpy()
然后将其加载到
ipython
中,并进行了如下测试:
315 ms ± 8.76 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
102 ms ± 1.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
69.1 ms ± 31.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
77.2 ms ± 994 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
42.9 ms ± 332 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
看起来
pyVIPS在这里是明显的赢家!
关键词:Python,PIL,Pillow,图像,图像处理,JPEG,加载时缩小,草稿模式,读取性能,加速。