Spaces:
Running
on
Zero
Running
on
Zero
File size: 5,719 Bytes
12d9ea9 |
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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
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 []
|