Rotate a 2D image around specified origin in Python

后端 未结 1 1702
再見小時候
再見小時候 2020-12-20 18:01

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

相关标签:
1条回答
  • 2020-12-20 18:58

    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:

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

      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.)

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

      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:

      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)).

    enter image description here

    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 讨论(0)
提交回复
热议问题