facer.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. # The implementation is adopted from https://github.com/610265158/Peppa_Pig_Face_Engine
  2. import time
  3. import cv2
  4. import numpy as np
  5. from .config import config as cfg
  6. from .face_detector import FaceDetector
  7. from .face_landmark import FaceLandmark
  8. from .LK.lk import GroupTrack
  9. class FaceAna():
  10. '''
  11. by default the top3 facea sorted by area will be calculated for time reason
  12. '''
  13. def __init__(self, model_dir):
  14. self.face_detector = FaceDetector(model_dir)
  15. self.face_landmark = FaceLandmark(model_dir)
  16. self.trace = GroupTrack()
  17. self.track_box = None
  18. self.previous_image = None
  19. self.previous_box = None
  20. self.diff_thres = 5
  21. self.top_k = cfg.DETECT.topk
  22. self.iou_thres = cfg.TRACE.iou_thres
  23. self.alpha = cfg.TRACE.smooth_box
  24. def run(self, image):
  25. boxes = self.face_detector(image)
  26. if boxes.shape[0] > self.top_k:
  27. boxes = self.sort(boxes)
  28. boxes_return = np.array(boxes)
  29. landmarks, states = self.face_landmark(image, boxes)
  30. if 1:
  31. track = []
  32. for i in range(landmarks.shape[0]):
  33. track.append([
  34. np.min(landmarks[i][:, 0]),
  35. np.min(landmarks[i][:, 1]),
  36. np.max(landmarks[i][:, 0]),
  37. np.max(landmarks[i][:, 1])
  38. ])
  39. tmp_box = np.array(track)
  40. self.track_box = self.judge_boxs(boxes_return, tmp_box)
  41. self.track_box, landmarks = self.sort_res(self.track_box, landmarks)
  42. return self.track_box, landmarks, states
  43. def sort_res(self, bboxes, points):
  44. area = []
  45. for bbox in bboxes:
  46. bbox_width = bbox[2] - bbox[0]
  47. bbox_height = bbox[3] - bbox[1]
  48. area.append(bbox_height * bbox_width)
  49. area = np.array(area)
  50. picked = area.argsort()[::-1]
  51. sorted_bboxes = [bboxes[x] for x in picked]
  52. sorted_points = [points[x] for x in picked]
  53. return np.array(sorted_bboxes), np.array(sorted_points)
  54. def diff_frames(self, previous_frame, image):
  55. if previous_frame is None:
  56. return True
  57. else:
  58. _diff = cv2.absdiff(previous_frame, image)
  59. diff = np.sum(
  60. _diff) / previous_frame.shape[0] / previous_frame.shape[1] / 3.
  61. return diff > self.diff_thres
  62. def sort(self, bboxes):
  63. if self.top_k > 100:
  64. return bboxes
  65. area = []
  66. for bbox in bboxes:
  67. bbox_width = bbox[2] - bbox[0]
  68. bbox_height = bbox[3] - bbox[1]
  69. area.append(bbox_height * bbox_width)
  70. area = np.array(area)
  71. picked = area.argsort()[-self.top_k:][::-1]
  72. sorted_bboxes = [bboxes[x] for x in picked]
  73. return np.array(sorted_bboxes)
  74. def judge_boxs(self, previous_bboxs, now_bboxs):
  75. def iou(rec1, rec2):
  76. # computing area of each rectangles
  77. S_rec1 = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1])
  78. S_rec2 = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1])
  79. # computing the sum_area
  80. sum_area = S_rec1 + S_rec2
  81. # find the each edge of intersect rectangle
  82. x1 = max(rec1[0], rec2[0])
  83. y1 = max(rec1[1], rec2[1])
  84. x2 = min(rec1[2], rec2[2])
  85. y2 = min(rec1[3], rec2[3])
  86. # judge if there is an intersect
  87. intersect = max(0, x2 - x1) * max(0, y2 - y1)
  88. return intersect / (sum_area - intersect)
  89. if previous_bboxs is None:
  90. return now_bboxs
  91. result = []
  92. for i in range(now_bboxs.shape[0]):
  93. contain = False
  94. for j in range(previous_bboxs.shape[0]):
  95. if iou(now_bboxs[i], previous_bboxs[j]) > self.iou_thres:
  96. result.append(self.smooth(now_bboxs[i], previous_bboxs[j]))
  97. contain = True
  98. break
  99. if not contain:
  100. result.append(now_bboxs[i])
  101. return np.array(result)
  102. def smooth(self, now_box, previous_box):
  103. return self.do_moving_average(now_box[:4], previous_box[:4])
  104. def do_moving_average(self, p_now, p_previous):
  105. p = self.alpha * p_now + (1 - self.alpha) * p_previous
  106. return p
  107. def reset(self):
  108. '''
  109. reset the previous info used foe tracking,
  110. :return:
  111. '''
  112. self.track_box = None
  113. self.previous_image = None
  114. self.previous_box = None