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

SFB*_*A26 5 python wxpython image image-processing scipy

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

因此,问题是,即使使用隔壁邻居 (NDN) 插值(模式 = 0),旋转 RGBA 图像也非常慢(因为图像约为 2000x2000)。当我插入浮点数组(用于分析)时,速度还不错(只要我使用 NDN 或线性)。

那么我的问题是:

  1. 有没有更好的方法来做到这一点而不需要所有的数据转换?
  2. 如果没有,那么有没有更快的方法来旋转 RGBA 数据?(质量并不是一个大问题,因为我只显示数据并查找参数;我使用未触及的浮点数组进行分析)。

任何帮助将不胜感激。谢谢。

sha*_*ani 3

根据我的实验,OpenCV 执行图像旋转速度最快。看一下链接。

\n

编辑:我还应该在这里包含答案:

\n

我将重点介绍三个最常用的 Python 图像编辑库,即 Pillow、OpenCV 和 Scipy。

\n

在下面的代码中,您可以了解如何导入这些库以及如何使用它们旋转图像。我为每个库定义了一个函数,以将其用于我们的实验

\n
import numpy as np\nimport PIL\nimport cv2\nimport matplotlib.pylab as plt\nfrom PIL import Image\nfrom scipy.ndimage import rotate\nfrom scipy.ndimage import interpolation\n\ndef rotate_PIL (image, angel, interpolation):\n    \'\'\'\n    input :\n    image           :  image                    : PIL image Object\n    angel           :  rotation angel           : int\n    interpolation   :  interpolation mode       : PIL.Image.interpolation_mode\n    \n                                                    Interpolation modes :\n                                                    PIL.Image.NEAREST (use nearest neighbour), PIL.Image.BILINEAR (linear interpolation in a 2\xc3\x972 environment), or PIL.Image.BICUBIC \n                                                    https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.rotate\n    returns : \n    rotated image \n    \n    \'\'\'\n\n    return image.rotate(angel,interpolation)\n    \n    \ndef rotate_CV(image, angel , interpolation):\n\n    \'\'\'\n        input :\n        image           :  image                    : ndarray\n        angel           :  rotation angel           : int\n        interpolation   :  interpolation mode       : cv2 Interpolation object\n        \n                                                        Interpolation modes :\n                                                        interpolation cv2.INTER_CUBIC (slow) & cv2.INTER_LINEAR\n                                                        https://theailearner.com/2018/11/15/image-interpolation-using-opencv-python/\n                                                        \n        returns : \n        rotated image   : ndarray\n        \n        \'\'\'\n\n\n\n    #in OpenCV we need to form the tranformation matrix and apply affine calculations\n    #\n    h,w = image.shape[:2]\n    cX,cY = (w//2,h//2)\n    M = cv2.getRotationMatrix2D((cX,cY),angel,1)\n    rotated = cv2.warpAffine(image,M , (w,h),flags=interpolation)\n    return rotated\n\n    \n\ndef rotate_scipy(image, angel , interpolation):\n    \'\'\'\n        input :\n        image           :  image                    : ndarray\n        angel           :  rotation angel           : int\n        interpolation   :  interpolation mode       : int\n        \n                                                        Interpolation modes :\n                                                        /sf/ask/4044415931/\n                                                        order=0 for nearest interpolation\n                                                        order=1 for linear interpolation\n        returns : \n        rotated image   : ndarray\n        \n        \'\'\'\n\n    return  scipy.ndimage.interpolation.rotate(image,angel,reshape=False,order=interpolation)\n
Run Code Online (Sandbox Code Playgroud)\n

为了了解哪个库在旋转和插值图像方面更有效,我们首先设计了一个简单的实验。我们使用所有三个库对函数 rand_8bit() 生成的 200 x 200 像素 8 位图像应用 20 度旋转。

\n
def rand_8bit(n):\n    im =np.random.rand(n,n)*255\n    im = im.astype(np.uint8)\n    im[n//2:n//2+n//2,n//2:n//4+n//2]= 0 # a self scaling rectangle \n    im[n//3:50+n//3,n//3:200+n//3]= 0 #  a constant rectangle \n    return im\n  \n#generate images of 200x200 pixels\nim = rand_8bit(200)\n#for PIL library we need to first convert the image array into a PIL image object \nimage_for_PIL=Image.fromarray(im)\n    \n\n%timeit rotate_PIL(image_for_PIL,20,PIL.Image.BILINEAR)\n%timeit rotate_CV(im,20,cv2.INTER_LINEAR)\n%timeit rotate_scipy(im,20,1)\n
Run Code Online (Sandbox Code Playgroud)\n

结果是:\n987 \xc2\xb5s \xc2\xb1 76 \xc2\xb5s 每个循环(平均 \xc2\xb1 标准偏差 7 次运行,每次 1000 个循环)\n414 \xc2\xb5s \xc2\xb1 79.8每个循环 \xc2\xb5s(平均 7 次运行的 \xc2\xb1 标准偏差,每次 1000 个循环)\n4.46 ms \xc2\xb1 每个循环 1.07 毫秒(平均 7 次运行的 \xc2\xb1 标准偏差,各 100 次循环)

\n

这意味着在图像旋转方面,OpenCV 是最高效的,而 Scipy 是最慢的。

\n