Files
2026-07-13 12:49:22 +08:00

90 lines
3.2 KiB
Python

"""
Helper functions used internally for object detection tasks.
"""
from typing import Any, Dict, List, Optional
import numpy as np
from cleanlab.internal.numerics import softmax
def bbox_xyxy_to_xywh(bbox: List[float]) -> Optional[List[float]]:
"""Converts bounding box coodrinate types from x1y1,x2y2 to x,y,w,h"""
if len(bbox) == 4:
x1, y1, x2, y2 = bbox
w = x2 - x1
h = y2 - y1
return [x1, y1, w, h]
else:
print("Wrong bbox shape", len(bbox))
return None
def softmin1d(scores: np.ndarray, temperature: float = 0.99, axis: int = 0) -> float:
"""Returns softmin of passed in scores."""
scores = np.array(scores)
softmax_scores = softmax(x=-1 * scores, temperature=temperature, axis=axis, shift=True)
return np.dot(softmax_scores, scores)
def calculate_bounding_box_areas(rectangle_coordinates):
"""Calculate areas of bounding boxes represented by numpy array with x1, y1, x2, y2 format"""
widths = rectangle_coordinates[:, 2] - rectangle_coordinates[:, 0]
heights = rectangle_coordinates[:, 3] - rectangle_coordinates[:, 1]
return widths * heights
def assert_valid_aggregation_weights(aggregation_weights: Dict[str, Any]) -> None:
"""assert aggregation weights are in the proper format"""
weights = np.array(list(aggregation_weights.values()))
if (not np.isclose(np.sum(weights), 1.0)) or (np.min(weights) < 0.0):
raise ValueError(
f"""Aggregation weights should be non-negative and must sum to 1.0
"""
)
def assert_valid_inputs(
labels: List[Dict[str, Any]],
predictions,
method: Optional[str] = None,
threshold: Optional[float] = None,
):
"""Asserts proper input format."""
if len(labels) != len(predictions):
raise ValueError(
f"labels and predictions length needs to match. len(labels) == {len(labels)} while len(predictions) == {len(predictions)}."
)
# Typecheck labels and predictions
if not isinstance(labels[0], dict):
raise ValueError(
f"Labels has to be a list of dicts. Instead it is list of {type(labels[0])}."
)
# check last column of predictions is probabilities ( < 1.)?
if not isinstance(predictions[0], (list, np.ndarray)):
raise ValueError(
f"Prediction has to be a list or np.ndarray. Instead it is type {type(predictions[0])}."
)
if not predictions[0][0].shape[1] == 5:
raise ValueError(
f"Prediction values have to be of format [x1,y1,x2,y2,pred_prob]. Please refer to the documentation for predicted probabilities under object_detection.rank.get_label_quality_scores for details"
)
valid_methods = ["objectlab"]
if method is not None and method not in valid_methods:
raise ValueError(
f"""
{method} is not a valid object detection scoring method!
Please choose a valid scoring_method: {valid_methods}
"""
)
if threshold is not None and threshold > 1.0:
raise ValueError(
f"""
Threshold is a cutoff of predicted probabilities and therefore should be <= 1.
"""
)