在Python中围绕指定原点旋转2D图像

时间:2022-05-04 18:15:23

I have a 2D image of 512x512 pixels that I would like to rotate with a certain angle at a certain origin (rotation center). All this time, I uses Scipy to rotate images with its rotate method. But, I got stumbled because the rotation always done around the center of the image. With 512x512 pixels the rotation center should be around point (x,y) 128,128. How can I rotate the image with a custom rotation center, let's say around (x,y) 20,128?

我有一个512x512像素的2D图像,我想在某个原点(旋转中心)以一定角度旋转。这一次,我使用Scipy用旋转方法旋转图像。但是,由于旋转始终围绕图像中心进行,因此我受到了挫折。对于512x512像素,旋转中心应该在点(x,y)128,128附近。如何使用自定义旋转中心旋转图像,让我们说围绕(x,y)20,128?

1 个解决方案

#1


14  

If OpenCV is not an option, you can do image rotation around a so called pivot point with NumPy (import numpy as np) and SciPy (from scipy import ndimage) the following way:

如果OpenCV不是一个选项,您可以通过以下方式使用NumPy(导入numpy为np)和SciPy(来自scipy import ndimage)围绕所谓的枢轴点进行图像旋转:

  1. Pad the image img such that the pivot point is in the image center and the image size is doubled:

    填充图像img,使得枢轴点位于图像中心,图像大小加倍:

    padX = [img.shape[1] - pivot[0], pivot[0]]
    padY = [img.shape[0] - pivot[1], pivot[1]]
    imgP = np.pad(img, [padY, padX], 'constant')
    

    (While the image shape is in row-column order, pivot is in X-Y or column-row order here. You might want to define it differently.)

    (虽然图像形状是按行列顺序,但此处的轴在X-Y或列行顺序中。您可能希望以不同方式定义它。)

  2. Rotate the image around its center (here the rotation angle is 45 degrees):

    围绕中心旋转图像(此处旋转角度为45度):

    imgR = ndimage.rotate(imgP, 45, reshape=False)
    

    Note that we disallow reshaping the image, since we'll crop the image ourselves.

    请注意,我们不允许重塑图像,因为我们会自己裁剪图像。

  3. Crop the image such that the pivot point is at its original position. Therefore, we simply reverse the padding from step 1:

    裁剪图像,使枢轴点位于其原始位置。因此,我们只需从第1步中反转填充:

    imgC = imgR[padY[0] : -padY[1], padX[0] : -padX[1]]
    

You can see the different steps in the following plot (original image, padded, rotated, cropped; 45 degrees around (100, 300)).

您可以在下图中看到不同的步骤(原始图像,填充,旋转,裁剪; 45度左右(100,300))。

在Python中围绕指定原点旋转2D图像

Wrapping it up in a handy function yields:

将它包装在一个方便的函数中会产生:

def rotateImage(img, angle, pivot):
    padX = [img.shape[1] - pivot[0], pivot[0]]
    padY = [img.shape[0] - pivot[1], pivot[1]]
    imgP = np.pad(img, [padY, padX], 'constant')
    imgR = ndimage.rotate(imgP, angle, reshape=False)
    return imgR[padY[0] : -padY[1], padX[0] : -padX[1]]

Update

更新

For colored images you'd have to avoid adding more channels while padding (zero padding in 3rd dimension):

对于彩色图像,您必须避免在填充时添加更多通道(第三维零填充):

imgP = np.pad(img, [padY, padX, [0, 0]], 'constant')

Don't forget to use a 0 for both "before" and "after" padding. Otherwise you get a ValueError.

不要忘记在“之前”和“之后”填充中使用0。否则你会得到一个ValueError。

#1


14  

If OpenCV is not an option, you can do image rotation around a so called pivot point with NumPy (import numpy as np) and SciPy (from scipy import ndimage) the following way:

如果OpenCV不是一个选项,您可以通过以下方式使用NumPy(导入numpy为np)和SciPy(来自scipy import ndimage)围绕所谓的枢轴点进行图像旋转:

  1. Pad the image img such that the pivot point is in the image center and the image size is doubled:

    填充图像img,使得枢轴点位于图像中心,图像大小加倍:

    padX = [img.shape[1] - pivot[0], pivot[0]]
    padY = [img.shape[0] - pivot[1], pivot[1]]
    imgP = np.pad(img, [padY, padX], 'constant')
    

    (While the image shape is in row-column order, pivot is in X-Y or column-row order here. You might want to define it differently.)

    (虽然图像形状是按行列顺序,但此处的轴在X-Y或列行顺序中。您可能希望以不同方式定义它。)

  2. Rotate the image around its center (here the rotation angle is 45 degrees):

    围绕中心旋转图像(此处旋转角度为45度):

    imgR = ndimage.rotate(imgP, 45, reshape=False)
    

    Note that we disallow reshaping the image, since we'll crop the image ourselves.

    请注意,我们不允许重塑图像,因为我们会自己裁剪图像。

  3. Crop the image such that the pivot point is at its original position. Therefore, we simply reverse the padding from step 1:

    裁剪图像,使枢轴点位于其原始位置。因此,我们只需从第1步中反转填充:

    imgC = imgR[padY[0] : -padY[1], padX[0] : -padX[1]]
    

You can see the different steps in the following plot (original image, padded, rotated, cropped; 45 degrees around (100, 300)).

您可以在下图中看到不同的步骤(原始图像,填充,旋转,裁剪; 45度左右(100,300))。

在Python中围绕指定原点旋转2D图像

Wrapping it up in a handy function yields:

将它包装在一个方便的函数中会产生:

def rotateImage(img, angle, pivot):
    padX = [img.shape[1] - pivot[0], pivot[0]]
    padY = [img.shape[0] - pivot[1], pivot[1]]
    imgP = np.pad(img, [padY, padX], 'constant')
    imgR = ndimage.rotate(imgP, angle, reshape=False)
    return imgR[padY[0] : -padY[1], padX[0] : -padX[1]]

Update

更新

For colored images you'd have to avoid adding more channels while padding (zero padding in 3rd dimension):

对于彩色图像,您必须避免在填充时添加更多通道(第三维零填充):

imgP = np.pad(img, [padY, padX, [0, 0]], 'constant')

Don't forget to use a 0 for both "before" and "after" padding. Otherwise you get a ValueError.

不要忘记在“之前”和“之后”填充中使用0。否则你会得到一个ValueError。