craft_utils.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. # -*- coding: utf-8 -*-
  2. import numpy as np
  3. import cv2
  4. import math
  5. def getDetBoxes_core(textmap, linkmap, text_threshold, link_threshold, low_text):
  6. # prepare data
  7. linkmap = linkmap.copy()
  8. textmap = textmap.copy()
  9. img_h, img_w = textmap.shape
  10. """ labeling method """
  11. ret, text_score = cv2.threshold(textmap, low_text, 1, 0)
  12. ret, link_score = cv2.threshold(linkmap, link_threshold, 1, 0)
  13. text_score_comb = np.clip(text_score + link_score, 0, 1)
  14. nLabels, labels, stats, centroids = cv2.connectedComponentsWithStats(text_score_comb.astype(np.uint8), connectivity=4)
  15. det = []
  16. mapper = []
  17. for k in range(1,nLabels):
  18. # size filtering
  19. size = stats[k, cv2.CC_STAT_AREA]
  20. if size < 10: continue
  21. # thresholding
  22. if np.max(textmap[labels==k]) < text_threshold: continue
  23. # make segmentation map
  24. segmap = np.zeros(textmap.shape, dtype=np.uint8)
  25. segmap[labels==k] = 255
  26. segmap[np.logical_and(link_score==1, text_score==0)] = 0 # remove link area
  27. x, y = stats[k, cv2.CC_STAT_LEFT], stats[k, cv2.CC_STAT_TOP]
  28. w, h = stats[k, cv2.CC_STAT_WIDTH], stats[k, cv2.CC_STAT_HEIGHT]
  29. niter = int(math.sqrt(size * min(w, h) / (w * h)) * 2)
  30. sx, ex, sy, ey = x - niter, x + w + niter + 1, y - niter, y + h + niter + 1
  31. # boundary check
  32. if sx < 0 : sx = 0
  33. if sy < 0 : sy = 0
  34. if ex >= img_w: ex = img_w
  35. if ey >= img_h: ey = img_h
  36. kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(1 + niter, 1 + niter))
  37. segmap[sy:ey, sx:ex] = cv2.dilate(segmap[sy:ey, sx:ex], kernel)
  38. # make box
  39. np_contours = np.roll(np.array(np.where(segmap!=0)),1,axis=0).transpose().reshape(-1,2)
  40. rectangle = cv2.minAreaRect(np_contours)
  41. box = cv2.boxPoints(rectangle)
  42. # align diamond-shape
  43. w, h = np.linalg.norm(box[0] - box[1]), np.linalg.norm(box[1] - box[2])
  44. box_ratio = max(w, h) / (min(w, h) + 1e-5)
  45. if abs(1 - box_ratio) <= 0.1:
  46. l, r = min(np_contours[:,0]), max(np_contours[:,0])
  47. t, b = min(np_contours[:,1]), max(np_contours[:,1])
  48. box = np.array([[l, t], [r, t], [r, b], [l, b]], dtype=np.float32)
  49. # make clock-wise order
  50. startidx = box.sum(axis=1).argmin()
  51. box = np.roll(box, 4-startidx, 0)
  52. box = np.array(box)
  53. det.append(box)
  54. mapper.append(k)
  55. return det, labels, mapper
  56. def getDetBoxes(textmap, linkmap, text_threshold, link_threshold, low_text):
  57. boxes, labels, mapper = getDetBoxes_core(textmap, linkmap, text_threshold, link_threshold, low_text)
  58. return boxes
  59. def adjustResultCoordinates(polys, ratio_w, ratio_h, ratio_net = 2):
  60. if len(polys) > 0:
  61. polys = np.array(polys)
  62. for k in range(len(polys)):
  63. if polys[k] is not None:
  64. polys[k] *= (ratio_w * ratio_net, ratio_h * ratio_net)
  65. return polys