Spaces:
Running
on
Zero
Running
on
Zero
| import logging | |
| import traceback | |
| from typing import Dict, Any, Optional | |
| class ConfidenceManager: | |
| """ | |
| 專門管理信心度相關邏輯,包括動態閾值調整、信心度乘數管理和地標類型特定的閾值處理 | |
| """ | |
| def __init__(self): | |
| """ | |
| 初始化置信度管理器 | |
| """ | |
| self.logger = logging.getLogger(__name__) | |
| # 初始化批處理參數 | |
| self.batch_size = 16 # 默認批處理大小 | |
| # 置信度閾值乘數配置 | |
| self.confidence_threshold_multipliers = { | |
| "close_up": 0.9, # 近景標準閾值 | |
| "partial": 0.6, # 部分可見降低閾值要求 | |
| "distant": 0.5, # 遠景更低閾值要求 | |
| "full_image": 0.7 # 整張圖像需要更高閾值 | |
| } | |
| # 地標類型閾值配置 | |
| self.landmark_type_thresholds = { | |
| "tower": 0.5, # 塔型建築需要更高閾值 | |
| "skyscraper": 0.4, # 摩天大樓使用較低閾值 | |
| "building": 0.55, # 一般的建築物閾值略微降低 | |
| "monument": 0.5, # 紀念碑閾值 | |
| "natural": 0.6 # 自然景觀可以使用較低閾值 | |
| } | |
| def set_batch_size(self, batch_size: int): | |
| """ | |
| 設置批處理大小 | |
| Args: | |
| batch_size: 新的批處理大小 | |
| """ | |
| self.batch_size = max(1, batch_size) | |
| self.logger.info(f"Batch size set to {self.batch_size}") | |
| def adjust_confidence_threshold(self, detection_type: str, multiplier: float): | |
| """ | |
| 調整特定檢測類型的信心度的threshold | |
| Args: | |
| detection_type: 檢測類型 ('close_up', 'partial', 'distant', 'full_image') | |
| multiplier: 置信度閾值乘數 | |
| """ | |
| if detection_type in self.confidence_threshold_multipliers: | |
| self.confidence_threshold_multipliers[detection_type] = max(0.1, min(1.5, multiplier)) | |
| self.logger.info(f"Adjusted confidence threshold multiplier for {detection_type} to {multiplier}") | |
| else: | |
| self.logger.warning(f"Unknown detection type: {detection_type}") | |
| def get_detection_type_multiplier(self, detection_type: str) -> float: | |
| """ | |
| 獲取檢測類型的置信度乘數 | |
| Args: | |
| detection_type: 檢測類型 | |
| Returns: | |
| float: 置信度乘數 | |
| """ | |
| return self.confidence_threshold_multipliers.get(detection_type, 1.0) | |
| def get_landmark_type_threshold(self, landmark_type: str) -> float: | |
| """ | |
| 獲取地標類型的閾值 | |
| Args: | |
| landmark_type: 地標類型 | |
| Returns: | |
| float: 地標類型閾值 | |
| """ | |
| return self.landmark_type_thresholds.get(landmark_type, 0.5) | |
| def calculate_adjusted_threshold(self, base_threshold: float, detection_type: str) -> float: | |
| """ | |
| 根據檢測類型計算調整後的閾值 | |
| Args: | |
| base_threshold: 基礎閾值 | |
| detection_type: 檢測type | |
| Returns: | |
| float: 調整後的閾值 | |
| """ | |
| try: | |
| base_multiplier = self.get_detection_type_multiplier(detection_type) | |
| adjusted_threshold = base_threshold * base_multiplier | |
| return adjusted_threshold | |
| except Exception as e: | |
| self.logger.error(f"Error calculating adjusted threshold: {e}") | |
| self.logger.error(traceback.format_exc()) | |
| return base_threshold | |
| def calculate_final_threshold(self, base_threshold: float, detection_type: str, | |
| landmark_type: str) -> float: | |
| """ | |
| 計算最終閾值,結合檢測類型和地標類型 | |
| Args: | |
| base_threshold: 基礎閾值 | |
| detection_type: 檢測type | |
| landmark_type: 地標type | |
| Returns: | |
| float: 最終閾值 | |
| """ | |
| try: | |
| # 根據檢測類型調整 | |
| adjusted_threshold = self.calculate_adjusted_threshold(base_threshold, detection_type) | |
| # 根據地標類型進一步調整 | |
| if landmark_type == "distinctive": | |
| # 特殊建築的閾值降低25% | |
| type_multiplier = 0.75 | |
| else: | |
| # 使用已有的類型閾值 | |
| type_multiplier = self.get_landmark_type_threshold(landmark_type) / 0.5 | |
| final_threshold = adjusted_threshold * type_multiplier | |
| return final_threshold | |
| except Exception as e: | |
| self.logger.error(f"Error calculating final threshold: {e}") | |
| self.logger.error(traceback.format_exc()) | |
| return base_threshold | |
| def evaluate_confidence(self, confidence: float, threshold: float) -> bool: | |
| """ | |
| 評估置信度是否達到閾值 | |
| Args: | |
| confidence: 信心度score | |
| threshold: 閾值 | |
| Returns: | |
| bool: 是否達到閾值 | |
| """ | |
| return confidence >= threshold | |
| def apply_architectural_boost(self, confidence: float, architectural_analysis: Dict[str, Any], | |
| landmark_id: str) -> float: | |
| """ | |
| 根據建築特徵分析調整信心度 | |
| Args: | |
| confidence: 原始置信度 | |
| architectural_analysis: 建築特徵分析結果 | |
| landmark_id: 地標ID | |
| Returns: | |
| float: 調整後的信心度 | |
| """ | |
| try: | |
| confidence_boost = 0 | |
| landmark_id_lower = landmark_id.lower() | |
| top_features = architectural_analysis.get("architectural_features", []) | |
| primary_category = architectural_analysis.get("primary_category", "") | |
| # 使用主要建築類別來調整置信度,使用通用條件而非特定地標名稱 | |
| if primary_category == "tower" and any(term in landmark_id_lower for term in ["tower", "spire", "needle"]): | |
| confidence_boost += 0.05 | |
| elif primary_category == "skyscraper" and any(term in landmark_id_lower for term in ["building", "skyscraper", "tall"]): | |
| confidence_boost += 0.05 | |
| elif primary_category == "historical" and any(term in landmark_id_lower for term in ["monument", "castle", "palace", "temple"]): | |
| confidence_boost += 0.05 | |
| elif primary_category == "distinctive" and any(term in landmark_id_lower for term in ["unusual", "unique", "special", "famous"]): | |
| confidence_boost += 0.05 | |
| # 根據特定特徵進一步微調,使用通用特徵描述而非特定地標 | |
| for feature, score in top_features: | |
| if feature == "time_display" and "clock" in landmark_id_lower: | |
| confidence_boost += 0.03 | |
| elif feature == "segmented_exterior" and "segmented" in landmark_id_lower: | |
| confidence_boost += 0.03 | |
| elif feature == "slanted_design" and "leaning" in landmark_id_lower: | |
| confidence_boost += 0.03 | |
| # 應用信心度調整 | |
| if confidence_boost > 0: | |
| adjusted_confidence = confidence + confidence_boost | |
| self.logger.info(f"Boosted confidence by {confidence_boost:.2f} based on architectural features ({primary_category})") | |
| return adjusted_confidence | |
| return confidence | |
| except Exception as e: | |
| self.logger.error(f"Error applying architectural boost: {e}") | |
| self.logger.error(traceback.format_exc()) | |
| return confidence | |
| def determine_detection_type_from_region(self, region_width: int, region_height: int, | |
| image_width: int, image_height: int) -> str: | |
| """ | |
| 根據區域大小自動判斷檢測類型 | |
| Args: | |
| region_width: 區域寬度 | |
| region_height: 區域高度 | |
| image_width: 圖像寬度 | |
| image_height: 圖像高度 | |
| Returns: | |
| str: 檢測類型 | |
| """ | |
| try: | |
| region_area_ratio = (region_width * region_height) / (image_width * image_height) | |
| if region_area_ratio > 0.5: | |
| return "close_up" | |
| elif region_area_ratio > 0.2: | |
| return "partial" | |
| else: | |
| return "distant" | |
| except Exception as e: | |
| self.logger.error(f"Error determining detection type from region: {e}") | |
| self.logger.error(traceback.format_exc()) | |
| return "partial" | |
| def adjust_detection_type_by_viewpoint(self, detection_type: str, dominant_viewpoint: str) -> str: | |
| """ | |
| 根據視角調整檢測類型 | |
| Args: | |
| detection_type: 原始檢測類型 | |
| dominant_viewpoint: 主要視角 | |
| Returns: | |
| str: 調整後的檢測類型 | |
| """ | |
| try: | |
| if dominant_viewpoint == "close_up" and detection_type != "close_up": | |
| return "close_up" | |
| elif dominant_viewpoint == "distant" and detection_type != "distant": | |
| return "distant" | |
| elif dominant_viewpoint == "angled_view": | |
| return "partial" # 角度視圖可能是部分可見 | |
| else: | |
| return detection_type | |
| except Exception as e: | |
| self.logger.error(f"Error adjusting detection type by viewpoint: {e}") | |
| self.logger.error(traceback.format_exc()) | |
| return detection_type | |
| def get_batch_size(self) -> int: | |
| """ | |
| 獲取當前批處理大小 | |
| Returns: | |
| int: 批處理大小 | |
| """ | |
| return self.batch_size | |
| def get_all_threshold_multipliers(self) -> Dict[str, float]: | |
| """ | |
| 獲取所有置信度閾值乘數 | |
| Returns: | |
| Dict[str, float]: 閾值乘數字典 | |
| """ | |
| return self.confidence_threshold_multipliers.copy() | |
| def get_all_landmark_type_thresholds(self) -> Dict[str, float]: | |
| """ | |
| 獲取所有地標類型閾值 | |
| Returns: | |
| Dict[str, float]: 地標類型閾值字典 | |
| """ | |
| return self.landmark_type_thresholds.copy() | |