Spaces:
Running
on
Zero
Running
on
Zero
import logging | |
import traceback | |
import numpy as np | |
from typing import Dict, List, Any, Optional | |
logger = logging.getLogger(__name__) | |
class SpecializedSceneProcessor: | |
""" | |
負責處理特殊場景類型和地標識別 | |
包含亞洲文化場景、高級餐飲、金融區、空中視角等專門處理邏輯 | |
""" | |
def __init__(self): | |
"""初始化特殊場景處理器""" | |
try: | |
logger.info("SpecializedSceneProcessor initialized successfully") | |
except Exception as e: | |
logger.error(f"Failed to initialize SpecializedSceneProcessor: {str(e)}") | |
logger.error(traceback.format_exc()) | |
raise | |
def identify_aerial_intersection_features(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
空中視角十字路口特徵 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
十字路口特徵區域字典 | |
""" | |
try: | |
zones = {} | |
# 檢查交通信號 | |
traffic_light_objs = [obj for obj in detected_objects if obj["class_id"] == 9] | |
if traffic_light_objs: | |
zones["traffic_control_pattern"] = { | |
"region": "intersection", | |
"objects": ["traffic light"] * len(traffic_light_objs), | |
"description": f"Intersection traffic control with {len(traffic_light_objs)} signals visible from above" | |
} | |
# 人行道從空中視角的情境推斷 | |
zones["crossing_pattern"] = { | |
"region": "central", | |
"objects": ["inferred crosswalk"], | |
"description": "Crossing pattern visible from aerial perspective" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying aerial intersection features: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_aerial_plaza_features(self, people_objs: List[Dict]) -> Dict: | |
""" | |
識別空中視角廣場特徵 | |
Args: | |
people_objs: 行人物件列表 | |
Returns: | |
廣場特徵區域字典 | |
""" | |
try: | |
zones = {} | |
if people_objs: | |
# 檢查人群是否聚集在中央區域 | |
central_people = [obj for obj in people_objs | |
if "middle" in obj["region"]] | |
if central_people: | |
zones["central_gathering"] = { | |
"region": "middle_center", | |
"objects": ["person"] * len(central_people), | |
"description": f"Central plaza gathering area with {len(central_people)} people viewed from above" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying aerial plaza features: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_asian_pedestrian_pathway(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
亞洲文化場景中的行人通道 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
行人通道區域字典 | |
""" | |
try: | |
zones = {} | |
pathway_items = [] | |
pathway_regions = {} | |
# 提取人群用於通道分析 | |
people_objs = [obj for obj in detected_objects if obj["class_id"] == 0] | |
# 分析人群是否形成線形(商業街的特徵) | |
people_positions = [obj["normalized_center"] for obj in people_objs] | |
structured_path = False | |
path_direction = "meandering" | |
if len(people_positions) >= 3: | |
# 檢查人群是否沿相似y坐標排列(水平路徑) | |
y_coords = [pos[1] for pos in people_positions] | |
y_mean = sum(y_coords) / len(y_coords) | |
y_variance = sum((y - y_mean)**2 for y in y_coords) / len(y_coords) | |
horizontal_path = y_variance < 0.05 # 低變異表示水平對齊 | |
# 檢查人群是否沿相似x坐標排列(垂直路徑) | |
x_coords = [pos[0] for pos in people_positions] | |
x_mean = sum(x_coords) / len(x_coords) | |
x_variance = sum((x - x_mean)**2 for x in x_coords) / len(x_coords) | |
vertical_path = x_variance < 0.05 # 低變異表示垂直對齊 | |
structured_path = horizontal_path or vertical_path | |
path_direction = "horizontal" if horizontal_path else "vertical" if vertical_path else "meandering" | |
# 收集通道物件(人、自行車、摩托車在中間區域) | |
for obj in detected_objects: | |
if obj["class_id"] in [0, 1, 3]: # Person, bicycle, motorcycle | |
y_pos = obj["normalized_center"][1] | |
# 按垂直位置分組(圖像中間可能是通道) | |
if 0.25 <= y_pos <= 0.75: | |
region = obj["region"] | |
if region not in pathway_regions: | |
pathway_regions[region] = [] | |
pathway_regions[region].append(obj) | |
pathway_items.append(obj["class_name"]) | |
if pathway_items: | |
path_desc = "Pedestrian walkway with people moving through the commercial area" | |
if structured_path: | |
path_desc = f"{path_direction.capitalize()} pedestrian walkway with organized foot traffic" | |
zones["pedestrian_pathway"] = { | |
"region": "middle_center", # 通道通常會在中間area | |
"objects": list(set(pathway_items)), | |
"description": path_desc | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying Asian pedestrian pathway: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_vendor_zones(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
識別攤販區域 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
攤販區域字典 | |
""" | |
try: | |
zones = {} | |
# 識別攤販區域(小攤/商店 - 從情境推斷) | |
has_small_objects = any(obj["class_id"] in [24, 26, 39, 41] for obj in detected_objects) # bags, bottles, cups | |
has_people = any(obj["class_id"] == 0 for obj in detected_objects) | |
if has_small_objects and has_people: | |
# 可能的攤販區域是人群和小物件聚集的地方 | |
small_obj_regions = {} | |
for obj in detected_objects: | |
if obj["class_id"] in [24, 26, 39, 41, 67]: # bags, bottles, cups, phones | |
region = obj["region"] | |
if region not in small_obj_regions: | |
small_obj_regions[region] = [] | |
small_obj_regions[region].append(obj) | |
if small_obj_regions: | |
main_vendor_region = max(small_obj_regions.items(), | |
key=lambda x: len(x[1]), | |
default=(None, [])) | |
if main_vendor_region[0] is not None: | |
vendor_items = [obj["class_name"] for obj in main_vendor_region[1]] | |
zones["vendor_zone"] = { | |
"region": main_vendor_region[0], | |
"objects": list(set(vendor_items)), | |
"description": "Vendor or market stall area with small merchandise" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying vendor zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_upscale_decorative_zones(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
識別高級餐飲的裝飾區域 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
裝飾區域字典 | |
""" | |
try: | |
zones = {} | |
decor_items = [] | |
decor_regions = {} | |
# 尋找裝飾元素(花瓶、酒杯、未使用的餐具) | |
for obj in detected_objects: | |
if obj["class_id"] in [75, 40]: # Vase, wine glass | |
region = obj["region"] | |
if region not in decor_regions: | |
decor_regions[region] = [] | |
decor_regions[region].append(obj) | |
decor_items.append(obj["class_name"]) | |
if decor_items: | |
main_decor_region = max(decor_regions.items(), | |
key=lambda x: len(x[1]), | |
default=(None, [])) | |
if main_decor_region[0] is not None: | |
zones["decorative_zone"] = { | |
"region": main_decor_region[0], | |
"objects": list(set(decor_items)), | |
"description": f"Decorative area with {', '.join(list(set(decor_items)))}" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying upscale decorative zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_dining_seating_zones(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
識別餐廳座位安排區域 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
座位區域字典 | |
""" | |
try: | |
zones = {} | |
# 識別座位安排區域 | |
chairs = [obj for obj in detected_objects if obj["class_id"] == 56] # chairs | |
if len(chairs) >= 2: | |
chair_regions = {} | |
for obj in chairs: | |
region = obj["region"] | |
if region not in chair_regions: | |
chair_regions[region] = [] | |
chair_regions[region].append(obj) | |
if chair_regions: | |
main_seating_region = max(chair_regions.items(), | |
key=lambda x: len(x[1]), | |
default=(None, [])) | |
if main_seating_region[0] is not None: | |
zones["dining_seating_zone"] = { | |
"region": main_seating_region[0], | |
"objects": ["chair"] * len(main_seating_region[1]), | |
"description": f"Formal dining seating arrangement with {len(main_seating_region[1])} chairs" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying dining seating zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_serving_zones(self, detected_objects: List[Dict], existing_zones: Dict) -> Dict: | |
""" | |
識別服務區域 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
existing_zones: 已存在的功能區域 | |
Returns: | |
服務區域字典 | |
""" | |
try: | |
zones = {} | |
serving_items = [] | |
serving_regions = {} | |
# 服務區域可能有瓶子、碗、容器 | |
for obj in detected_objects: | |
if obj["class_id"] in [39, 45]: # Bottle, bowl | |
# 檢查是否在與主餐桌不同的區域 | |
if "formal_dining_zone" in existing_zones and obj["region"] != existing_zones["formal_dining_zone"]["region"]: | |
region = obj["region"] | |
if region not in serving_regions: | |
serving_regions[region] = [] | |
serving_regions[region].append(obj) | |
serving_items.append(obj["class_name"]) | |
if serving_items: | |
main_serving_region = max(serving_regions.items(), | |
key=lambda x: len(x[1]), | |
default=(None, [])) | |
if main_serving_region[0] is not None: | |
zones["serving_zone"] = { | |
"region": main_serving_region[0], | |
"objects": list(set(serving_items)), | |
"description": f"Serving or sideboard area with {', '.join(list(set(serving_items)))}" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying serving zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_building_zones(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
識別建築區域(從場景情境推斷) | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
建築區域字典 | |
""" | |
try: | |
zones = {} | |
# 側邊建築區域(從場景情境推斷) | |
# 檢查是否有實際可能包含建築物的區域 | |
left_side_regions = ["top_left", "middle_left", "bottom_left"] | |
right_side_regions = ["top_right", "middle_right", "bottom_right"] | |
# 檢查左側 | |
left_building_evidence = True | |
for region in left_side_regions: | |
# 如果此區域有很多車輛或人群,不太可能是建築物 | |
vehicle_in_region = any(obj["region"] == region and obj["class_id"] in [1, 2, 3, 5, 7] | |
for obj in detected_objects) | |
people_in_region = any(obj["region"] == region and obj["class_id"] == 0 | |
for obj in detected_objects) | |
if vehicle_in_region or people_in_region: | |
left_building_evidence = False | |
break | |
# 檢查右側 | |
right_building_evidence = True | |
for region in right_side_regions: | |
# 如果此區域有很多車輛或人群,不太可能是建築物 | |
vehicle_in_region = any(obj["region"] == region and obj["class_id"] in [1, 2, 3, 5, 7] | |
for obj in detected_objects) | |
people_in_region = any(obj["region"] == region and obj["class_id"] == 0 | |
for obj in detected_objects) | |
if vehicle_in_region or people_in_region: | |
right_building_evidence = False | |
break | |
# 如果證據支持,添加建築區域 | |
if left_building_evidence: | |
zones["building_zone_left"] = { | |
"region": "middle_left", | |
"objects": ["building"], # 推斷 | |
"description": "Tall buildings line the left side of the street" | |
} | |
if right_building_evidence: | |
zones["building_zone_right"] = { | |
"region": "middle_right", | |
"objects": ["building"], # 推斷 | |
"description": "Tall buildings line the right side of the street" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying building zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def identify_financial_pedestrian_zones(self, detected_objects: List[Dict]) -> Dict: | |
""" | |
識別金融區的行人區域 | |
Args: | |
detected_objects: 檢測到的物件列表 | |
Returns: | |
行人區域字典 | |
""" | |
try: | |
zones = {} | |
# 辨識行人區域(如果有人群) | |
people_objs = [obj for obj in detected_objects if obj["class_id"] == 0] | |
if people_objs: | |
people_regions = {} | |
for obj in people_objs: | |
region = obj["region"] | |
if region not in people_regions: | |
people_regions[region] = [] | |
people_regions[region].append(obj) | |
if people_regions: | |
main_pedestrian_region = max(people_regions.items(), | |
key=lambda x: len(x[1]), | |
default=(None, [])) | |
if main_pedestrian_region[0] is not None: | |
zones["pedestrian_zone"] = { | |
"region": main_pedestrian_region[0], | |
"objects": ["person"] * len(main_pedestrian_region[1]), | |
"description": f"Pedestrian area with {len(main_pedestrian_region[1])} people navigating the financial district" | |
} | |
return zones | |
except Exception as e: | |
logger.error(f"Error identifying financial pedestrian zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |
def create_landmark_auxiliary_zones(self, landmark: Dict, index: int) -> Dict: | |
""" | |
創建地標相關的輔助區域(攝影區、紀念品區等) | |
Args: | |
landmark: 地標物件字典 | |
index: 地標索引 | |
Returns: | |
輔助區域字典 | |
""" | |
try: | |
auxiliary_zones = {} | |
landmark_region = landmark.get("region", "middle_center") | |
landmark_name = landmark.get("class_name", "Landmark") | |
# 創建攝影區 | |
# 根據地標位置調整攝影區位置(地標前方通常是攝影區) | |
region_mapping = { | |
"top_left": "bottom_right", | |
"top_center": "bottom_center", | |
"top_right": "bottom_left", | |
"middle_left": "middle_right", | |
"middle_center": "bottom_center", | |
"middle_right": "middle_left", | |
"bottom_left": "top_right", | |
"bottom_center": "top_center", | |
"bottom_right": "top_left" | |
} | |
photo_region = region_mapping.get(landmark_region, landmark_region) | |
photo_key = f"{landmark_name.lower().replace(' ', '_')}_photography_spot" | |
auxiliary_zones[photo_key] = { | |
"name": f"{landmark_name} Photography Spot", | |
"description": f"Popular position for photographing {landmark_name} with optimal viewing angle.", | |
"objects": ["camera", "person", "cell phone"], | |
"region": photo_region, | |
"primary_function": "Tourist photography" | |
} | |
# 如果是著名地標,可能有紀念品販售區 | |
if landmark.get("confidence", 0) > 0.7: # 高置信度地標更可能有紀念品區 | |
# 根據地標位置找到適合的紀念品區位置(通常在地標附近但不直接在地標上) | |
adjacent_regions = { | |
"top_left": ["top_center", "middle_left"], | |
"top_center": ["top_left", "top_right"], | |
"top_right": ["top_center", "middle_right"], | |
"middle_left": ["top_left", "bottom_left"], | |
"middle_center": ["middle_left", "middle_right"], | |
"middle_right": ["top_right", "bottom_right"], | |
"bottom_left": ["middle_left", "bottom_center"], | |
"bottom_center": ["bottom_left", "bottom_right"], | |
"bottom_right": ["bottom_center", "middle_right"] | |
} | |
if landmark_region in adjacent_regions: | |
souvenir_region = adjacent_regions[landmark_region][0] # 選擇第一個相鄰區域 | |
souvenir_key = f"{landmark_name.lower().replace(' ', '_')}_souvenir_area" | |
auxiliary_zones[souvenir_key] = { | |
"name": f"{landmark_name} Souvenir Area", | |
"description": f"Area where visitors can purchase souvenirs and memorabilia related to {landmark_name}.", | |
"objects": ["person", "handbag", "backpack"], | |
"region": souvenir_region, | |
"primary_function": "Tourism commerce" | |
} | |
return auxiliary_zones | |
except Exception as e: | |
logger.error(f"Error creating landmark auxiliary zones: {str(e)}") | |
logger.error(traceback.format_exc()) | |
return {} | |