File size: 10,293 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
274
275
276
277
278
279
280
281
282
283
284

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()