Spaces:
Running
on
Zero
Running
on
Zero
| import logging | |
| import numpy as np | |
| from typing import Dict, List, Optional, Any | |
| class ProminenceCalculator: | |
| """ | |
| 重要性計算器 - 專門處理物件重要性評估和篩選邏輯 | |
| 負責計算物件的重要性分數、類別重要性係數以及重要物件的篩選 | |
| """ | |
| def __init__(self, min_prominence_score: float = 0.1): | |
| """ | |
| 初始化重要性計算器 | |
| Args: | |
| min_prominence_score: 物件顯著性的最低分數閾值 | |
| """ | |
| self.logger = logging.getLogger(self.__class__.__name__) | |
| self.min_prominence_score = min_prominence_score | |
| def calculate_prominence_score(self, obj: Dict) -> float: | |
| """ | |
| 計算物件的重要性評分 | |
| 基本上權重設定為信心度 > 尺寸 > 空間 > 類別重要性 | |
| Args: | |
| obj: 物件字典,包含檢測信息 | |
| Returns: | |
| float: 重要性評分 (0.0-1.0) | |
| """ | |
| try: | |
| # 基礎置信度評分 (權重: 40%) | |
| confidence = obj.get("confidence", 0.5) | |
| confidence_score = confidence * 0.4 | |
| # 大小評分 (權重: 30%) | |
| normalized_area = obj.get("normalized_area", 0.1) | |
| # 使用對數縮放避免過大物件主導評分 | |
| size_score = min(np.log(normalized_area * 10 + 1) / np.log(11), 1.0) * 0.3 | |
| # 位置評分 (權重: 20%) | |
| # 中心區域的物件通常更重要 | |
| center_x, center_y = obj.get("normalized_center", [0.5, 0.5]) | |
| distance_from_center = np.sqrt((center_x - 0.5)**2 + (center_y - 0.5)**2) | |
| position_score = (1 - min(distance_from_center * 2, 1.0)) * 0.2 | |
| # 類別重要性評分 (權重: 10%) | |
| class_importance = self.get_class_importance(obj.get("class_name", "unknown")) | |
| class_score = class_importance * 0.1 | |
| total_score = confidence_score + size_score + position_score + class_score | |
| # 確保評分在有效範圍內 | |
| return max(0.0, min(1.0, total_score)) | |
| except Exception as e: | |
| self.logger.warning(f"Error calculating prominence score for object: {str(e)}") | |
| return 0.5 # 返回中等評分作為備用 | |
| def get_class_importance(self, class_name: str) -> float: | |
| """ | |
| 根據物件類別返回重要性係數 | |
| Args: | |
| class_name: 物件類別名稱 | |
| Returns: | |
| float: 類別重要性係數 (0.0-1.0) | |
| """ | |
| # 高重要性物件(人、車輛、建築) | |
| high_importance = ["person", "car", "truck", "bus", "motorcycle", "bicycle", "building"] | |
| # 中等重要性物件(家具、電器) | |
| medium_importance = ["chair", "couch", "tv", "laptop", "refrigerator", "dining table", "bed"] | |
| # 低重要性物件(小物品、配件) | |
| low_importance = ["handbag", "backpack", "umbrella", "cell phone", "remote", "mouse"] | |
| class_name_lower = class_name.lower() | |
| if any(item in class_name_lower for item in high_importance): | |
| return 1.0 | |
| elif any(item in class_name_lower for item in medium_importance): | |
| return 0.7 | |
| elif any(item in class_name_lower for item in low_importance): | |
| return 0.4 | |
| else: | |
| return 0.6 # 預設中等重要性 | |
| def filter_prominent_objects(self, detected_objects: List[Dict], | |
| min_prominence_score: float = 0.5, | |
| max_categories_to_return: Optional[int] = None) -> List[Dict]: | |
| """ | |
| 獲取最重要的物件,基於置信度、大小和位置計算重要性評分 | |
| Args: | |
| detected_objects: 檢測到的物件列表 | |
| min_prominence_score: 最小重要性分數閾值,範圍 0.0-1.0 | |
| max_categories_to_return: 可選的最大返回類別數量限制 | |
| Returns: | |
| List[Dict]: 按重要性排序的物件列表 | |
| """ | |
| try: | |
| if not detected_objects: | |
| return [] | |
| prominent_objects = [] | |
| for obj in detected_objects: | |
| # 計算重要性評分 | |
| prominence_score = self.calculate_prominence_score(obj) | |
| # 只保留超過閾值的物件 | |
| if prominence_score >= min_prominence_score: | |
| obj_copy = obj.copy() | |
| obj_copy['prominence_score'] = prominence_score | |
| prominent_objects.append(obj_copy) | |
| # 按重要性評分排序(從高到低) | |
| prominent_objects.sort(key=lambda x: x.get('prominence_score', 0), reverse=True) | |
| # 如果指定了最大類別數量限制,進行過濾 | |
| if max_categories_to_return is not None and max_categories_to_return > 0: | |
| categories_seen = set() | |
| filtered_objects = [] | |
| for obj in prominent_objects: | |
| class_name = obj.get("class_name", "unknown") | |
| # 如果是新類別且未達到限制 | |
| if class_name not in categories_seen: | |
| if len(categories_seen) < max_categories_to_return: | |
| categories_seen.add(class_name) | |
| filtered_objects.append(obj) | |
| else: | |
| # 已見過的類別,直接添加 | |
| filtered_objects.append(obj) | |
| return filtered_objects | |
| return prominent_objects | |
| except Exception as e: | |
| self.logger.error(f"Error calculating prominent objects: {str(e)}") | |
| return [] | |