Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV Python : rotate image without cropping sides

Imagine I have these images :

ttps://i.stack.imgur.com/jjRfe.png

I want the image from left to be rotated like the image of the middle, not the right one. How do I do this using Python and OpenCV. I looked at getRotationMatrix2D and warpAffine but the examples about it transform my image to the right one.

like image 698
Fosheus Badabu Avatar asked May 10 '17 12:05

Fosheus Badabu


People also ask

How do you rotate an image 90 degrees in Python?

The imutils. rotate() function is used to rotate an image by an angle in Python.


6 Answers

This is by far the best solution i have found for rotating images while avoiding cropping the image.

Rotate an image without cropping in OpenCV in C++

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

You can add checks to avoid some calculations when the angles are 90*n, but this function will work for any angle as is.

like image 73
en_lorithai Avatar answered Oct 02 '22 23:10

en_lorithai


If you only care about 90 degree rotations numpy instead. It's much easier and works on opencv input:

import numpy as np
rotated_image = np.rot90(im)
like image 43
Ryan Jay Avatar answered Oct 02 '22 22:10

Ryan Jay


As I don't know your code I still would guess that using the imutils.rotate_boundfunction will solve the problem. E.g.: rotate = imutils.rotate_bound(image, angle)

like image 34
mkorbi Avatar answered Oct 02 '22 21:10

mkorbi


This is the easiest way to rotate image frames by using cv2.rotate(frame,rotateCode = 1) and rescale or resizing by using cv2.CAP_PROP_FRAME_WIDTH and cv2.CAP_PROP_FRAME_HEIGHT of the frame.

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) 

You can enter rotateCode= 0 or 1 or 2. Depends on your rotation. It's gonna give you 0 or 90 or 180 or 270 angles

    # 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()

Hopefully, it with help you.

like image 38
sahaj patel Avatar answered Oct 02 '22 22:10

sahaj patel


While this question was asked for CV2, you can do this with python's native image library.

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

If you leave out expand=True in the rotate command you will get a result that looks like OP's right hand photo.

like image 34
deweydb Avatar answered Oct 02 '22 23:10

deweydb


Here is an alternative from ndimage.rotate from SciPy

Related documentation

from scipy.ndimage import rotate as rotate_image

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

enter image description here

rotated_img2 = rotate_image(img,-110)

enter image description here

rotated_img3 = rotate_image(img,-45)

enter image description here

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

enter image description here

like image 29
Jeru Luke Avatar answered Oct 02 '22 22:10

Jeru Luke