有没有比scipy.interpolate.rotate()更快的旋转大rgba图像的方法?

5 投票
1 回答
1135 浏览
提问于 2025-04-18 10:26

我正在开发一个应用程序,用来进行一些图像分析的任务。我需要对图像进行一些操作,比如旋转、缩放、改变中心点等等,这样才能获取图像的特定部分进行分析。我使用wxPython来做图形界面,所以显示的图像需要是wxImage类型(这样才能缩放并转换成wxBitmap)。不过,我的图像数据是一个二维的浮点数组。为了创建一个wxImage,数据必须是RGBA格式的。因此,现在我正在把图像转换成RGBA格式,并使用scipy.interpolate.rotate()进行旋转(缩放则是通过裁剪图像来实现),同时保存我想要的那部分信息。然后,在找到那部分后,我会用新的参数对原始的浮点数组数据进行同样的操作。

所以,问题是,旋转RGBA图像的速度非常慢(因为图像大约是2000x2000的大小),即使使用最近邻插值(NDN,模式=0)。而当我对浮点数组进行插值(用于分析)时,速度还算可以(只要我使用NDN或线性插值)。

我的问题是:

  1. 有没有更好的方法可以避免所有这些数据转换?
  2. 如果没有,那有没有更快的方法来旋转RGBA数据?(质量不是特别重要,因为我只是显示数据并寻找参数;我会用未处理的浮点数组进行分析)。

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

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)

为了了解哪个库在旋转和插值图像方面更有效,我们首先设计了一个简单的实验。我们对一个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是最慢的。

撰写回答