docstr: Find the center point of poly as key_points, then fit and gather.
docstr_tok: ["Find","the","center","point","of","poly","as","key_points",",","then","fit","and","gather","."]
code: def fit_and_gather_tcl_points_v3(
      self,
      min_area_quad,
      poly,
      max_h,
      max_w,
      fixed_point_num=64,
      img_id=0,
      reference_height=3,
  ):
      """
      Find the center point of poly as key_points, then fit and gather.
      """
      det_mask = np.zeros(
          (int(max_h / self.ds_ratio), int(max_w / self.ds_ratio))
      ).astype(np.float32)
  
      # score_big_map
      cv2.fillPoly(
          det_mask, np.round(poly / self.ds_ratio).astype(np.int32), 1.0
      )
      det_mask = cv2.resize(
          det_mask, dsize=None, fx=self.ds_ratio, fy=self.ds_ratio
      )
      det_mask = np.array(det_mask > 1e-3, dtype="float32")
  
      f_direction = self.f_direction
      skeleton_map = thin(det_mask.astype(np.uint8))
      instance_count, instance_label_map = cv2.connectedComponents(
          skeleton_map.astype(np.uint8), connectivity=8
      )
  
      ys, xs = np.where(instance_label_map == 1)
      pos_list = list(zip(ys, xs))
      if len(pos_list) < 3:
          return None
      pos_list_sorted = sort_and_expand_with_direction_v2(
          pos_list, f_direction, det_mask
      )
  
      pos_list_sorted = np.array(pos_list_sorted)
      length = len(pos_list_sorted) - 1
      insert_num = 0
      for index in range(length):
          stride_y = np.abs(
              pos_list_sorted[index + insert_num][0]
              - pos_list_sorted[index + 1 + insert_num][0]
          )
          stride_x = np.abs(
              pos_list_sorted[index + insert_num][1]
              - pos_list_sorted[index + 1 + insert_num][1]
          )
          max_points = int(max(stride_x, stride_y))
  
          stride = (
              pos_list_sorted[index + insert_num]
              - pos_list_sorted[index + 1 + insert_num]
          ) / (max_points)
          insert_num_temp = max_points - 1
  
          for i in range(int(insert_num_temp)):
              insert_value = (
                  pos_list_sorted[index + insert_num] - (i + 1) * stride
              )
              insert_index = index + i + 1 + insert_num
              pos_list_sorted = np.insert(
                  pos_list_sorted, insert_index, insert_value, axis=0
              )
          insert_num += insert_num_temp
  
      pos_info = (
          np.array(pos_list_sorted).reshape(-1, 2).astype(np.float32)
      )  # xy-> yx
  
      point_num = len(pos_info)
      if point_num > fixed_point_num:
          keep_ids = [
              int((point_num * 1.0 / fixed_point_num) * x)
              for x in range(fixed_point_num)
          ]
          pos_info = pos_info[keep_ids, :]
  
      keep = int(min(len(pos_info), fixed_point_num))
      reference_width = (
          np.abs(poly[0, 0, 0] - poly[-1, 1, 0])
          + np.abs(poly[0, 3, 0] - poly[-1, 2, 0])
      ) // 2
      if np.random.rand() < 1:
          dh = (np.random.rand(keep) - 0.5) * reference_height
          offset = np.random.rand() - 0.5
          dw = np.array([[0, offset * reference_width * 0.2]])
          random_float_h = np.array([1, 0]).reshape(
              [1, 2]
          ) * dh.reshape([keep, 1])
          random_float_w = dw.repeat(keep, axis=0)
          pos_info += random_float_h
          pos_info += random_float_w
          pos_info[:, 0] = np.clip(pos_info[:, 0], 0, max_h - 1)
          pos_info[:, 1] = np.clip(pos_info[:, 1], 0, max_w - 1)
  
      # padding to fixed length
      pos_l = np.zeros((self.tcl_len, 3), dtype=np.int32)
      pos_l[:, 0] = np.ones((self.tcl_len,)) * img_id
      pos_m = np.zeros((self.tcl_len, 1), dtype=np.float32)
      pos_l[:keep, 1:] = np.round(pos_info).astype(np.int32)
      pos_m[:keep] = 1.0
      return pos_l, pos_m
  
imports: import math
  import cv2
  import numpy
  from skimage.morphology._skeletonize import thin
  from ppocr.utils.e2e_utils.extract_textpoint_fast import sort_and_expand_with_direction_v2
label_desc: Use image node_id 8 for calling the PGProcessTrain obj's underlying member method code with example usage: obj.fit_and_gather_tcl_points_v3(min_area_quad, poly, max_h, max_w, fixed_point_num, img_id, reference_height) and returns: pos_l,  pos_m, None