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.
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)
As I don't know your code I still would guess that using the imutils.rotate_bound
function will solve the problem. Eg: rotate = imutils.rotate_bound(image, angle)
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)
# 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.
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.
You can also use padding as well, that is, add borders to the sides of the image, then rotate it to avoid cropping from the original image.
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
its simple no need of any warpaffine or any calculation check this code out
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()
Here is an alternative from ndimage.rotate
from SciPy
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.