| import numpy as np |
| from collections import deque |
| import numpy as np |
| from collections import deque |
| import math |
|
|
| def get_bbox_area(bbox): |
| x1, y1, x2, y2 = bbox |
| return (x2 - x1) * (y2 - y1) |
|
|
|
|
| def check_consistant(boxA, boxB, scoreA_lst, scoreB_lst, beta, all_threshold): |
| """ |
| 计算两个锚框之间的 IoU(交并比)以及分数的变化比例,来判断连续性 |
| """ |
| |
| scoreA = scoreA_lst[0] |
| scoreB = scoreB_lst[0] |
| iou = get_IoU(boxA, boxB) |
|
|
| reduction_ratio = (scoreA - scoreB) / (scoreA + scoreB) if scoreA > scoreB else 0 |
|
|
| return iou - reduction_ratio * beta > all_threshold |
|
|
|
|
| def get_IoU(boxA, boxB): |
| """ |
| 计算两个锚框之间的 IoU(交并比)以及分数的变化比例,来判断连续性 |
| """ |
| |
| x1_int = max(boxA[0], boxB[0]) |
| y1_int = max(boxA[1], boxB[1]) |
| x2_int = min(boxA[2], boxB[2]) |
| y2_int = min(boxA[3], boxB[3]) |
|
|
| |
| inter_width = max(0, x2_int - x1_int) |
| inter_height = max(0, y2_int - y1_int) |
| inter_area = inter_width * inter_height |
|
|
| |
| areaA = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1]) |
| areaB = (boxB[2] - boxB[0]) * (boxB[3] - boxB[1]) |
|
|
| |
| union_area = areaA + areaB - inter_area |
|
|
| |
| iou = inter_area / union_area if union_area > 0 else 0.0 |
|
|
| return iou |
|
|
| def check_bbox_single_for_video(bbox, reference_width, reference_height, min_bbox_width=1/6, min_bbox_area=1/30): |
| """ |
| 每一帧都要检查,判断 bbox 是否符合视频格式下的要求 |
| """ |
| x1, y1, x2, y2 = bbox |
| bbox_width = x2 - x1 |
| bbox_height = y2 - y1 |
|
|
| |
| if bbox_width <= 0 or bbox_height <= 0: |
| return False |
|
|
| bbox_area = bbox_width * bbox_height |
|
|
| if bbox_area < min_bbox_area: |
| |
| return False |
|
|
| |
| if reference_width > reference_height: |
| if bbox_width < min_bbox_width: |
| |
| return False |
| return True |
|
|
|
|
|
|
| |
|
|
| def part5_valid(valid_joints): |
| """ |
| 判断身体五块是不是都有点 |
| |
| 参数: |
| valid_joints:布尔数组 |
| |
| 返回: |
| bool: 如果满足要求返回True,否则返回False。 |
| """ |
|
|
| |
| |
| |
| |
| top_core_joints = valid_joints[[0,1,2,5]] |
| top_nece_joints = valid_joints[[14,15,16,17]] |
| if all(top_core_joints) and any(top_nece_joints): |
| return True |
| |
| wholebody_core_joints = valid_joints[[0,1,2,5,8,11]] |
| if all(wholebody_core_joints): |
| return True |
| return False |
| |
| |
| def check_valid_sequence(valid_keypoints, threshold=0.3): |
| valid_joints = np.zeros(24) |
| for valid_keypoint in valid_keypoints: |
| valid_joints += valid_keypoint |
| return part5_valid(valid_joints) |
|
|
|
|
| def get_valid_indice_from_keypoints(ref_part_poses, ref_part_indices): |
| |
| |
| valid_indice = [] |
| for i, (keypoint_all, indice) in enumerate(zip(ref_part_poses, ref_part_indices)): |
| body_subset = keypoint_all["bodies"]["subset"][0] |
| valid_joints = body_subset > -1 |
|
|
| if not part5_valid(valid_joints): |
| continue |
|
|
| faces = keypoint_all["faces"][0] |
|
|
| left_eye = faces[36:42] |
| right_eye = faces[42:48] |
| nose = faces[27:36] |
| mouth = faces[48:68] |
|
|
| |
| left_eye_valid = sum(1 for point in left_eye if point[0] > 0 and point[1] > 0) |
| right_eye_valid = sum(1 for point in right_eye if point[0] > 0 and point[1] > 0) |
| nose_valid = sum(1 for point in nose if point[0] > 0 and point[1] > 0) |
| mouth_valid = sum(1 for point in mouth if point[0] > 0 and point[1] > 0) |
|
|
| |
| valid_face_parts = 0 |
| if left_eye_valid >= 4: |
| valid_face_parts += 1 |
| if right_eye_valid >= 4: |
| valid_face_parts += 1 |
| if nose_valid >= 5: |
| valid_face_parts += 1 |
| if mouth_valid >= 15: |
| valid_face_parts += 1 |
|
|
| if valid_face_parts >= 2: |
| valid_indice.append(int(indice)) |
| |
| return valid_indice |
| |
| def check_from_keypoints_core_keypoints(keypoints, bboxs): |
| |
| valid_sequence = deque(maxlen=4) |
| for i, (keypoint_all, bbox_all) in enumerate(zip(keypoints, bboxs)): |
| body_subset = keypoint_all["bodies"]["subset"][0] |
| valid_joints = body_subset > -1 |
| if len(valid_sequence) == 4: |
| if not check_valid_sequence(valid_sequence): |
| |
| return False |
| valid_sequence.append(valid_joints) |
| return True |
|
|
| def select_ref_from_keypoints_bbox_multi(ref_part_indices, ref_part_bboxes, bboxs): |
| for ref_index, ref_bbox in zip(ref_part_indices, ref_part_bboxes): |
| bbox_areas_ref = [get_bbox_area(bbox) for bbox in ref_bbox] |
| max_bbox_area_ref = max(bbox_areas_ref) |
| num_human_ref = sum(1 for bbox in ref_bbox if get_bbox_area(bbox) > max_bbox_area_ref * 0.5) |
| if num_human_ref < 2 or num_human_ref > 5: |
| continue |
| driving_bbox_ok = True |
| for i, bbox_all in enumerate(bboxs): |
| bbox_areas = [get_bbox_area(bbox) for bbox in bbox_all] |
| max_bbox_area = max(bbox_areas) |
| num_human = sum(1 for bbox in bbox_all if get_bbox_area(bbox) > max_bbox_area * 0.5) |
| if num_human != num_human_ref: |
| driving_bbox_ok = False |
| break |
| if driving_bbox_ok: |
| return int(ref_index) |
| else: |
| continue |
| return None |
|
|
| def check_from_keypoints_bbox(keypoints, bboxs, IoU_thresthold, reference_width, reference_height, multi_person=False): |
| |
| last_bbox = None |
| for i, (keypoint_all, bbox_all) in enumerate(zip(keypoints, bboxs)): |
| if not len(bbox_all): |
| return False |
| else: |
| if multi_person: |
| for bbox in bbox_all: |
| if not check_bbox_single_for_video(bbox, reference_width, reference_height, min_bbox_width=1/6): |
| return False |
| else: |
| bbox = bbox_all[0] |
| if not check_bbox_single_for_video(bbox, reference_width, reference_height, min_bbox_width=1/7): |
| return False |
| if last_bbox is not None: |
| if not get_IoU(bbox, last_bbox) > IoU_thresthold: |
| return False |
| last_bbox = bbox |
| return True |
|
|
|
|
|
|
| def check_from_keypoints_stick_movement(keypoints, angle_threshold): |
| |
| |
| bones = [(1, 0), (1, 2), (1, 5), (1, 8), (1, 11), (2, 3), (5, 6), (8, 9), (11, 12)] |
| max_delta_list = [] |
| |
| human_num_list = [len(keypoints[idx]["bodies"]["candidate"]) for idx in range(0, len(keypoints))] |
| min_human_num = min(human_num_list) |
| for human_idx in range(min_human_num): |
| for i in range(1, len(keypoints)): |
| |
| prev_frame_subset = keypoints[i-1]["bodies"]["subset"][human_idx] |
| curr_frame_subset = keypoints[i]["bodies"]["subset"][human_idx] |
| prev_frame_keypoints = keypoints[i-1]["bodies"]["candidate"][human_idx] |
| curr_frame_keypoints = keypoints[i]["bodies"]["candidate"][human_idx] |
|
|
| |
| max_delta = 0 |
| for (j1, j2) in bones: |
| |
| if prev_frame_subset[j1] < 0 or prev_frame_subset[j2] < 0: |
| continue |
| if curr_frame_subset[j1] < 0 or curr_frame_subset[j2] < 0: |
| continue |
|
|
| |
| vec_prev = np.array([prev_frame_keypoints[j2][0] - prev_frame_keypoints[j1][0], |
| prev_frame_keypoints[j2][1] - prev_frame_keypoints[j1][1]]) |
| vec_curr = np.array([curr_frame_keypoints[j2][0] - curr_frame_keypoints[j1][0], |
| curr_frame_keypoints[j2][1] - curr_frame_keypoints[j1][1]]) |
| |
| |
| if np.linalg.norm(vec_prev) == 0 or np.linalg.norm(vec_curr) == 0: |
| continue |
| |
| angle_prev = math.atan2(vec_prev[1], vec_prev[0]) |
| angle_curr = math.atan2(vec_curr[1], vec_curr[0]) |
| |
| |
| delta = abs(angle_curr - angle_prev) |
| if delta > math.pi: |
| delta = 2 * math.pi - delta |
| |
| max_delta = max(delta, max_delta) |
| max_delta_list.append(max_delta) |
| max_delta_list = sorted(max_delta_list) |
| max_delta_list = max_delta_list[len(max_delta_list)//8:-len(max_delta_list)//8] |
| avg_movement = sum(max_delta_list) / len(max_delta_list) |
| if avg_movement < angle_threshold: |
| return False |
| return True |
| |