📜  使用Python旋转图像而不切掉边 – OpenCV

📅  最后修改于: 2022-05-13 01:55:50.151000             🧑  作者: Mango

使用Python旋转图像而不切掉边 – OpenCV

先决条件: Python中的图像处理(缩放、旋转、移动和边缘检测)

使用 OpenCV 旋转图像很容易,但有时简单的旋转任务会裁剪/剪切图像的侧面,这会导致半幅图像。现在,在本教程中,我们将探索一种无需裁剪/剪切图像边的安全旋转图像的解决方案,以便整个图像都包含在旋转中,并将传统旋转方法与修改后的旋转版本进行比较。

循序渐进的方法:

  • 为了在不切掉边的情况下旋转图像,我们将创建一个名为ModifedWay()的显式函数,它将图像本身和图像旋转的角度作为参数。
  • 在函数中,首先获取图像的高度和宽度。
  • 找到图像的中心。
  • 然后计算二维旋转矩阵
  • 从旋转矩阵中提取绝对sincos值。
  • 获取图像的新高度和宽度并更新旋转矩阵的值以确保没有裁剪。
  • 最后,使用wrapAffine()方法执行图像的实际旋转。

下面是该方法的实现:

Python3
def ModifiedWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreX, centreY), angle, 1.0)
 
    # Now will take out sin and cos values from rotationMatrix
    # Also used numpy absolute function to make positive value
    cosofRotationMatrix = np.abs(rotationMatrix[0][0])
    sinofRotationMatrix = np.abs(rotationMatrix[0][1])
 
    # Now will compute new height & width of
    # an image so that we can use it in
    # warpAffine function to prevent cropping of image sides
    newImageHeight = int((imgHeight * sinofRotationMatrix) +
                         (imgWidth * cosofRotationMatrix))
    newImageWidth = int((imgHeight * cosofRotationMatrix) +
                        (imgWidth * sinofRotationMatrix))
 
    # After computing the new height & width of an image
    # we also need to update the values of rotation matrix
    rotationMatrix[0][2] += (newImageWidth/2) - centreX
    rotationMatrix[1][2] += (newImageHeight/2) - centreY
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (newImageWidth, newImageHeight))
 
    return rotatingimage


Python3
# Importing Required Libraries
import cv2
import numpy as np
 
 
# The below function is for conventionally way of rotating
# an Image without preventing cutting off sides
def SimpleWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (imgWidth, imgHeight))
 
    return rotatingimage
 
 
# The Below function is a modified version of the
# conventional way to rotate an image without
# cropping/cutting sides.
def ModifiedWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now will take out sin and cos values from rotationMatrix
    # Also used numpy absolute function to make positive value
    cosofRotationMatrix = np.abs(rotationMatrix[0][0])
    sinofRotationMatrix = np.abs(rotationMatrix[0][1])
 
    # Now will compute new height & width of
    # an image so that we can use it in
    # warpAffine function to prevent cropping of image sides
    newImageHeight = int((imgHeight * sinofRotationMatrix) +
                         (imgWidth * cosofRotationMatrix))
    newImageWidth = int((imgHeight * cosofRotationMatrix) +
                        (imgWidth * sinofRotationMatrix))
 
    # After computing the new height & width of an image
    # we also need to update the values of rotation matrix
    rotationMatrix[0][2] += (newImageWidth/2) - centreX
    rotationMatrix[1][2] += (newImageHeight/2) - centreY
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (newImageWidth, newImageHeight))
 
    return rotatingimage
 
 
# Driver Code
 
# Loading an Image from Disk
DogImage = cv2.imread("doggy.png", 1)
 
 
# Performing 40 degree rotation
NormalRotation = SimpleWay(DogImage, 40)
ModifiedVersionRotation = ModifiedWay(DogImage, 40)
 
# Display image on Screen
cv2.imshow("Original Image", DogImage)
 
# Display rotated image on Screen
cv2.imshow("Normal Rotation", NormalRotation)
cv2.imshow("Modified Version Rotation", ModifiedVersionRotation)
 
 
# To hold the GUI screen and control until it is detected
# the input for closing it, Once it is closed
# control will be released
cv2.waitKey(0)
 
# To destroy and remove all created GUI windows from
#screen and memory
cv2.destroyAllWindows()


Python3
# Importing Required Libraries
import cv2
import numpy as np
 
 
# The Below function is a modified version of the
# conventional way to rotate an image without
# cropping/cutting sides.
def ModifiedWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now will take out sin and cos values from rotationMatrix
    # Also used numpy absolute function to make positive value
    cosofRotationMatrix = np.abs(rotationMatrix[0][0])
    sinofRotationMatrix = np.abs(rotationMatrix[0][1])
 
    # Now will compute new height & width of
    # an image so that we can use it in
    # warpAffine function to prevent cropping of image sides
    newImageHeight = int((imgHeight * sinofRotationMatrix) +
                         (imgWidth * cosofRotationMatrix))
    newImageWidth = int((imgHeight * cosofRotationMatrix) +
                        (imgWidth * sinofRotationMatrix))
 
    # After computing the new height & width of an image
    # we also need to update the values of rotation matrix
    rotationMatrix[0][2] += (newImageWidth/2) - centreX
    rotationMatrix[1][2] += (newImageHeight/2) - centreY
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (newImageWidth, newImageHeight))
 
    return rotatingimage
 
 
