OpenCV Python:不裁剪边的旋转图像

8yparm6h  于 2023-08-06  发布在  Python
关注(0)|答案(8)|浏览(118)

想象一下我有这些图像:


的数据
我想从左边的图像被旋转像中间的图像,而不是右边的。如何使用Python和OpenCV来实现这一点?我看了getRotationMatrix2DwarpAffine,但关于它的例子将我的图像转换为正确的图像。

ippsafx7

ippsafx71#

这是迄今为止我找到的旋转图像同时避免裁剪图像的最佳解决方案。
在C++中的OpenCV中旋转图像而不进行裁剪

import cv2

def rotate_image(mat, angle):
    """
    Rotates an image (angle in degrees) and expands image to avoid cropping
    """
    
    height, width = mat.shape[:2] # image shape has 3 dimensions
    image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape
    
    rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.)
    
    # rotation calculates the cos and sin, taking absolutes of those.
    abs_cos = abs(rotation_mat[0,0]) 
    abs_sin = abs(rotation_mat[0,1])
    
    # find the new width and height bounds
    bound_w = int(height * abs_sin + width * abs_cos)
    bound_h = int(height * abs_cos + width * abs_sin)
    
    # subtract old image center (bringing image back to origo) and adding the new image center coordinates
    rotation_mat[0, 2] += bound_w/2 - image_center[0]
    rotation_mat[1, 2] += bound_h/2 - image_center[1]
    
    # rotate image with the new bounds and translated rotation matrix
    rotated_mat = cv2.warpAffine(mat, rotation_mat, (bound_w, bound_h))
    return rotated_mat

字符串
当Angular 为90*n时,您可以添加检查以避免某些计算,但此函数将适用于任何Angular 。
利用numpy矢量化

def rotate_image(img, angle):
    size_reverse = np.array(img.shape[1::-1]) # swap x with y
    M = cv2.getRotationMatrix2D(tuple(size_reverse / 2.), angle, 1.)
    MM = np.absolute(M[:,:2])
    size_new = MM @ size_reverse
    M[:,-1] += (size_new - size_reverse) / 2.
    return cv2.warpAffine(img, M, tuple(size_new.astype(int)))

5t7ly7z5

5t7ly7z52#

如果你只关心90度的旋转,那么就用numpy代替。它更容易,并且适用于opencv输入:

import numpy as np
rotated_image = np.rot90(im)

字符串

dxxyhpgq

dxxyhpgq3#

由于我不知道你的代码,我仍然会猜测使用imutils.rotate_bound函数将解决这个问题。例如:rotate = imutils.rotate_bound(image, angle)

wswtfjt7

wswtfjt74#

这里是ndimage.rotate的替代品来自SciPy
Related documentation

from scipy.ndimage import rotate as rotate_image

#rotation angle in degree
rotated_img1 = rotate_image(img,90)

字符串


的数据

rotated_img2 = rotate_image(img,-110)


rotated_img3 = rotate_image(img,-45)


# angles extending beyond 360 are calculated appropriately:
rotated_img4 = rotate_image(img,390)


cgh8pdjw

cgh8pdjw5#

这是使用cv2.rotate(frame,rotateCode = 1)旋转图像帧以及使用帧的cv2.CAP_PROP_FRAME_WIDTH和cv2.CAP_PROP_FRAME_HEIGHT重新缩放或调整大小的最简单方法。

import numpy as np
import cv2

cam = cv2.VideoCapture(2)

while(True):
    # Capture frame-by-frame
    cam.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # You can change frame width by chaning number.

    cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # You can change frame height by chaning number.

    ret, frame = cam.read()

    new_frame=cv2.rotate(frame,rotateCode = 1)

字符串

您可以输入rotateCode= 0或1或2。这取决于你的轮换。它会给予你0度或90度或180度或270度的Angular

# Display the resulting frame
    cv2.imshow('frame',new_frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cam.release()
cv2.destroyAllWindows()


希望能帮到你。

dluptydi

dluptydi6#

虽然这个问题是针对CV2提出的,但您可以使用python的本机映像库来解决这个问题。

rotate_degrees = -90
img = Image.open(input_file_path)
img2 = img.rotate(rotate_degrees, expand=True)
img2.save(output_file_path)

字符串
如果你在rotate命令中省略了expand=True,你会得到一个看起来像OP右手边照片的结果。

rm5edbpk

rm5edbpk7#

您也可以使用填充,即在图像的两侧添加边框,然后旋转它以避免从原始图像裁剪。

def rotate_im(image, angle)
    image_height = image.shape[0]
    image_width = image.shape[1]
    diagonal_square = (image_width*image_width) + (
        image_height* image_height
    )
    #
    diagonal = round(sqrt(diagonal_square))
    padding_top = round((diagonal-image_height) / 2)
    padding_bottom = round((diagonal-image_height) / 2)
    padding_right = round((diagonal-image_width) / 2)
    padding_left = round((diagonal-image_width) / 2)
    padded_image = cv2.copyMakeBorder(image,
                                      top=padding_top,
                                      bottom=padding_bottom,
                                      left=padding_left,
                                      right=padding_right,
                                      borderType=cv2.BORDER_CONSTANT,
                                      value=0
            )
    padded_height = padded_image.shape[0]
    padded_width = padded_image.shape[1]
    transform_matrix = cv2.getRotationMatrix2D(
                (padded_height/2,
                 padded_width/2), # center
                angle, # angle
      1.0) # scale
    rotated_image = cv2.warpAffine(padded_image,
                                   transform_matrix,
                                   (diagonal, diagonal),
                                   flags=cv2.INTER_LANCZOS4)
    return rotated_image

字符串

6xfqseft

6xfqseft8#

它的简单没有任何warpaffine或任何计算的需要检查这个代码了

import numpy as np
from PIL import ImageGrab
import cv2

angle = -90
scale = 1.0

while True:
    img = ImageGrab.grab()
    img_np = np.array(img)
    frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
    new = cv2.rotate(frame,rotateCode = 0)# this is the line to rotate the image
    true = cv2.resize(new, (0,0), fx = 0.6, fy = 0.6) # with fxand fy u can control the size
    cv2.imshow('output', true)
    if cv2.waitKey(1) == 27:
        break

cv2.destroyAllWindows()

字符串

相关问题