Skip to content

Utils

sahi.postprocess.utils

Classes

Functions

calculate_area(box)

Parameters:

Name Type Description Default
box
List[int]

[x1, y1, x2, y2]

required
Source code in sahi/postprocess/utils.py
def calculate_area(box: Union[List[int], np.ndarray]) -> float:
    """
    Args:
        box (List[int]): [x1, y1, x2, y2]
    """
    return (box[2] - box[0]) * (box[3] - box[1])

calculate_bbox_ios(pred1, pred2)

Returns the ratio of intersection area to the smaller box's area

Source code in sahi/postprocess/utils.py
def calculate_bbox_ios(pred1: ObjectPrediction, pred2: ObjectPrediction) -> float:
    """Returns the ratio of intersection area to the smaller box's area"""
    box1 = np.array(pred1.bbox.to_xyxy())
    box2 = np.array(pred2.bbox.to_xyxy())
    area1 = calculate_area(box1)
    area2 = calculate_area(box2)
    intersect = calculate_intersection_area(box1, box2)
    smaller_area = np.minimum(area1, area2)
    return intersect / smaller_area

calculate_bbox_iou(pred1, pred2)

Returns the ratio of intersection area to the union

Source code in sahi/postprocess/utils.py
def calculate_bbox_iou(pred1: ObjectPrediction, pred2: ObjectPrediction) -> float:
    """Returns the ratio of intersection area to the union"""
    box1 = np.array(pred1.bbox.to_xyxy())
    box2 = np.array(pred2.bbox.to_xyxy())
    area1 = calculate_area(box1)
    area2 = calculate_area(box2)
    intersect = calculate_intersection_area(box1, box2)
    return intersect / (area1 + area2 - intersect)

calculate_box_union(box1, box2)

Parameters:

Name Type Description Default
box1
List[int]

[x1, y1, x2, y2]

required
box2
List[int]

[x1, y1, x2, y2]

required
Source code in sahi/postprocess/utils.py
def calculate_box_union(box1: Union[List[int], np.ndarray], box2: Union[List[int], np.ndarray]) -> List[int]:
    """
    Args:
        box1 (List[int]): [x1, y1, x2, y2]
        box2 (List[int]): [x1, y1, x2, y2]
    """
    box1 = np.array(box1)
    box2 = np.array(box2)
    left_top = np.minimum(box1[:2], box2[:2])
    right_bottom = np.maximum(box1[2:], box2[2:])
    return list(np.concatenate((left_top, right_bottom)))

calculate_intersection_area(box1, box2)

Parameters:

Name Type Description Default
box1
ndarray

np.array([x1, y1, x2, y2])

required
box2
ndarray

np.array([x1, y1, x2, y2])

required
Source code in sahi/postprocess/utils.py
def calculate_intersection_area(box1: np.ndarray, box2: np.ndarray) -> float:
    """
    Args:
        box1 (np.ndarray): np.array([x1, y1, x2, y2])
        box2 (np.ndarray): np.array([x1, y1, x2, y2])
    """
    left_top = np.maximum(box1[:2], box2[:2])
    right_bottom = np.minimum(box1[2:], box2[2:])
    width_height = (right_bottom - left_top).clip(min=0)
    return width_height[0] * width_height[1]

coco_segmentation_to_shapely(segmentation)

Fix segment data in COCO format :param segmentation: segment data in COCO format :return:

Source code in sahi/postprocess/utils.py
def coco_segmentation_to_shapely(segmentation: Union[List, List[List]]):
    """
    Fix segment data in COCO format
    :param segmentation: segment data in COCO format
    :return:
    """
    if isinstance(segmentation, List) and all([not isinstance(seg, List) for seg in segmentation]):
        segmentation = [segmentation]
    elif isinstance(segmentation, List) and all([isinstance(seg, List) for seg in segmentation]):
        pass
    else:
        raise ValueError("segmentation must be List or List[List]")

    polygon_list = []

    for coco_polygon in segmentation:
        point_list = list(zip(coco_polygon[::2], coco_polygon[1::2]))
        shapely_polygon = Polygon(point_list)
        polygon_list.append(repair_polygon(shapely_polygon))

    shapely_multipolygon = repair_multipolygon(MultiPolygon(polygon_list))
    return shapely_multipolygon

object_prediction_list_to_numpy(object_prediction_list)

Returns:

Type Description
ndarray

np.ndarray of size N x [x1, y1, x2, y2, score, category_id]

Source code in sahi/postprocess/utils.py
def object_prediction_list_to_numpy(object_prediction_list: ObjectPredictionList) -> np.ndarray:
    """
    Returns:
        np.ndarray of size N x [x1, y1, x2, y2, score, category_id]
    """
    num_predictions = len(object_prediction_list)
    numpy_predictions = np.zeros([num_predictions, 6], dtype=np.float32)
    for ind, object_prediction in enumerate(object_prediction_list):
        numpy_predictions[ind, :4] = np.array(object_prediction.tolist().bbox.to_xyxy(), dtype=np.float32)
        numpy_predictions[ind, 4] = object_prediction.tolist().score.value
        numpy_predictions[ind, 5] = object_prediction.tolist().category.id
    return numpy_predictions

object_prediction_list_to_torch(object_prediction_list)

Returns:

Type Description
tensor

torch.tensor of size N x [x1, y1, x2, y2, score, category_id]

Source code in sahi/postprocess/utils.py
def object_prediction_list_to_torch(object_prediction_list: ObjectPredictionList) -> torch.tensor:
    """
    Returns:
        torch.tensor of size N x [x1, y1, x2, y2, score, category_id]
    """
    num_predictions = len(object_prediction_list)
    torch_predictions = torch.zeros([num_predictions, 6], dtype=torch.float32)
    for ind, object_prediction in enumerate(object_prediction_list):
        torch_predictions[ind, :4] = torch.tensor(object_prediction.tolist().bbox.to_xyxy(), dtype=torch.float32)
        torch_predictions[ind, 4] = object_prediction.tolist().score.value
        torch_predictions[ind, 5] = object_prediction.tolist().category.id
    return torch_predictions

repair_multipolygon(shapely_multipolygon)

Fix invalid MultiPolygon objects :param shapely_multipolygon: Imported shapely MultiPolygon object :return:

Source code in sahi/postprocess/utils.py
def repair_multipolygon(shapely_multipolygon: MultiPolygon) -> MultiPolygon:
    """
    Fix invalid MultiPolygon objects
    :param shapely_multipolygon: Imported shapely MultiPolygon object
    :return:
    """
    if not shapely_multipolygon.is_valid:
        fixed_geometry = shapely_multipolygon.buffer(0)

        if fixed_geometry.is_valid:
            if isinstance(fixed_geometry, MultiPolygon):
                return fixed_geometry
            elif isinstance(fixed_geometry, Polygon):
                return MultiPolygon([fixed_geometry])
            elif isinstance(fixed_geometry, GeometryCollection):
                polygons = [geom for geom in fixed_geometry.geoms if isinstance(geom, Polygon)]
                return MultiPolygon(polygons) if polygons else shapely_multipolygon

    return shapely_multipolygon

repair_polygon(shapely_polygon)

Fix polygons :param shapely_polygon: Shapely polygon object :return:

Source code in sahi/postprocess/utils.py
def repair_polygon(shapely_polygon: Polygon) -> Polygon:
    """
    Fix polygons
    :param shapely_polygon: Shapely polygon object
    :return:
    """
    if not shapely_polygon.is_valid:
        fixed_polygon = shapely_polygon.buffer(0)
        if fixed_polygon.is_valid:
            if isinstance(fixed_polygon, Polygon):
                return fixed_polygon
            elif isinstance(fixed_polygon, MultiPolygon):
                return max(fixed_polygon.geoms, key=lambda p: p.area)
            elif isinstance(fixed_polygon, GeometryCollection):
                polygons = [geom for geom in fixed_polygon.geoms if isinstance(geom, Polygon)]
                return max(polygons, key=lambda p: p.area) if polygons else shapely_polygon

    return shapely_polygon