insecta / khandy /image /rotate.py
admin
sync
67a9b5d
import cv2
import khandy
import numpy as np
def get_2d_rotation_matrix(angle, cx=0, cy=0, scale=1,
degrees=True, dtype=np.float32):
"""
References:
`cv2.getRotationMatrix2D` in OpenCV
"""
if degrees:
angle = np.deg2rad(angle)
c = scale * np.cos(angle)
s = scale * np.sin(angle)
tx = cx - cx * c + cy * s
ty = cy - cx * s - cy * c
return np.array([[ c, -s, tx],
[ s, c, ty],
[ 0, 0, 1]], dtype=dtype)
def rotate_image(image, angle, scale=1.0, center=None,
degrees=True, border_value=0, auto_bound=False):
"""Rotate an image.
Args:
image : ndarray
Image to be rotated.
angle : float
Rotation angle in degrees, positive values mean clockwise rotation.
center : tuple
Center of the rotation in the source image, by default
it is the center of the image.
scale : float
Isotropic scale factor.
degrees : bool
border_value : int
Border value.
auto_bound : bool
Whether to adjust the image size to cover the whole rotated image.
Returns:
ndarray: The rotated image.
References:
mmcv.imrotate
"""
assert khandy.is_numpy_image(image)
image_height, image_width = image.shape[:2]
if auto_bound:
center = None
if center is None:
center = ((image_width - 1) * 0.5, (image_height - 1) * 0.5)
assert isinstance(center, tuple)
rotation_matrix = get_2d_rotation_matrix(angle, center[0], center[1], scale, degrees)
if auto_bound:
scale_cos = np.abs(rotation_matrix[0, 0])
scale_sin = np.abs(rotation_matrix[0, 1])
new_width = image_width * scale_cos + image_height * scale_sin
new_height = image_width * scale_sin + image_height * scale_cos
rotation_matrix[0, 2] += (new_width - image_width) * 0.5
rotation_matrix[1, 2] += (new_height - image_height) * 0.5
image_width = int(np.round(new_width))
image_height = int(np.round(new_height))
rotated = cv2.warpAffine(image, rotation_matrix[:2,:], (image_width, image_height),
borderValue=border_value)
return rotated