Spaces:
Runtime error
Runtime error
| import torch | |
| import numpy as np | |
| import cv2 | |
| from ProposalNetwork.scoring.convex_outline import tracing_outline_robust | |
| import ProposalNetwork.utils.spaces as spaces | |
| from scipy.spatial import cKDTree | |
| from ProposalNetwork.utils.utils import iou_2d, mask_iou, mod_mask_iou | |
| def score_point_cloud(point_cloud:torch.Tensor, cubes:list[spaces.Cubes], K:torch.Tensor=None, segmentation_mask:torch.Tensor=None): | |
| ''' | |
| score the cube according to the density (number of points) of the point cloud in the cube | |
| ''' | |
| # must normalise the point cloud to have the same density for the entire depth | |
| verts = cubes.get_all_corners().squeeze(0) | |
| min_x, _, = verts[:,0].min(1); max_x, _ = verts[:,0].max(1) | |
| min_y, _, = verts[:,1].min(1); max_y, _ = verts[:,1].max(1) | |
| min_z, _, = verts[:,2].min(1); max_z, _ = verts[:,2].max(1) | |
| point_cloud_dens = ((point_cloud[:,0].view(-1,1) > min_x) & | |
| (point_cloud[:,0].view(-1,1) < max_x) & | |
| (point_cloud[:,1].view(-1,1) > min_y) & | |
| (point_cloud[:,1].view(-1,1) < max_y) & | |
| (point_cloud[:,2].view(-1,1) > min_z) & | |
| (point_cloud[:,2].view(-1,1) < max_z)) | |
| score = point_cloud_dens.sum(0) | |
| # method 1 | |
| # just in case this is needed in the future, the function can be found at commit ID: 4a06501c46beda804fd3b8ddfcbb27211f89ef66 | |
| # area = cube.get_projected_2d_area(K).item() | |
| # if area != 0: | |
| # score /= area | |
| # method 2 | |
| # corners = cube.get_bube_corners(K) | |
| # bube_mask = np.zeros(segmentation_mask.shape, dtype=np.uint8) | |
| # polygon_points = cv2.convexHull(corners.numpy()) | |
| # polygon_points = np.array([polygon_points],dtype=np.int32) | |
| # cv2.fillPoly(bube_mask, polygon_points, 1) | |
| # normalisation = (bube_mask).sum() | |
| # if normalisation != 0: | |
| # score = score/normalisation | |
| return score | |
| def score_iou(gt_box, proposal_box): | |
| IoU = iou_2d(gt_box,proposal_box) | |
| return IoU | |
| def modified_chamfer_distance(set1, set2): | |
| tree2 = cKDTree(set2) | |
| # For each point in set1 (seg point), find the distance to the nearest point in set2 (bube corner) | |
| distances2, _ = tree2.query(set1) | |
| return np.mean(distances2) | |
| def score_corners(segmentation_mask, bube_corners): | |
| mask_np = segmentation_mask.cpu().numpy().astype(np.uint8) | |
| # Find contours | |
| contours, _ = cv2.findContours(mask_np, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| # Find the minimum area rectangle around the largest contour | |
| if contours: | |
| largest_contour = max(contours, key=cv2.contourArea) | |
| rect = cv2.minAreaRect(largest_contour) | |
| box = cv2.boxPoints(rect) | |
| else: | |
| # if it fails, set the box as the mean of the bube corners | |
| mean_min_x = bube_corners[:,:,0].min(1)[0].mean().cpu().numpy() | |
| mean_max_x = bube_corners[:,:,0].max(1)[0].mean().cpu().numpy() | |
| mean_min_y = bube_corners[:,:,1].min(1)[0].mean().cpu().numpy() | |
| mean_max_y = bube_corners[:,:,1].max(1)[0].mean().cpu().numpy() | |
| box = np.array([[mean_min_x, mean_min_y], [mean_max_x, mean_min_y], [mean_max_x, mean_max_y], [mean_min_x, mean_max_y]]) | |
| bube_corners = bube_corners.squeeze(0) # remove instance dim | |
| scores = torch.zeros(len(bube_corners), device=segmentation_mask.device) | |
| for i in range(len(bube_corners)): | |
| # Chamfer distance bube corners and box | |
| scores[i] = modified_chamfer_distance(box, bube_corners[i].cpu().numpy()) | |
| max_score = torch.max(scores) | |
| return 1 - scores / max_score | |
| def score_segmentation(segmentation_mask, bube_corners): | |
| ''' | |
| segmentation_mask : Mask | |
| bube_corners : List of Lists | |
| ''' | |
| bube_corners = bube_corners.to(device=segmentation_mask.device) | |
| bube_corners = bube_corners.squeeze(0) # remove instance dim | |
| scores = torch.zeros(len(bube_corners), device=segmentation_mask.device) | |
| for i in range(len(bube_corners)): | |
| bube_mask = np.zeros(segmentation_mask.shape, dtype='uint8') | |
| # Remove "inner" points (2) and put others in correct order | |
| # Calculate the convex hull of the points which also orders points correctly | |
| polygon_points = cv2.convexHull(np.array(bube_corners[i])) | |
| polygon_points = np.array([polygon_points],dtype=np.int32) | |
| cv2.fillPoly(bube_mask, polygon_points, 1) | |
| scores[i] = mask_iou(segmentation_mask[::4,::4], bube_mask[::4,::4]) | |
| return scores | |
| def score_mod_segmentation(segmentation_mask, bube_corners): | |
| ''' | |
| segmentation_mask : Mask | |
| bube_corners : List of Lists | |
| ''' | |
| bube_corners = bube_corners.to(device=segmentation_mask.device) | |
| bube_corners = bube_corners.squeeze(0) # remove instance dim | |
| scores = torch.zeros(len(bube_corners), device=segmentation_mask.device) | |
| for i in range(len(bube_corners)): | |
| bube_mask = np.zeros(segmentation_mask.shape, dtype='uint8') | |
| # Remove "inner" points (2) and put others in correct order | |
| # Calculate the convex hull of the points which also orders points correctly | |
| polygon_points = cv2.convexHull(np.array(bube_corners[i])) | |
| polygon_points = np.array([polygon_points],dtype=np.int32) | |
| cv2.fillPoly(bube_mask, polygon_points, 1) | |
| scores[i] = mod_mask_iou(segmentation_mask[::4,::4], bube_mask[::4,::4]) | |
| return scores | |
| def score_segmentation_v2(segmentation_mask, pred_cubes, K): | |
| scores = [] | |
| for i in range(len(pred_cubes.tensor.squeeze())): | |
| v_2d = pred_cubes[:, i].get_bube_corners(K).squeeze() | |
| _, f = pred_cubes[:, i].get_cuboids_verts_faces() | |
| f = f.squeeze() | |
| points, ids = tracing_outline_robust(v_2d.numpy(), f.numpy()) # not doing any projection,just simply take the verts's x and y . | |
| bube_mask = np.zeros(segmentation_mask.shape, dtype='uint8') | |
| # append first point to close the loop | |
| # points = np.append(points, [points[0]], axis=0) | |
| cv2.fillPoly(bube_mask, np.expand_dims(points,0).astype(int), 1) | |
| scores.append(mask_iou(segmentation_mask, bube_mask)) | |
| return scores | |
| def score_dimensions(category, dimensions, gt_boxes, pred_boxes): | |
| ''' | |
| category : List | |
| dimensions : List of Lists | |
| P(dim|priors) | |
| ''' | |
| # category_name = Metadatacatalog.thing_classes[category] # for printing and checking that correct | |
| [prior_mean, prior_std] = category | |
| dimensions_scores = torch.exp(-1/2 * ((dimensions - prior_mean)/prior_std)**2) | |
| scores = dimensions_scores.mean(1) | |
| gt_ratio = (gt_boxes.tensor[0,2]-gt_boxes.tensor[0,0])/(gt_boxes.tensor[0,3]-gt_boxes.tensor[0,1]) | |
| pred_ratios = (pred_boxes.tensor[:,2]-pred_boxes.tensor[:,0])/(pred_boxes.tensor[:,3]-pred_boxes.tensor[:,1]) | |
| differences = torch.abs(gt_ratio-pred_ratios) | |
| max_difference = torch.max(differences) | |
| return (1 - differences / max_difference) * scores | |
| def score_ratios(gt_box,pred_boxes): | |
| gt_points = gt_box.tensor[0] | |
| differences = torch.abs(pred_boxes.tensor - gt_points).sum(axis=1) | |
| max_difference = torch.max(differences) | |
| return 1 - differences / max_difference | |
| # 3D Dim Ratio | |
| gt_ratio = gt_dim[0]/gt_dim[1] | |
| pred_ratios = pred_dims[:,0]/pred_dims[:,1] | |
| differences = torch.abs(pred_ratios-gt_ratio) | |
| max_difference = torch.max(differences) | |
| return 1 - differences / max_difference | |
| # 2D Dim Ratio | |
| gt_ratio = (gt_dim.tensor[0,2]-gt_dim.tensor[0,0])/(gt_dim.tensor[0,3]-gt_dim.tensor[0,1]) | |
| pred_ratios = (pred_dims.tensor[:,2]-pred_dims.tensor[:,0])/(pred_dims.tensor[:,3]-pred_dims.tensor[:,1]) | |
| differences = torch.abs(pred_ratios-gt_ratio) | |
| max_difference = torch.max(differences) | |
| return 1 - differences / max_difference | |
| def score_function(gt_box, proposal_box, bube_corners, segmentation_mask, category, dimensions): | |
| score = 1.0 | |
| score *= score_iou(gt_box, proposal_box) | |
| score *= score_segmentation(bube_corners, segmentation_mask) | |
| score *= score_dimensions(category, dimensions) | |
| return score | |
| if __name__ == '__main__': | |
| # testing | |
| s = score_point_cloud(torch.tensor([[0.1,0.1,0.1],[0.2,0.2,0.2],[-3,0,0]]), [spaces.Cube(torch.tensor([0.5,0.5,0.5,1,1,1]), torch.eye(3))]) | |
| print(s) | |
| assert s == 2 |