def do_poly_nms(gdf:gpd.GeoDataFrame, nms_thresh=0.1, crit='score') -> gpd.GeoDataFrame:
"Perform non-max suppression for polygons using `nms_threshold` to `gdf`"
gdf = gdf.copy()
scores = gdf.score.values
idxs = non_max_suppression_poly(gdf.geometry.values, scores, nms_thresh, crit)
gdf = gdf.iloc[idxs]
return gdfPostprocessing
Smoothing, combining etc.
Non-maximum suppression
First the commonly used NMS with bounding boxes, that prioritizes either confidence score (default) or bounding box area.
non_max_suppression_fast
def non_max_suppression_fast(
boxes, scores, overlap_thresh:float, sort_criterion:str='score'
):
Possibility to sort boxes by score (default) or area
Non-max suppression can in theory be applied also on polygons, but it hasn’t been used in any publications as far as I know.
If non_max_suppression_poly is used to eliminate polygons, threshold might need to be smaller than typical value of 0.7 that is used.
poly_IoU
def poly_IoU(
poly_1:Polygon, poly_2:Polygon
)->float:
Calculate IoU for two shapely Polygons
non_max_suppression_poly
def non_max_suppression_poly(
geoms, scores, overlap_thresh:float, sort_criterion:str='score'
):
Do non-max suppression for shapely Polygons in geoms. Can be sorted according to area or score
Some utils to run above functions to GeoDataFrames
do_nms
def do_nms(
gdf:GeoDataFrame, nms_thresh:float=0.7, crit:str='score'
)->GeoDataFrame:
Perform non-max suppression for bounding boxes using nms_threshold to gdf
def do_min_rot_rectangle_nms(gdf:gpd.GeoDataFrame, nms_thresh=0.7, crit='score') -> gpd.GeoDataFrame:
"Perform non-max suppression for rotated bounding boxes using `nms_threshold` to `gdf`"
gdf = gdf.copy()
scores = gdf.score.values
boxes = np.array([g.minimum_rotated_rectangle for g in gdf.geometry.values])
idxs = non_max_suppression_poly(boxes, scores, nms_thresh, crit)
gdf = gdf.iloc[idxs]
return gdf