Spaces:
Running
on
Zero
Running
on
Zero
File size: 11,558 Bytes
12d9ea9 acb9007 12d9ea9 acb9007 12d9ea9 acb9007 12d9ea9 acb9007 12d9ea9 acb9007 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 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 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
import logging
import traceback
from typing import Dict, List, Any, Optional
logger = logging.getLogger(__name__)
class FunctionalZoneDetector:
"""
負責基於物件關聯性的功能區域識別
處理物件組合分析和描述性區域命名
"""
def __init__(self):
"""初始化功能區域檢測器"""
try:
logger.info("FunctionalZoneDetector initialized successfully")
except Exception as e:
logger.error(f"Failed to initialize FunctionalZoneDetector: {str(e)}")
logger.error(traceback.format_exc())
raise
def identify_primary_functional_area(self, detected_objects: List[Dict]) -> Dict:
"""
識別主要功能區域,基於最強的物件關聯性組合
採用通用邏輯處理各種室內場景
Args:
detected_objects: 檢測到的物件列表
Returns:
主要功能區域字典或None
"""
try:
# 用餐區域檢測(桌椅組合)
dining_area = self.detect_functional_combination(
detected_objects,
primary_objects=[60], # dining table
supporting_objects=[56, 40, 41, 42, 43], # chair, wine glass, cup, fork, knife
min_supporting=2,
description_template="Dining area with table and seating arrangement"
)
if dining_area:
return dining_area
# 休息區域檢測(沙發電視組合或床)
seating_area = self.detect_functional_combination(
detected_objects,
primary_objects=[57, 59], # sofa, bed
supporting_objects=[62, 58, 56], # tv, potted plant, chair
min_supporting=1,
description_template="Seating and relaxation area"
)
if seating_area:
return seating_area
# 工作區域檢測(電子設備與家具組合)
work_area = self.detect_functional_combination(
detected_objects,
primary_objects=[63, 66], # laptop, keyboard
supporting_objects=[60, 56, 64], # dining table, chair, mouse
min_supporting=2,
description_template="Workspace area with electronics and furniture"
)
if work_area:
return work_area
return None
except Exception as e:
logger.error(f"Error identifying primary functional area: {str(e)}")
logger.error(traceback.format_exc())
return None
def identify_secondary_functional_area(self, detected_objects: List[Dict], existing_zones: Dict) -> Dict:
"""
識別次要功能區域,避免與主要區域重疊
Args:
detected_objects: 檢測到的物件列表
existing_zones: 已存在的功能區域
Returns:
次要功能區域字典或None
"""
try:
# 獲取已使用的區域
used_regions = set(zone.get("region") for zone in existing_zones.values())
# 裝飾區域檢測(植物集中區域)
decorative_area = self.detect_functional_combination(
detected_objects,
primary_objects=[58], # potted plant
supporting_objects=[75], # vase
min_supporting=0,
min_primary=3, # 至少需要3個植物
description_template="Decorative area with plants and ornamental items",
exclude_regions=used_regions
)
if decorative_area:
return decorative_area
# 儲存區域檢測(廚房電器組合)
storage_area = self.detect_functional_combination(
detected_objects,
primary_objects=[72, 68, 69], # refrigerator, microwave, oven
supporting_objects=[71], # sink
min_supporting=0,
min_primary=2,
description_template="Kitchen appliance and storage area",
exclude_regions=used_regions
)
if storage_area:
return storage_area
return None
except Exception as e:
logger.error(f"Error identifying secondary functional area: {str(e)}")
logger.error(traceback.format_exc())
return None
def detect_functional_combination(self, detected_objects: List[Dict], primary_objects: List[int],
supporting_objects: List[int], min_supporting: int,
description_template: str, min_primary: int = 1,
exclude_regions: set = None) -> Dict:
"""
通用的功能組合檢測方法
基於主要物件和支持物件的組合判斷功能區域
Args:
detected_objects: 檢測到的物件列表
primary_objects: 主要物件的class_id列表
supporting_objects: 支持物件的class_id列表
min_supporting: 最少需要的支持物件數量
description_template: 描述模板
min_primary: 最少需要的主要物件數量
exclude_regions: 需要排除的區域集合
Returns:
功能區域資訊字典,如果不符合條件則返回None
"""
try:
if exclude_regions is None:
exclude_regions = set()
# 收集主要物件
primary_objs = [obj for obj in detected_objects
if obj.get("class_id") in primary_objects and obj.get("confidence", 0) >= 0.4]
# 收集支持物件
supporting_objs = [obj for obj in detected_objects
if obj.get("class_id") in supporting_objects and obj.get("confidence", 0) >= 0.4]
# 檢查是否滿足最少數量要求
if len(primary_objs) < min_primary or len(supporting_objs) < min_supporting:
return None
# 按區域組織物件
region_combinations = {}
all_relevant_objs = primary_objs + supporting_objs
for obj in all_relevant_objs:
region = obj.get("region")
# 排除指定區域
if region in exclude_regions:
continue
if region not in region_combinations:
region_combinations[region] = {"primary": [], "supporting": [], "all": []}
region_combinations[region]["all"].append(obj)
if obj.get("class_id") in primary_objects:
region_combinations[region]["primary"].append(obj)
else:
region_combinations[region]["supporting"].append(obj)
# 找到最佳區域組合
best_region = None
best_score = 0
for region, objs in region_combinations.items():
# 計算該區域的評分
primary_count = len(objs["primary"])
supporting_count = len(objs["supporting"])
# 必須滿足最低要求
if primary_count < min_primary or supporting_count < min_supporting:
continue
# 計算組合評分(主要物件權重較高)
score = primary_count * 2 + supporting_count
if score > best_score:
best_score = score
best_region = region
if best_region is None:
return None
best_combination = region_combinations[best_region]
all_objects = [obj["class_name"] for obj in best_combination["all"]]
return {
"region": best_region,
"objects": all_objects,
"description": description_template
}
except Exception as e:
logger.error(f"Error detecting functional combination: {str(e)}")
logger.error(traceback.format_exc())
return None
def generate_descriptive_zone_key_from_data(self, zone_data: Dict, priority_level: str) -> str:
"""
基於區域與物品名產生一個比較有描述性的區域
Args:
zone_data: 區域數據字典
priority_level: 優先級別(primary/secondary)
Returns:
str: 描述性區域鍵名
"""
try:
objects = zone_data.get("objects", [])
region = zone_data.get("region", "")
description = zone_data.get("description", "")
# 基於物件內容確定功能類型
if any("dining" in obj.lower() or "table" in obj.lower() for obj in objects):
base_name = "dining area"
elif any("chair" in obj.lower() or "sofa" in obj.lower() for obj in objects):
base_name = "seating area"
elif any("bed" in obj.lower() for obj in objects):
base_name = "sleeping area"
elif any("laptop" in obj.lower() or "keyboard" in obj.lower() for obj in objects):
base_name = "workspace area"
elif any("plant" in obj.lower() or "vase" in obj.lower() for obj in objects):
base_name = "decorative area"
elif any("refrigerator" in obj.lower() or "microwave" in obj.lower() for obj in objects):
base_name = "kitchen area"
else:
# 基於描述內容推斷
if "dining" in description.lower():
base_name = "dining area"
elif "seating" in description.lower() or "relaxation" in description.lower():
base_name = "seating area"
elif "work" in description.lower():
base_name = "workspace area"
elif "decorative" in description.lower():
base_name = "decorative area"
else:
base_name = "functional area"
# 為次要區域添加位置標識以區分
if priority_level == "secondary" and region:
spatial_context = self.get_spatial_context_description(region)
if spatial_context:
return f"{spatial_context} {base_name}"
return base_name
except Exception as e:
logger.warning(f"Error generating descriptive zone key: {str(e)}")
return "activity area"
def get_spatial_context_description(self, region: str) -> str:
"""
獲取空間上下文描述
Args:
region: 區域位置標識
Returns:
str: 空間上下文描述
"""
try:
spatial_mapping = {
"top_left": "upper left",
"top_center": "upper",
"top_right": "upper right",
"middle_left": "left side",
"middle_center": "central",
"middle_right": "right side",
"bottom_left": "lower left",
"bottom_center": "lower",
"bottom_right": "lower right"
}
return spatial_mapping.get(region, "")
except Exception as e:
logger.warning(f"Error getting spatial context for region '{region}': {str(e)}")
return ""
|