# Driver Code
# Loading an Image from Disk
Image = cv2.imread("gfg.png", 1)
 
 
# Performing 40 degree rotation
ModifiedVersionRotation = ModifiedWay(Image, 40)
 
# Display image on Screen
cv2.imshow("Original Image", Image)
 
# Display rotated image on Screen
cv2.imshow("Modified Version Rotation", ModifiedVersionRotation)
 
 
# To hold the GUI screen and control until it is detected
# the input for closing it, Once it is closed
# control will be released
cv2.waitKey(0)
 
# To destroy and remove all created GUI windows from
#screen and memory
cv2.destroyAllWindows()


下面是一些示例,它们描述了如何使用上述函数在不切掉边的情况下旋转图像:

示例 1:

下面是修改后的旋转版本的实现以及它与正常旋转版本的比较:

蟒蛇3

# Importing Required Libraries
import cv2
import numpy as np
 
 
# The below function is for conventionally way of rotating
# an Image without preventing cutting off sides
def SimpleWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (imgWidth, imgHeight))
 
    return rotatingimage
 
 
# The Below function is a modified version of the
# conventional way to rotate an image without
# cropping/cutting sides.
def ModifiedWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now will take out sin and cos values from rotationMatrix
    # Also used numpy absolute function to make positive value
    cosofRotationMatrix = np.abs(rotationMatrix[0][0])
    sinofRotationMatrix = np.abs(rotationMatrix[0][1])
 
    # Now will compute new height & width of
    # an image so that we can use it in
    # warpAffine function to prevent cropping of image sides
    newImageHeight = int((imgHeight * sinofRotationMatrix) +
                         (imgWidth * cosofRotationMatrix))
    newImageWidth = int((imgHeight * cosofRotationMatrix) +
                        (imgWidth * sinofRotationMatrix))
 
    # After computing the new height & width of an image
    # we also need to update the values of rotation matrix
    rotationMatrix[0][2] += (newImageWidth/2) - centreX
    rotationMatrix[1][2] += (newImageHeight/2) - centreY
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (newImageWidth, newImageHeight))
 
    return rotatingimage
 
 
# Driver Code
 
# Loading an Image from Disk
DogImage = cv2.imread("doggy.png", 1)
 
 
# Performing 40 degree rotation
NormalRotation = SimpleWay(DogImage, 40)
ModifiedVersionRotation = ModifiedWay(DogImage, 40)
 
# Display image on Screen
cv2.imshow("Original Image", DogImage)
 
# Display rotated image on Screen
cv2.imshow("Normal Rotation", NormalRotation)
cv2.imshow("Modified Version Rotation", ModifiedVersionRotation)
 
 
# To hold the GUI screen and control until it is detected
# the input for closing it, Once it is closed
# control will be released
cv2.waitKey(0)
 
# To destroy and remove all created GUI windows from
#screen and memory
cv2.destroyAllWindows()

输出:

原图

使用 SimpleWay()函数正常旋转

使用 ModifiedWay()函数旋转

示例 2:

这是另一个描述现代旋转方法的示例:

蟒蛇3

# Importing Required Libraries
import cv2
import numpy as np
 
 
# The Below function is a modified version of the
# conventional way to rotate an image without
# cropping/cutting sides.
def ModifiedWay(rotateImage, angle):
   
    # Taking image height and width
    imgHeight, imgWidth = rotateImage.shape[0], rotateImage.shape[1]
 
    # Computing the centre x,y coordinates
    # of an image
    centreY, centreX = imgHeight//2, imgWidth//2
 
    # Computing 2D rotation Matrix to rotate an image
    rotationMatrix = cv2.getRotationMatrix2D((centreY, centreX), angle, 1.0)
 
    # Now will take out sin and cos values from rotationMatrix
    # Also used numpy absolute function to make positive value
    cosofRotationMatrix = np.abs(rotationMatrix[0][0])
    sinofRotationMatrix = np.abs(rotationMatrix[0][1])
 
    # Now will compute new height & width of
    # an image so that we can use it in
    # warpAffine function to prevent cropping of image sides
    newImageHeight = int((imgHeight * sinofRotationMatrix) +
                         (imgWidth * cosofRotationMatrix))
    newImageWidth = int((imgHeight * cosofRotationMatrix) +
                        (imgWidth * sinofRotationMatrix))
 
    # After computing the new height & width of an image
    # we also need to update the values of rotation matrix
    rotationMatrix[0][2] += (newImageWidth/2) - centreX
    rotationMatrix[1][2] += (newImageHeight/2) - centreY
 
    # Now, we will perform actual image rotation
    rotatingimage = cv2.warpAffine(
        rotateImage, rotationMatrix, (newImageWidth, newImageHeight))
 
    return rotatingimage
 
 
# Driver Code
# Loading an Image from Disk
Image = cv2.imread("gfg.png", 1)
 
 
# Performing 40 degree rotation
ModifiedVersionRotation = ModifiedWay(Image, 40)
 
# Display image on Screen
cv2.imshow("Original Image", Image)
 
# Display rotated image on Screen
cv2.imshow("Modified Version Rotation", ModifiedVersionRotation)
 
 
# To hold the GUI screen and control until it is detected
# the input for closing it, Once it is closed
# control will be released
cv2.waitKey(0)
 
# To destroy and remove all created GUI windows from
#screen and memory
cv2.destroyAllWindows()

输出: