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)围绕所谓的枢轴点进行图像旋转:
-
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或列行顺序中。您可能希望以不同方式定义它。)
-
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.
请注意,我们不允许重塑图像,因为我们会自己裁剪图像。
-
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))。
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)围绕所谓的枢轴点进行图像旋转:
-
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或列行顺序中。您可能希望以不同方式定义它。)
-
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.
请注意,我们不允许重塑图像,因为我们会自己裁剪图像。
-
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))。
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。