utility.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import cv2
  2. import numpy as np
  3. from os import path, listdir
  4. __all__ = [
  5. "sorted_boxes", "get_rotate_crop_image", "get_min_area_rect_crop",
  6. "get_image_file_list", "check_and_read"
  7. ]
  8. def sorted_boxes(dt_boxes):
  9. num_boxes = dt_boxes.shape[0]
  10. _sorted_boxes = sorted(dt_boxes, key=lambda x: (x[0][1], x[0][0]))
  11. _boxes = list(_sorted_boxes)
  12. for i in range(num_boxes - 1):
  13. for j in range(i, -1, -1):
  14. if abs(_boxes[j + 1][0][1] - _boxes[j][0][1]) < 10 and (_boxes[j + 1][0][0] < _boxes[j][0][0]):
  15. tmp = _boxes[j]
  16. _boxes[j] = _boxes[j + 1] # noqa
  17. _boxes[j + 1] = tmp
  18. else:
  19. break
  20. return _boxes
  21. def get_rotate_crop_image(img, points):
  22. """
  23. img_height, img_width = img.shape[0:2]
  24. left = int(np.min(points[:, 0]))
  25. right = int(np.max(points[:, 0]))
  26. top = int(np.min(points[:, 1]))
  27. bottom = int(np.max(points[:, 1]))
  28. img_crop = img[top:bottom, left:right, :].copy()
  29. points[:, 0] = points[:, 0] - left
  30. points[:, 1] = points[:, 1] - top
  31. """
  32. assert len(points) == 4, "shape of points must be 4*2"
  33. img_crop_width = int(max(np.linalg.norm(points[0] - points[1]), np.linalg.norm(points[2] - points[3])))
  34. img_crop_height = int(max(np.linalg.norm(points[0] - points[3]), np.linalg.norm(points[1] - points[2])))
  35. pts_std = np.float32([[0, 0], [img_crop_width, 0], [img_crop_width, img_crop_height], [0, img_crop_height]])
  36. M = cv2.getPerspectiveTransform(points, pts_std) # noqa
  37. dst_img = cv2.warpPerspective( # noqa
  38. img, M, (img_crop_width, img_crop_height),
  39. borderMode=cv2.BORDER_REPLICATE, flags=cv2.INTER_CUBIC # noqa
  40. )
  41. dst_img_height, dst_img_width = dst_img.shape[0:2]
  42. if dst_img_height * 1.0 / dst_img_width >= 1.5:
  43. dst_img = np.rot90(dst_img)
  44. return dst_img
  45. def get_min_area_rect_crop(img, points):
  46. bounding_box = cv2.minAreaRect(np.array(points).astype(np.int32)) # noqa
  47. points = sorted(list(cv2.boxPoints(bounding_box)), key=lambda x: x[0]) # noqa
  48. if points[1][1] > points[0][1]:
  49. index_a = 0
  50. index_d = 1
  51. else:
  52. index_a = 1
  53. index_d = 0
  54. if points[3][1] > points[2][1]:
  55. index_b = 2
  56. index_c = 3
  57. else:
  58. index_b = 3
  59. index_c = 2
  60. box = [points[index_a], points[index_b], points[index_c], points[index_d]]
  61. crop_img = get_rotate_crop_image(img, np.array(box))
  62. return crop_img
  63. def _check_image_file(file_path):
  64. img_end = ("jpg", "bmp", "png", "jpeg", "rgb", "tif", "tiff", "gif")
  65. return any([file_path.lower().endswith(e) for e in img_end])
  66. def get_image_file_list(img_file):
  67. images = []
  68. if img_file is None or not path.exists(img_file):
  69. raise Exception(f"not found any img file in {img_file}")
  70. if path.isfile(img_file) and _check_image_file(img_file):
  71. images.append(img_file)
  72. elif path.isdir(img_file):
  73. for single_file in listdir(img_file):
  74. file_path = path.join(img_file, single_file)
  75. if path.isfile(file_path) and _check_image_file(file_path):
  76. images.append(file_path)
  77. if len(images) == 0:
  78. raise Exception(f"not found any img file in {img_file}")
  79. images = sorted(images)
  80. return images
  81. def check_and_read(img_path):
  82. if path.basename(img_path)[-3:].lower() == "gif":
  83. gif = cv2.VideoCapture(img_path) # noqa
  84. ret, frame = gif.read()
  85. if not ret:
  86. print(f"Cannot read {img_path}. This gif image maybe corrupted.")
  87. return None, False
  88. if len(frame.shape) == 2 or frame.shape[-1] == 1:
  89. frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB) # noqa
  90. img = frame[:, :, ::-1]
  91. return img, True
  92. return None, False