Spaces:
Runtime error
Runtime error
| # -*- coding: UTF-8 -*- | |
| '''================================================= | |
| @Project -> File pram -> geometry | |
| @IDE PyCharm | |
| @Author fx221@cam.ac.uk | |
| @Date 07/02/2024 11:08 | |
| ==================================================''' | |
| import numpy as np | |
| def nms_fast(in_corners, H, W, dist_thresh): | |
| """ | |
| Run a faster approximate Non-Max-Suppression on numpy corners shaped: | |
| 3xN [x_i,y_i,conf_i]^T | |
| Algo summary: Create a grid sized HxW. Assign each corner location a 1, rest | |
| are zeros. Iterate through all the 1's and convert them either to -1 or 0. | |
| Suppress points by setting nearby values to 0. | |
| Grid Value Legend: | |
| -1 : Kept. | |
| 0 : Empty or suppressed. | |
| 1 : To be processed (converted to either kept or supressed). | |
| NOTE: The NMS first rounds points to integers, so NMS distance might not | |
| be exactly dist_thresh. It also assumes points are within image boundaries. | |
| Inputs | |
| in_corners - 3xN numpy array with corners [x_i, y_i, confidence_i]^T. | |
| H - Image height. | |
| W - Image width. | |
| dist_thresh - Distance to suppress, measured as an infinty norm distance. | |
| Returns | |
| nmsed_corners - 3xN numpy matrix with surviving corners. | |
| nmsed_inds - N length numpy vector with surviving corner indices. | |
| """ | |
| grid = np.zeros((H, W)).astype(int) # Track NMS data. | |
| inds = np.zeros((H, W)).astype(int) # Store indices of points. | |
| # Sort by confidence and round to nearest int. | |
| inds1 = np.argsort(-in_corners[2, :]) | |
| corners = in_corners[:, inds1] | |
| rcorners = corners[:2, :].round().astype(int) # Rounded corners. | |
| # Check for edge case of 0 or 1 corners. | |
| if rcorners.shape[1] == 0: | |
| return np.zeros((3, 0)).astype(int), np.zeros(0).astype(int) | |
| if rcorners.shape[1] == 1: | |
| out = np.vstack((rcorners, in_corners[2])).reshape(3, 1) | |
| return out, np.zeros((1)).astype(int) | |
| # Initialize the grid. | |
| for i, rc in enumerate(rcorners.T): | |
| grid[rcorners[1, i], rcorners[0, i]] = 1 | |
| inds[rcorners[1, i], rcorners[0, i]] = i | |
| # Pad the border of the grid, so that we can NMS points near the border. | |
| pad = dist_thresh | |
| grid = np.pad(grid, ((pad, pad), (pad, pad)), mode='constant') | |
| # Iterate through points, highest to lowest conf, suppress neighborhood. | |
| count = 0 | |
| for i, rc in enumerate(rcorners.T): | |
| # Account for top and left padding. | |
| pt = (rc[0] + pad, rc[1] + pad) | |
| if grid[pt[1], pt[0]] == 1: # If not yet suppressed. | |
| grid[pt[1] - pad:pt[1] + pad + 1, pt[0] - pad:pt[0] + pad + 1] = 0 | |
| grid[pt[1], pt[0]] = -1 | |
| count += 1 | |
| # Get all surviving -1's and return sorted array of remaining corners. | |
| keepy, keepx = np.where(grid == -1) | |
| keepy, keepx = keepy - pad, keepx - pad | |
| inds_keep = inds[keepy, keepx] | |
| out = corners[:, inds_keep] | |
| values = out[-1, :] | |
| inds2 = np.argsort(-values) | |
| out = out[:, inds2] | |
| out_inds = inds1[inds_keep[inds2]] | |
| return out_inds | |