为什么skimage.transform.rotate比PIL的Image.rotate慢得多?

6
我正在将一些基于PIL库的代码转换为NumPy,但我发现 skimage.transform.rotate 函数比PIL的 Image.rotate 函数慢得很多
大致对比,使用 skimage 在一个 ~1000x1000 像素图像上旋转需要 ~2.2 秒,而Image.rotate 只需要 ~0.1 秒:
import time
from PIL import Image
import numpy as np
from skimage.transform import rotate

im = Image.open("some_big_image.png").convert("L")
print "Image size: %s" %(im.size, )

s = time.time()
im.rotate(10, Image.BICUBIC, expand=True)
print "Image.rotate: %0.04f" %(time.time() - s, )

ima = np.array(im) / 255.0
s = time.time()
rotate(ima, 10, order=3) # order=3 --> bi-cubic filtering
print "skimage.transform.rotate: %0.04f" %(time.time() - s, )

输出结果为:

$ py rotate.py
Image size: (1275, 1650)
Image.rotate: 0.1154
skimage.transform.rotate: 2.2310

(这些数字在多次运行中基本保持一致; 我不认为这是没有运行足够的测试的结果)

那么! 这是怎么回事?有没有办法加速 skimage 的 rotate

版本信息:

  • PIL: 1.1.7
  • skimage: 0.14.1
  • numpy: 1.7.1
  • Python: 2.7.2

还值得注意的是:

  • 如果不使用BICUBIC滤波,则im.rotate操作仅需要大约0.01秒,而设置order=0以使用最近邻滤波,则skimage.rotate需要大约0.6秒。

你跑了多少次来比较时间? - usethedeathstar
我注意到在约100次运行中出现了这种情况。每次运行之间有大约10%的变化(正如您所预期的那样),但没有任何可以解释20倍时间差异的因素。 - David Wolever
2个回答

7
请从https://github.com/scikit-image/scikit-image安装最新版本。仅仅几天前,我修复了一个有关此速度放缓的错误(请参见https://github.com/scikit-image/scikit-image/commit/d5776656a8217e58cb28d5760439a54e96d15316)。
以下是当前开发版本的数据:
from PIL import Image
import numpy as np
from skimage.transform import rotate

a = np.zeros((1000, 1000), dtype=np.uint8)

im = Image.fromarray(a)

%timeit im.rotate(10, Image.BICUBIC, expand=True)

ima = a / 255.0
%timeit rotate(ima, 10, order=1)
%timeit rotate(ima, 10, order=3)


## -- Output --
10 loops, best of 3: 41.3 ms per loop
10 loops, best of 3: 43.6 ms per loop
10 loops, best of 3: 101 ms per loop

太棒了!谢谢!有趣的是,在我的电脑上,时间有些不同:PIL每个循环大约50毫秒,而sk-image大约160毫秒...但是,目前来说,这对于我的目的已经足够快了。 - David Wolever
可能与您使用的编译器有关。我正在使用LLVM版本5.0(clang-500.2.79)(基于LLVM 3.3svn)和-O3。 - user2970139
啊,是的,可能吧。我的主要版本比你低:“Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)” - David Wolever

1

我只阅读了Python代码,没有看Cython代码,但我的猜想是,由于skimage使用的是通用的变形代码,所以其代码路径比专门用于平面旋转且不做其他事情的代码要低效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接