I needed to know what is the fastest way to rotate an Image in Python.
There is no such question asked or answered to my knowledge in Stack Overflow, so I decided to run an experiment and find out the answer. That is why I would like to share the result with you:
#we will compare which method is faster for rotating a 2D image
#there are four major libraries for image handling and manipulation
#PIL
#OpenCV
#SciPy
#skimage
import numpy as np
import PIL
import cv2
import matplotlib.pylab as plt
from PIL import Image
from scipy.ndimage import rotate
from scipy.ndimage import interpolation
import scipy
from skimage.transform import rotate
#get data :
PIL_image = Image.open('cat.jpg')
#image = cv2.imread('bambi.jpg') #read gray scale
array_image = np.array(PIL_image)
Define a function for each module:
def rotate_PIL (image, angel, interpolation):
#PIL.Image.NEAREST (use nearest neighbour), PIL.Image.BILINEAR (linear interpolation in a 2×2 environment), or PIL.Image.BICUBIC
return image.rotate(angel,interpolation)
def rotate_CV(image, angel , interpolation):
#in OpenCV we need to form the tranformation matrix and apply affine calculations
#interpolation cv2.INTER_CUBIC (slow) & cv2.INTER_LINEAR
h,w = image.shape[:2]
cX,cY = (w//2,h//2)
M = cv2.getRotationMatrix2D((cX,cY),angel,1)
rotated = cv2.warpAffine(image,M , (w,h),flags=interpolation)
return rotated
def rotate_scipy(image, angel , interpolation):
return scipy.ndimage.interpolation.rotate(image,angel,reshape=False,order=interpolation)
Use timeit to find out which is fastest , PIL , Open CV or Scipy:
%timeit rotate_PIL(PIL_image,20,PIL.Image.NEAREST)
%timeit rotate_CV(array_image,20,cv2.INTER_LINEAR)
%timeit rotate_scipy(array_image,20,0)
The result came out to be:
975 µs ± 203 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3.5 ms ± 634 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
36.4 ms ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
There is a twist though - this was for a jpeg file and PIL just crushed the other two libraries. However I am working mainly with large raw images in TIFF format, so I also decided to test TIFF files:
#test for TIFF image
#get data :
PIL_image = Image.open('TiffImage.tif')
#image = cv2.imread('bambi.jpg') #read gray scale
array_image = np.array(PIL_image)
%timeit rotate_PIL(PIL_image,20,PIL.Image.NEAREST)
%timeit rotate_CV(array_image,20,cv2.INTER_LINEAR)
%timeit rotate_scipy(array_image,20,0)
65.1 ms ± 9.35 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
38.6 ms ± 6.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
344 ms ± 43.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Which means OpenCV does a better job in TIFF file formats than our clear winner for JPEG files.
If anybody happens to know the reason, or if anyone has similar experiments, please share here. I think this will be a nice public document for comparison.
Also, please let me know if you think my experiment is not valid, or could be improved, for any reason.