Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is skimage.transform.rotate significantly slower than PIL's Image.rotate?

I'm in the process of converting some PIL-based code over to NumPy, but I've found that the skimage.transform.rotate function is significantly slower than PIL's Image.rotate.

As a rough comparison, using skimage's rotate on a ~1000x1000 pixel image takes ~2.2 seconds, while Image.rotate takes ~0.1 seconds:

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, )

And the output:

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

(these numbers are more or less consistent across multiple runs; I don't believe that this is an artifact of not running enough tests)

So! What's up with that? Is there any way to speed up skimage's rotate?

Version info:

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

It may also be worth noting:

  • If BICUBIC filtering isn't used, the im.rotate operation only takes ~0.01 seconds, while setting order=0 to use nearest-neighbour filtering, skimage.rotate takes ~0.6 seconds.
like image 727
David Wolever Avatar asked Nov 06 '13 00:11

David Wolever


People also ask

What is skimage transform?

skimage.transform. ifrt2 (a)[source] Compute the 2-dimensional inverse finite radon transform (iFRT) for an (n+1) x n integer array. Parameters aarray_like. A 2-D (n+1) row x n column integer array.

How do you rotate an image in Python?

rotate() function is used to rotate an image by an angle in Python.


2 Answers

Install the latest version from https://github.com/scikit-image/scikit-image. Just a few days ago I fixed a bug (see https://github.com/scikit-image/scikit-image/commit/d5776656a8217e58cb28d5760439a54e96d15316) related to this slow down.

My numbers are as follows with the current dev version:

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
like image 110
user2970139 Avatar answered Sep 20 '22 23:09

user2970139


Having only read the Python code and not the Cython code for warp(), guess would be that since skimage is using generic warping code, its code paths are less efficient than something written specifically to do in-plane rotation and nothing else.

like image 44
dwf Avatar answered Sep 21 '22 23:09

dwf