Spaces:
Build error
Build error
File size: 4,045 Bytes
9847531 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import time
import numpy as np
from contextlib import contextmanager
from loguru import logger
from typing import List, Dict, Optional, Tuple, Union
from detection_schema import BBox
from storage import StorageInterface
class DebugHandler:
"""Production-grade debugging and performance tracking"""
def __init__(self, enabled: bool = False, storage: StorageInterface = None):
self.enabled = enabled
self.storage = storage
self.metrics = {}
self._start_time = None
@contextmanager
def track_performance(self, operation_name: str):
"""Context manager for performance tracking"""
if self.enabled:
self._start_time = time.perf_counter()
logger.debug(f"Starting {operation_name}")
yield
if self.enabled:
duration = time.perf_counter() - self._start_time
self.metrics[operation_name] = duration
logger.debug(f"{operation_name} completed in {duration:.2f}s")
def save_artifact(self, name: str, data: bytes, extension: str = "png"):
"""Generic artifact storage handler"""
if self.enabled and self.storage:
path = f"debug/{name}.{extension}"
self.storage.save_file(path, data)
logger.info(f"Saved debug artifact: {path}")
class CoordinateTransformer:
@staticmethod
def global_to_local_bbox(
bbox: Union[BBox, List[BBox]],
roi: Optional[np.ndarray]
) -> Union[BBox, List[BBox]]:
"""
Convert global BBox(es) to ROI-local coordinates
Handles both single BBox and lists of BBoxes
"""
if roi is None or len(roi) != 4:
return bbox
x_min, y_min, _, _ = roi
def convert(b: BBox) -> BBox:
return BBox(
xmin=b.xmin - x_min,
ymin=b.ymin - y_min,
xmax=b.xmax - x_min,
ymax=b.ymax - y_min
)
return map(convert, bbox) if isinstance(bbox, list) else convert(bbox)
@staticmethod
def local_to_global_bbox(
bbox: Union[BBox, List[BBox]],
roi: Optional[np.ndarray]
) -> Union[BBox, List[BBox]]:
"""
Convert ROI-local BBox(es) to global coordinates
Handles both single BBox and lists of BBoxes
"""
if roi is None or len(roi) != 4:
return bbox
x_min, y_min, _, _ = roi
def convert(b: BBox) -> BBox:
return BBox(
xmin=b.xmin + x_min,
ymin=b.ymin + y_min,
xmax=b.xmax + x_min,
ymax=b.ymax + y_min
)
return map(convert, bbox) if isinstance(bbox, list) else convert(bbox)
# Maintain legacy tuple support if needed
@staticmethod
def global_to_local(
bboxes: List[Tuple[int, int, int, int]],
roi: Optional[np.ndarray]
) -> List[Tuple[int, int, int, int]]:
"""Legacy tuple version for backward compatibility"""
if roi is None or len(roi) != 4:
return bboxes
x_min, y_min, _, _ = roi
return [(x1 - x_min, y1 - y_min, x2 - x_min, y2 - y_min)
for x1, y1, x2, y2 in bboxes]
@staticmethod
def local_to_global(
bboxes: List[Tuple[int, int, int, int]],
roi: Optional[np.ndarray]
) -> List[Tuple[int, int, int, int]]:
"""Legacy tuple version for backward compatibility"""
if roi is None or len(roi) != 4:
return bboxes
x_min, y_min, _, _ = roi
return [(x1 + x_min, y1 + y_min, x2 + x_min, y2 + y_min)
for x1, y1, x2, y2 in bboxes]
@staticmethod
def local_to_global_point(point: Tuple[int, int], roi: Optional[np.ndarray]) -> Tuple[int, int]:
"""Convert single point from local to global coordinates"""
if roi is None or len(roi) != 4:
return point
x_min, y_min, _, _ = roi
return (int(point[0] + x_min), int(point[1] + y_min))
|