optional_solve.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # @Author : lightXu
  2. # @File : optional_solve.py
  3. # @Time : 2019/9/17 0017 下午 13:18
  4. import cv2
  5. import re
  6. from segment.sheet_resolve.tools.brain_api import get_ocr_text_and_coordinate
  7. from segment.sheet_resolve.analysis.sheet.choice_infer import find_digital
  8. def rgb2binary(im):
  9. gray_img = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
  10. _ret, thresh_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
  11. return thresh_img
  12. def find_contours(left, top, image, ex_x=30, ex_y=1):
  13. threshed = rgb2binary(image)
  14. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (ex_x, ex_y)) # 膨胀系数
  15. # morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)
  16. morphed = cv2.dilate(threshed, kernel, iterations=1)
  17. (major, minor, _) = cv2.__version__.split(".")
  18. contours = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  19. cnts = contours[0] if int(major) > 3 else contours[1]
  20. cnt = sorted(cnts, key=cv2.contourArea)
  21. boxes = []
  22. for ele in cnt:
  23. x, y, w, h = cv2.boundingRect(ele)
  24. x_mid = x + w//2
  25. y_mid = y + h//2
  26. xmax = x+w
  27. ymax = y+h
  28. boxes.append((x, y, xmax, ymax, x_mid,y_mid))
  29. return boxes
  30. def point_in_polygon(point, polygon):
  31. xmin, ymin, xmax, ymax = polygon[0], polygon[1], polygon[2], polygon[3]
  32. if xmin <= point[0] <= xmax and ymin <= point[1] <= ymax:
  33. return True
  34. else:
  35. return False
  36. def resolve_optional_choice(l_, t_, direction, image):
  37. ocr_res = get_ocr_text_and_coordinate(image)
  38. digital_list, chars_list, d_mean_height, d_mean_width = find_digital(ocr_res, 0, 0,)
  39. if not digital_list:
  40. numbers = [501, 502]
  41. h, w = image.shape
  42. optional_choice_dict = {'class_name': 'optional_choice',
  43. 'rows': 1, 'cols': 2,
  44. 'single_width': w,
  45. 'single_height': h,
  46. 'direction': direction,
  47. 'bounding_box': {'xmin': l_,
  48. 'ymin': t_,
  49. 'xmax': l_ + w,
  50. 'ymax': t_ + h},
  51. 'number': numbers}
  52. else:
  53. numbers = sorted([ele['digital'] for ele in digital_list])
  54. contours = find_contours(l_, t_, image, d_mean_width*2, d_mean_height)
  55. res_region = []
  56. for contour in contours:
  57. for num in digital_list:
  58. loc = num['loc']
  59. num_center = (loc[-2], loc[-1])
  60. if point_in_polygon(num_center, contour):
  61. if num_center[0] < contour[-2] - d_mean_width//3:
  62. # 数字在box的左侧
  63. region = (loc[2]+1, loc[1]-1, contour[2]-3, loc[3]+1)
  64. else:
  65. # 数字在box中间, 数字在box左侧
  66. region = (contour[0], loc[1] - 1, contour[2], loc[3] + 1)
  67. res_region.append(region)
  68. l, t, r, b = 9999, 9999, 0, 0
  69. sum_w, sum_h = 0, 0
  70. for region in res_region:
  71. l, t, r, b = min(l, region[0]), min(t, region[1]), max(r, region[2]), max(b, region[3])
  72. width, height = region[2] - region[0], region[3] - region[1]
  73. sum_w += width
  74. sum_h += height
  75. mean_w, mean_h = sum_w//len(numbers), sum_h//len(numbers)
  76. if direction == 180:
  77. rows, cols = 1, max(2, len(numbers))
  78. if len(numbers) < 2:
  79. numbers.append(501)
  80. else:
  81. rows, cols = max(2, len(numbers)), 1
  82. if len(numbers) < 2:
  83. numbers.append(501)
  84. optional_choice_dict = {'class_name': 'optional_choice',
  85. 'rows': rows, 'cols': cols,
  86. 'single_width': mean_w,
  87. 'single_height': mean_h,
  88. 'direction': direction,
  89. 'bounding_box': {'xmin': l_ + l,
  90. 'ymin': t_ + t,
  91. 'xmax': l_ + r,
  92. 'ymax': t_ + b},
  93. 'number': numbers}
  94. # print(optional_choice_dict)
  95. return optional_choice_dict