有比scipy.interpolate.rotate()更快的方法可以旋转大型RGBA图像吗?

5
我正在构建一个应用程序来执行一些图像分析任务。我需要能够进行一些图像操作(例如旋转、缩放、更改中心点等),以便获取特定部分的图像进行分析。我正在使用wxPython作为我的GUI,所以显示的图像需要是wxImage类型(以进行缩放,然后转换为wxBitmap)。但是,我的图像数据是一个二维浮点数组。为了创建wxImage,数据需要以RGBA格式存在。因此,现在,我正在将图像转换为RGBA,并使用scipy.interpolate.rotate()(通过裁剪图像进行缩放等)进行旋转,并保存想要的所有信息。然后,一旦找到该部分,我会在原始浮点数组数据上执行相同的操作,使用新发现的参数。

问题在于,旋转RGBA图像非常慢(因为图像大约为2000x2000),即使使用最近邻居(NDN)插值(mode = 0)。当我对浮点数组进行插值(用于分析)时,速度并不太慢(只要使用NDN或线性插值)。

我的问题是:

  1. 是否有更好的方法可以避免所有这些数据转换?
  2. 如果没有,那么是否有更快的方法可以旋转RGBA数据? (由于我只显示数据并查找参数,因此质量并不是一个巨大的问题;我对未触及的浮点数组用于分析)。

非常感谢任何帮助。谢谢。


你尝试过Pillow或者PIL(Python图像库)吗? - furas
@furas 是的,我已经尝试使用Pillow。问题在于来回转换太慢了,在每个操作和显示之间进行转换是不可行的。 - SFBA26
1个回答

3
根据我的实验,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)

为了了解哪个库在旋转和插值图像方面更有效,我们首先设计了一个简单的实验。我们在一个由我们的函数rand_8bit()生成的200 x 200像素8位图像上使用所有三个库进行20度旋转。
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是最慢的。


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