有没有比scipy.interpolate.rotate()更快的旋转大rgba图像的方法?
我正在开发一个应用程序,用来进行一些图像分析的任务。我需要对图像进行一些操作,比如旋转、缩放、改变中心点等等,这样才能获取图像的特定部分进行分析。我使用wxPython来做图形界面,所以显示的图像需要是wxImage类型(这样才能缩放并转换成wxBitmap)。不过,我的图像数据是一个二维的浮点数组。为了创建一个wxImage,数据必须是RGBA格式的。因此,现在我正在把图像转换成RGBA格式,并使用scipy.interpolate.rotate()进行旋转(缩放则是通过裁剪图像来实现),同时保存我想要的那部分信息。然后,在找到那部分后,我会用新的参数对原始的浮点数组数据进行同样的操作。
所以,问题是,旋转RGBA图像的速度非常慢(因为图像大约是2000x2000的大小),即使使用最近邻插值(NDN,模式=0)。而当我对浮点数组进行插值(用于分析)时,速度还算可以(只要我使用NDN或线性插值)。
我的问题是:
- 有没有更好的方法可以避免所有这些数据转换?
- 如果没有,那有没有更快的方法来旋转RGBA数据?(质量不是特别重要,因为我只是显示数据并寻找参数;我会用未处理的浮点数组进行分析)。
任何帮助都将非常感谢。谢谢。
1 个回答
根据我在实验中的发现,OpenCV在图像旋转方面是最快的。可以去看看这个链接。
编辑:我也应该在这里把答案写出来:
我将重点介绍Python中最常用的三个图像处理库,分别是Pillow、OpenCV和Scipy。
在接下来的代码中,你可以学习如何导入这些库,以及如何使用它们来旋转图像。我为每个库定义了一个函数,以便在我们的实验中使用。
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
def rotate_PIL (image, angel, interpolation):
'''
input :
image : image : PIL image Object
angel : rotation angel : int
interpolation : interpolation mode : PIL.Image.interpolation_mode
Interpolation modes :
PIL.Image.NEAREST (use nearest neighbour), PIL.Image.BILINEAR (linear interpolation in a 2×2 environment), or PIL.Image.BICUBIC
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.rotate
returns :
rotated image
'''
return image.rotate(angel,interpolation)
def rotate_CV(image, angel , interpolation):
'''
input :
image : image : ndarray
angel : rotation angel : int
interpolation : interpolation mode : cv2 Interpolation object
Interpolation modes :
interpolation cv2.INTER_CUBIC (slow) & cv2.INTER_LINEAR
https://theailearner.com/2018/11/15/image-interpolation-using-opencv-python/
returns :
rotated image : ndarray
'''
#in OpenCV we need to form the tranformation matrix and apply affine calculations
#
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):
'''
input :
image : image : ndarray
angel : rotation angel : int
interpolation : interpolation mode : int
Interpolation modes :
https://stackoverflow.com/questions/57777370/set-interpolation-method-in-scipy-ndimage-map-coordinates-to-nearest-and-bilinea
order=0 for nearest interpolation
order=1 for linear interpolation
returns :
rotated image : ndarray
'''
return scipy.ndimage.interpolation.rotate(image,angel,reshape=False,order=interpolation)
为了了解哪个库在旋转和插值图像方面更有效,我们首先设计了一个简单的实验。我们对一个200 x 200像素的8位图像进行20度的旋转,这个图像是通过我们的函数rand_8bit()生成的。
def rand_8bit(n):
im =np.random.rand(n,n)*255
im = im.astype(np.uint8)
im[n//2:n//2+n//2,n//2:n//4+n//2]= 0 # a self scaling rectangle
im[n//3:50+n//3,n//3:200+n//3]= 0 # a constant rectangle
return im
#generate images of 200x200 pixels
im = rand_8bit(200)
#for PIL library we need to first convert the image array into a PIL image object
image_for_PIL=Image.fromarray(im)
%timeit rotate_PIL(image_for_PIL,20,PIL.Image.BILINEAR)
%timeit rotate_CV(im,20,cv2.INTER_LINEAR)
%timeit rotate_scipy(im,20,1)
结果是: 每次循环987微秒 ± 76微秒(7次运行的平均值 ± 标准差,每次1000次循环) 每次循环414微秒 ± 79.8微秒(7次运行的平均值 ± 标准差,每次1000次循环) 每次循环4.46毫秒 ± 1.07毫秒(7次运行的平均值 ± 标准差,每次100次循环)
这意味着在图像旋转方面,OpenCV是最有效的,而Scipy是最慢的。