text: import sys
  import os
  import cv2
  import numpy as np
  sys.path.append(os.path.abspath("./../graph/"))
  from graph.visualize_pose_matching import pose_matching, graph_pair_to_data
  from utils_custom import convert_coco_poseTrack
  
  
  def get_track_id_SGCN(bbox_cur_frame, bbox_list_prev_frame, keypoints_cur_frame, keypoints_list_prev_frame, pose_matching_threshold=0.5):
      assert(len(bbox_list_prev_frame) == len(keypoints_list_prev_frame))
  
      min_index = None
      min_matching_score = sys.maxsize
      # if track_id is still not assigned, the person is really missing or track is really lost
      track_id = -1
  
  
      # 循环匹配
      for det_index, bbox_det_dict in enumerate(bbox_list_prev_frame):
          bbox_prev_frame = bbox_det_dict["bbox"]
  
          # check the pose matching score
          keypoints_dict = keypoints_list_prev_frame[det_index]
          keypoints_prev_frame = keypoints_dict["keypoints"]
          pose_matching_score = get_pose_matching_score(keypoints_cur_frame, keypoints_prev_frame, bbox_cur_frame, bbox_prev_frame)
  
          if pose_matching_score <= pose_matching_threshold and pose_matching_score <= min_matching_score:
              # match the target based on the pose matching score
              min_matching_score = pose_matching_score
              min_index = det_index
  
      if min_index is None:
          return -1, None
      else:
          track_id = bbox_list_prev_frame[min_index]["track_id"]
          return track_id, min_index
  
  
  
  def get_track_id_SpatialConsistency(bbox_cur_frame, bbox_list_prev_frame):
      thresh = 0.3
      max_iou_score = 0
      max_index = -1
  
      for bbox_index, bbox_det_dict in enumerate(bbox_list_prev_frame):
          bbox_prev_frame = bbox_det_dict["bbox"]
  
          boxA = xywh_to_x1y1x2y2(bbox_cur_frame)
          boxB = xywh_to_x1y1x2y2(bbox_prev_frame)
          iou_score = iou(boxA, boxB)
          if iou_score > max_iou_score:
              max_iou_score = iou_score
              max_index = bbox_index
  
      if max_iou_score > thresh:
          track_id = bbox_list_prev_frame[max_index]["track_id"]
          return track_id, max_index
      else:
          return -1, None #未匹配成功
  
  
  def get_pose_matching_score(keypoints_A, keypoints_B, bbox_A, bbox_B):
      if keypoints_A == [] or keypoints_B == []:
          print("graph not correctly generated!")
          return sys.maxsize
  
      if bbox_invalid(bbox_A) or bbox_invalid(bbox_B):
          print("graph not correctly generated!")
          return sys.maxsize
  
      graph_A, flag_pass_check = keypoints_to_graph(keypoints_A, bbox_A)
      if flag_pass_check is False:
          print("graph not correctly generated!")
          return sys.maxsize
  
      graph_B, flag_pass_check = keypoints_to_graph(keypoints_B, bbox_B)
      if flag_pass_check is False:
          print("graph not correctly generated!")
          return sys.maxsize
  
      sample_graph_pair = (graph_A, graph_B)
      data_A, data_B = graph_pair_to_data(sample_graph_pair)
  
      flag_match, dist = pose_matching(data_A, data_B)
      return dist
  
  
  
  
  def get_iou_score(bbox_gt, bbox_det):
      boxA = xywh_to_x1y1x2y2(bbox_gt)
      boxB = xywh_to_x1y1x2y2(bbox_det)
  
      iou_score = iou(boxA, boxB)
      #print("iou_score: ", iou_score)
      return iou_score
  
  
  def is_target_lost(keypoints, method="max_average"):
      num_keypoints = int(len(keypoints) / 3.0)
      if method == "average":
          # pure average
          score = 0
          for i in range(num_keypoints):
              score += keypoints[3*i + 2]
          score /= num_keypoints*1.0
          print("target_score: {}".format(score))
      elif method == "max_average":
          score_list = keypoints[2::3]
          score_list_sorted = sorted(score_list)
          top_N = 4
          assert(top_N < num_keypoints)
          top_scores = [score_list_sorted[-i] for i in range(1, top_N+1)]
          score = sum(top_scores)/top_N
      #  print('SCORES ', score)
      if score < 0.6:
          return True
      else:
          return False
  
  
  def iou(boxA, boxB):
      # box: (x1, y1, x2, y2)
      # determine the (x, y)-coordinates of the intersection rectangle
      xA = max(boxA[0], boxB[0])
      yA = max(boxA[1], boxB[1])
      xB = min(boxA[2], boxB[2])
      yB = min(boxA[3], boxB[3])
  
      # compute the area of intersection rectangle
      interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
  
      # compute the area of both the prediction and ground-truth
      # rectangles
      boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
      boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)
  
      # compute the intersection over union by taking the intersection
      # area and dividing it by the sum of prediction + ground-truth
      # areas - the interesection area
      iou = interArea / float(boxAArea + boxBArea - interArea)
  
      # return the intersection over union value
      return iou
  
  
  def get_bbox_from_keypoints(keypoints_python_data, enlarge_scale=0.2):
      if keypoints_python_data == [] or keypoints_python_data == 45*[0]:
          return [0, 0, 2, 2]
  
      num_keypoints = len(keypoints_python_data)
      x_list = []
      y_list = []
  
      for keypoint_id in range(int(num_keypoints / 3)):
          #  if keypoint_id == 14:
              #  print('discard top-head ', keypoint_id)
              #  continue
  
          x = keypoints_python_data[3 * keypoint_id]
          y = keypoints_python_data[3 * keypoint_id + 1]
          vis = keypoints_python_data[3 * keypoint_id + 2]
          if vis != 0 and vis!= 3:
              x_list.append(x)
              y_list.append(y)
      min_x = min(x_list)
      min_y = min(y_list)
      max_x = max(x_list)
      max_y = max(y_list)
  
      if not x_list or not y_list:
          return [0, 0, 2, 2]
  
      #  min_y = min_y - 0.05 * (max_y - min_y)
      scale = enlarge_scale # enlarge bbox by 20% with same center position
      bbox = enlarge_bbox([min_x, min_y, max_x, max_y], scale*1)
      bbox_in_xywh = x1y1x2y2_to_xywh(bbox)
      return bbox_in_xywh
  
  
  def enlarge_bbox(bbox, scale):
      assert(scale > 0)
      min_x, min_y, max_x, max_y = bbox
      margin_x = int(0.5 * scale * (max_x - min_x))
      margin_y = int(0.5 * scale * (max_y - min_y))
      if margin_x < 0: margin_x = 2
      if margin_y < 0: margin_y = 2
  
      min_x -= margin_x
      max_x += margin_x
      min_y -= margin_y
      max_y += margin_y
  
      width = max_x - min_x
      height = max_y - min_y
      if max_y < 0 or max_x < 0 or width <= 0 or height <= 0 or width > 2000 or height > 2000:
          min_x=0
          max_x=2
          min_y=0
          max_y=2
  
      bbox_enlarged = [min_x, min_y, max_x, max_y]
      return bbox_enlarged
  
  def inference_keypoints_custom(pose_model, test_data, raw_img, get_keypoints_from_bbox):
      image_id = test_data['img_id']
      category_id = 1
      bbox = test_data['bbox']
      coco_kps = get_keypoints_from_bbox(pose_model, raw_img, bbox)
      keypoints = convert_coco_poseTrack(coco_kps)[0]
      keypoints[..., 2] = keypoints[..., 2] + 0.5
      score = np.mean(coco_kps[0][...,2], 0) + 0.5
      keypoints = keypoints.reshape(-1).tolist()
      keypoints = [round(i, 3) for i in keypoints]
  
      result = dict(image_id=image_id, category_id=category_id, bbox=bbox, score=float(round(score, 4)) , keypoints=keypoints)
      results = []
      results.append(result)
      return results
  
  
  
  def is_keyframe(img_id, interval=10):
      if img_id % interval == 0:
          return True
      else:
          return False
  
  
  
  def x1y1x2y2_to_xywh(det):
      x1, y1, x2, y2 = det
      w, h = int(x2) - int(x1), int(y2) - int(y1)
      return [x1, y1, w, h]
  
  
  def xywh_to_x1y1x2y2(det):
      x1, y1, w, h = det
      x2, y2 = x1 + w, y1 + h
      return [x1, y1, x2, y2]
  
  
  def bbox_invalid(bbox):
      if bbox == [0, 0, 2, 2]:
          return True
      if bbox[2] <= 0 or bbox[3] <= 0 or bbox[2] > 2000 or bbox[3] > 2000:
          return True
      return False
  
  def keypoints_to_graph(keypoints, bbox):
      num_elements = len(keypoints)
      num_keypoints = num_elements/3
      assert(num_keypoints == 15)
  
      x0, y0, w, h = bbox
      flag_pass_check = True
  
      graph = 15*[(0, 0)]
      for id in range(15):
          x = keypoints[3*id] - x0
          y = keypoints[3*id+1] - y0
          score = keypoints[3*id+2]
  
          graph[id] = (int(x), int(y))
      return graph, flag_pass_check
  