Compute body penetration/collision percentage using BVH collision detection
(full_info_path: str, device: str, **kwargs)
| 137 | |
| 138 | |
| 139 | def compute_body_penetration(full_info_path: str, device: str, **kwargs): |
| 140 | """ |
| 141 | Compute body penetration/collision percentage using BVH collision detection |
| 142 | """ |
| 143 | prompt_dict_ls = load_dimension_info(full_info_path, dimension='Body_Penetration') |
| 144 | gender = 'neutral' |
| 145 | model_path = 'data/body_models/smpl/SMPL_NEUTRAL.pkl' |
| 146 | |
| 147 | collision_percentage_list = [] |
| 148 | per_motion_metrics = [] |
| 149 | skipped = 0 |
| 150 | |
| 151 | for prompt_dict in tqdm(prompt_dict_ls): |
| 152 | evaluation_file = prompt_dict["evaluation_file"] |
| 153 | try: |
| 154 | data = load_pose_data(evaluation_file, device, require_vertices=True) |
| 155 | except ValueError as e: |
| 156 | skipped += 1 |
| 157 | continue |
| 158 | |
| 159 | pred_joints = torch.as_tensor(data['joints'], device=device, dtype=torch.float32) |
| 160 | pred_vertices = torch.as_tensor(data['vertices'], device=device, dtype=torch.float32) |
| 161 | motion_length = pred_joints.shape[0] |
| 162 | |
| 163 | # Initialize SMPL model |
| 164 | smpl_model = get_smpl_model(gender=gender, model_path=model_path, batch_size=motion_length, device=device) |
| 165 | faces_np = np.asarray(smpl_model.faces, dtype=np.int64) |
| 166 | faces = torch.as_tensor(faces_np, device=device, dtype=torch.long) |
| 167 | |
| 168 | # Self-collision detection |
| 169 | bvh_model = BVH(max_collisions=8) |
| 170 | collision_percentage = [] |
| 171 | for frame_idx in range(pred_vertices.shape[0]): |
| 172 | vertices = pred_vertices[frame_idx].unsqueeze(dim=0) |
| 173 | triangles = vertices[:, faces] |
| 174 | outputs = bvh_model(triangles) |
| 175 | outputs = outputs.detach().cpu().numpy().squeeze() |
| 176 | collisions = outputs[outputs[:, 0] >= 0, :] |
| 177 | collision_percentage.append(collisions.shape[0] / float(triangles.shape[1]) * 100) |
| 178 | collision_percentage = np.mean(collision_percentage) |
| 179 | |
| 180 | collision_value = float(collision_percentage) |
| 181 | collision_percentage_list.append(collision_value) |
| 182 | per_motion_metrics.append( |
| 183 | { |
| 184 | "id": prompt_dict.get("id"), |
| 185 | "prompt": prompt_dict.get("prompt"), |
| 186 | "value": collision_value, |
| 187 | "evaluation_file": evaluation_file, |
| 188 | "motion_duration": prompt_dict.get("motion_duration"), |
| 189 | } |
| 190 | ) |
| 191 | |
| 192 | if skipped > 0: |
| 193 | print(f"Body_Penetration: Skipped {skipped} samples (missing SMPLify data). Run SMPLify rendering first.") |
| 194 | |
| 195 | return { |
| 196 | "aggregate": summarize_scores(collision_percentage_list), |
nothing calls this directly
no test coverage detected