Spaces:
Running
on
Zero
Running
on
Zero
File size: 12,033 Bytes
e6a18b7 |
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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
import logging
import traceback
import numpy as np
from typing import Dict, List, Any, Optional
logger = logging.getLogger(__name__)
class ZoneEvaluator:
"""
負責功能區域辨識的可行性評估和物件關聯性計算
評估是否應該進行區域劃分以及計算物件間的功能關聯性
"""
def __init__(self):
"""初始化區域評估器"""
try:
# 定義物件間的功能關聯性評分表
# 分數越高表示兩個物件在功能上越相關,更可能出現在同一功能區域
self.relationship_pairs = {
# 家具組合關係 - 這些組合通常出現在特定功能區域
frozenset([56, 60]): 1.0, # 椅子+桌子 (dining/work area)
frozenset([57, 62]): 0.9, # 沙發+電視 (living area)
frozenset([59, 58]): 0.7, # 床+植物 (bedroom decor)
# 工作相關組合 - 工作環境的典型配置
frozenset([63, 66]): 0.9, # 筆電+鍵盤 (workspace)
frozenset([63, 64]): 0.8, # 筆電+滑鼠 (workspace)
frozenset([60, 63]): 0.8, # 桌子+筆電 (workspace)
# 廚房相關組合 - 廚房設備的常見的物品
frozenset([68, 72]): 0.9, # 微波爐+冰箱 (kitchen)
frozenset([69, 71]): 0.8, # 烤箱+水槽 (kitchen)
# 用餐相關組合 - 餐廳或用餐區域的典型物品
frozenset([60, 40]): 0.8, # 桌子+酒杯 (dining)
frozenset([60, 41]): 0.8, # 桌子+杯子 (dining)
frozenset([56, 40]): 0.7, # 椅子+酒杯 (dining)
# 交通相關組合 - 城市交通的環境
frozenset([2, 9]): 0.8, # 汽車+交通燈 (traffic)
frozenset([0, 9]): 0.7, # 行人+交通燈 (crosswalk)
}
logger.info("ZoneEvaluator initialized with predefined relationship pairs")
except Exception as e:
logger.error(f"Failed to initialize ZoneEvaluator: {str(e)}")
logger.error(traceback.format_exc())
raise
def evaluate_zone_identification_feasibility(self, detected_objects: List[Dict], scene_type: str) -> bool:
"""
基於物件關聯性和分布特徵的彈性可行性評估
決定是否應該進行功能區域劃分
Args:
detected_objects: 檢測到的物件列表
scene_type: 場景類型
Returns:
是否適合進行區域識別
"""
try:
if len(detected_objects) < 2:
logger.info("Insufficient objects for zone identification (minimum 2 required)")
return False
# 計算不同置信度層級的物件分布
# 高信心度物件更可靠,用於核心區域判斷
high_conf_objects = [obj for obj in detected_objects if obj.get("confidence", 0) >= 0.6]
# 中等置信度物件提供補充資訊
medium_conf_objects = [obj for obj in detected_objects if obj.get("confidence", 0) >= 0.4]
# 基礎條件:至少需要一定數量的可信物件才值得進行區域分析
if len(medium_conf_objects) < 2:
logger.info("Insufficient medium confidence objects for zone identification")
return False
# 評估物件間的功能關聯性,關聯性高的物件更適合劃分功能區域
functional_relationships = self.calculate_functional_relationships(detected_objects)
# 評估空間分布多樣性 - 物件分散在多個區域才有劃分的意義
spatial_diversity = self.calculate_spatial_diversity(detected_objects)
# 綜合評分機制,用各項指標加權計算最終可行性評分
feasibility_score = 0
# 物件數量的貢獻(權重30%)- 更多物件提供更多劃分依據
object_count_score = min(len(detected_objects) / 5.0, 1.0) * 0.3
# 信心度質量貢獻(權重25%)- 高置信度物件比例影響可靠性
confidence_score = len(high_conf_objects) / max(len(detected_objects), 1) * 0.25
# 功能關聯性貢獻(權重25%)- 有功能關聯的物件更適合劃分區域
relationship_score = functional_relationships * 0.25
# 空間多樣性貢獻(權重20%)- 分散的物件才需要區域劃分
diversity_score = spatial_diversity * 0.20
feasibility_score = object_count_score + confidence_score + relationship_score + diversity_score
# 動態閾值:根據場景複雜度調整可行性標準
complexity_threshold = self.get_complexity_threshold(scene_type)
is_feasible = feasibility_score >= complexity_threshold
logger.info(f"Zone identification feasibility: {is_feasible} (score: {feasibility_score:.3f}, threshold: {complexity_threshold:.3f})")
logger.debug(f"Score breakdown - objects: {object_count_score:.3f}, confidence: {confidence_score:.3f}, relationships: {relationship_score:.3f}, diversity: {diversity_score:.3f}")
return is_feasible
except Exception as e:
logger.error(f"Error evaluating zone identification feasibility: {str(e)}")
logger.error(traceback.format_exc())
return False
def calculate_functional_relationships(self, detected_objects: List[Dict]) -> float:
"""
計算物件間的功能關聯性評分
基於常見的物件組合模式評估功能相關性
Args:
detected_objects: 檢測到的物件列表
Returns:
功能關聯性評分 (0.0-1.0)
"""
try:
detected_class_ids = set(obj.get("class_id") for obj in detected_objects)
max_possible_score = 0
actual_score = 0
# 遍歷所有預定義的關聯性組合,計算實際場景中的關聯性評分
for pair, score in self.relationship_pairs.items():
max_possible_score += score
# 如果檢測到的物件中包含這個關聯組合,累加其評分
if pair.issubset(detected_class_ids):
actual_score += score
logger.debug(f"Found functional relationship: {pair} with score {score}")
# 標準化評分:實際評分除以最大可能評分
relationship_score = actual_score / max_possible_score if max_possible_score > 0 else 0
logger.info(f"Functional relationships calculated: {relationship_score:.3f} (found {actual_score:.1f}/{max_possible_score:.1f} possible relationships)")
return relationship_score
except Exception as e:
logger.error(f"Error calculating functional relationships: {str(e)}")
logger.error(traceback.format_exc())
return 0
def calculate_spatial_diversity(self, detected_objects: List[Dict]) -> float:
"""
計算物件空間分布的多樣性
評估物件是否分散在不同區域,避免所有物件集中在單一區域
Args:
detected_objects: 檢測到的物件列表
Returns:
空間多樣性評分 (0.0-1.0)
"""
try:
# 收集所有物件所在的不同區域
regions = set(obj.get("region", "center") for obj in detected_objects)
unique_regions = len(regions)
# 標準化多樣性評分:假設理想情況是物件分散在2個以上區域
# 更多區域意味著更高的空間多樣性,更適合進行區域劃分
diversity_score = min(unique_regions / 2.0, 1.0)
logger.info(f"Spatial diversity calculated: {diversity_score:.3f} (objects distributed across {unique_regions} regions)")
return diversity_score
except Exception as e:
logger.error(f"Error calculating spatial diversity: {str(e)}")
logger.error(traceback.format_exc())
return 0
def get_complexity_threshold(self, scene_type: str) -> float:
"""
根據場景類型返回適當的複雜度閾值
平衡不同場景的區域劃分需求
Args:
scene_type: 場景類型
Returns:
複雜度閾值 (0.0-1.0)
"""
try:
# 較簡單場景需要較高分數才進行區域劃分
# 這些場景通常功能較為單純,不太需要細分
simple_scenes = ["bedroom", "bathroom", "closet"]
# 較複雜場景可以較低分數進行區域劃分
# 這些場景通常有多種功能,適合劃分不同區域
complex_scenes = ["living_room", "kitchen", "office_workspace", "dining_area"]
if scene_type in simple_scenes:
threshold = 0.65 # 較高閾值,避免過度細分
logger.debug(f"Using high threshold {threshold} for simple scene: {scene_type}")
elif scene_type in complex_scenes:
threshold = 0.45 # 較低閾值,允許合理劃分
logger.debug(f"Using low threshold {threshold} for complex scene: {scene_type}")
else:
threshold = 0.55 # 中等閾值,平衡策略
logger.debug(f"Using medium threshold {threshold} for scene: {scene_type}")
return threshold
except Exception as e:
logger.error(f"Error getting complexity threshold for scene '{scene_type}': {str(e)}")
logger.error(traceback.format_exc())
return 0.55 # 預設中等閾值
def analyze_object_clustering(self, detected_objects: List[Dict]) -> Dict:
"""
分析物件的聚集模式
識別物件是否形成明顯的聚集群組,這有助於功能區域的劃分
Args:
detected_objects: 檢測到的物件列表
Returns:
包含聚集分析結果的字典
"""
try:
clustering_result = {
"has_clusters": False,
"cluster_count": 0,
"cluster_regions": [],
"clustering_score": 0.0
}
if len(detected_objects) < 3:
logger.info("Insufficient objects for clustering analysis")
return clustering_result
# 統計每個區域的物件數量
region_counts = {}
for obj in detected_objects:
region = obj.get("region", "unknown")
region_counts[region] = region_counts.get(region, 0) + 1
# 找出有顯著物件聚集的區域(物件數量 >= 2)
significant_regions = [region for region, count in region_counts.items() if count >= 2]
# 計算聚集:聚集區域數量與總區域數量的比例
total_regions_with_objects = len([count for count in region_counts.values() if count > 0])
clustering_score = len(significant_regions) / max(total_regions_with_objects, 1)
clustering_result.update({
"has_clusters": len(significant_regions) >= 2,
"cluster_count": len(significant_regions),
"cluster_regions": significant_regions,
"clustering_score": clustering_score
})
logger.info(f"Object clustering analysis: {len(significant_regions)} clusters found in regions {significant_regions}")
return clustering_result
except Exception as e:
logger.error(f"Error analyzing object clustering: {str(e)}")
logger.error(traceback.format_exc())
return {
"has_clusters": False,
"cluster_count": 0,
"cluster_regions": [],
"clustering_score": 0.0
}
|