rotate.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import cv2
  2. import khandy
  3. import numpy as np
  4. def get_2d_rotation_matrix(angle, cx=0, cy=0, scale=1,
  5. degrees=True, dtype=np.float32):
  6. """
  7. References:
  8. `cv2.getRotationMatrix2D` in OpenCV
  9. """
  10. if degrees:
  11. angle = np.deg2rad(angle)
  12. c = scale * np.cos(angle)
  13. s = scale * np.sin(angle)
  14. tx = cx - cx * c + cy * s
  15. ty = cy - cx * s - cy * c
  16. return np.array([[ c, -s, tx],
  17. [ s, c, ty],
  18. [ 0, 0, 1]], dtype=dtype)
  19. def rotate_image(image, angle, scale=1.0, center=None,
  20. degrees=True, border_value=0, auto_bound=False):
  21. """Rotate an image.
  22. Args:
  23. image : ndarray
  24. Image to be rotated.
  25. angle : float
  26. Rotation angle in degrees, positive values mean clockwise rotation.
  27. center : tuple
  28. Center of the rotation in the source image, by default
  29. it is the center of the image.
  30. scale : float
  31. Isotropic scale factor.
  32. degrees : bool
  33. border_value : int
  34. Border value.
  35. auto_bound : bool
  36. Whether to adjust the image size to cover the whole rotated image.
  37. Returns:
  38. ndarray: The rotated image.
  39. References:
  40. mmcv.imrotate
  41. """
  42. assert khandy.is_numpy_image(image)
  43. image_height, image_width = image.shape[:2]
  44. if auto_bound:
  45. center = None
  46. if center is None:
  47. center = ((image_width - 1) * 0.5, (image_height - 1) * 0.5)
  48. assert isinstance(center, tuple)
  49. rotation_matrix = get_2d_rotation_matrix(angle, center[0], center[1], scale, degrees)
  50. if auto_bound:
  51. scale_cos = np.abs(rotation_matrix[0, 0])
  52. scale_sin = np.abs(rotation_matrix[0, 1])
  53. new_width = image_width * scale_cos + image_height * scale_sin
  54. new_height = image_width * scale_sin + image_height * scale_cos
  55. rotation_matrix[0, 2] += (new_width - image_width) * 0.5
  56. rotation_matrix[1, 2] += (new_height - image_height) * 0.5
  57. image_width = int(np.round(new_width))
  58. image_height = int(np.round(new_height))
  59. rotated = cv2.warpAffine(image, rotation_matrix[:2,:], (image_width, image_height),
  60. borderValue=border_value)
  61. return rotated