Sfoglia il codice sorgente

feat(performance_analyzer): 添加镜头统计信息并优化性能指标计算

在性能分析器中添加了针对每个镜头的报警统计信息,包括总报警数、误报数及误报率。同时优化了性能指标的计算逻辑,确保统计结果的准确性和完整性。
Hannnk 3 settimane fa
parent
commit
c7587ee62f

+ 109 - 0
Output/output_20250329_100448_results/performance_stats.txt

@@ -0,0 +1,109 @@
+检测性能统计报告
+==================================================
+
+详细统计信息:
+总样本数(CSV中唯一图像数): 32850
+检测到的目标总数: 444
+真实目标总数(TP): 220
+误报目标数(FP): 224
+真阴性数量(TN): 32406
+
+性能指标:
+准确率: 0.9932
+精确率: 0.4955
+召回率: 1.0000
+F1分数: 0.6627
+误报率(虚警率): 0.0069
+
+镜头统计信息:
+------------------------------
+镜头 cam_00:
+  总报警数: 14
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_01:
+  总报警数: 49
+  误报数: 30
+  误报率: 0.6122
+------------------------------
+镜头 cam_02:
+  总报警数: 42
+  误报数: 17
+  误报率: 0.4048
+------------------------------
+镜头 cam_03:
+  总报警数: 21
+  误报数: 4
+  误报率: 0.1905
+------------------------------
+镜头 cam_04:
+  总报警数: 42
+  误报数: 23
+  误报率: 0.5476
+------------------------------
+镜头 cam_05:
+  总报警数: 72
+  误报数: 70
+  误报率: 0.9722
+------------------------------
+镜头 cam_06:
+  总报警数: 38
+  误报数: 34
+  误报率: 0.8947
+------------------------------
+镜头 cam_07:
+  总报警数: 47
+  误报数: 9
+  误报率: 0.1915
+------------------------------
+镜头 cam_08:
+  总报警数: 8
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_09:
+  总报警数: 15
+  误报数: 4
+  误报率: 0.2667
+------------------------------
+镜头 cam_10:
+  总报警数: 15
+  误报数: 7
+  误报率: 0.4667
+------------------------------
+镜头 cam_11:
+  总报警数: 11
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_12:
+  总报警数: 8
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_13:
+  总报警数: 6
+  误报数: 1
+  误报率: 0.1667
+------------------------------
+镜头 cam_14:
+  总报警数: 33
+  误报数: 24
+  误报率: 0.7273
+------------------------------
+镜头 cam_15:
+  总报警数: 6
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_16:
+  总报警数: 10
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_17:
+  总报警数: 7
+  误报数: 1
+  误报率: 0.1429
+------------------------------

+ 89 - 0
Output/output_20250329_111006_results/performance_stats.txt

@@ -0,0 +1,89 @@
+检测性能统计报告
+==================================================
+
+详细统计信息:
+总样本数(CSV中唯一图像数): 8136
+检测到的目标总数: 109
+真实目标总数(TP): 39
+误报目标数(FP): 70
+真阴性数量(TN): 8027
+
+性能指标:
+准确率: 0.9914
+精确率: 0.3578
+召回率: 1.0000
+F1分数: 0.5270
+误报率(虚警率): 0.0086
+
+镜头统计信息:
+------------------------------
+镜头 cam_01:
+  总报警数: 7
+  误报数: 6
+  误报率: 0.8571
+------------------------------
+镜头 cam_02:
+  总报警数: 13
+  误报数: 7
+  误报率: 0.5385
+------------------------------
+镜头 cam_03:
+  总报警数: 26
+  误报数: 23
+  误报率: 0.8846
+------------------------------
+镜头 cam_04:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_05:
+  总报警数: 8
+  误报数: 8
+  误报率: 1.0000
+------------------------------
+镜头 cam_06:
+  总报警数: 4
+  误报数: 4
+  误报率: 1.0000
+------------------------------
+镜头 cam_07:
+  总报警数: 9
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_08:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_09:
+  总报警数: 1
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_10:
+  总报警数: 3
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_11:
+  总报警数: 3
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_14:
+  总报警数: 26
+  误报数: 22
+  误报率: 0.8462
+------------------------------
+镜头 cam_15:
+  总报警数: 3
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_17:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------

+ 88 - 0
Output/output_20250329_130338_results/performance_stats.txt

@@ -14,3 +14,91 @@
 召回率: 1.0000
 F1分数: 0.4312
 误报率(虚警率): 0.0136
+
+镜头统计信息:
+------------------------------
+镜头 cam_00:
+  总报警数: 5
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_01:
+  总报警数: 48
+  误报数: 32
+  误报率: 0.6667
+------------------------------
+镜头 cam_02:
+  总报警数: 76
+  误报数: 59
+  误报率: 0.7763
+------------------------------
+镜头 cam_03:
+  总报警数: 20
+  误报数: 11
+  误报率: 0.5500
+------------------------------
+镜头 cam_04:
+  总报警数: 115
+  误报数: 95
+  误报率: 0.8261
+------------------------------
+镜头 cam_05:
+  总报警数: 110
+  误报数: 110
+  误报率: 1.0000
+------------------------------
+镜头 cam_06:
+  总报警数: 117
+  误报数: 115
+  误报率: 0.9829
+------------------------------
+镜头 cam_07:
+  总报警数: 45
+  误报数: 10
+  误报率: 0.2222
+------------------------------
+镜头 cam_08:
+  总报警数: 10
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_09:
+  总报警数: 16
+  误报数: 13
+  误报率: 0.8125
+------------------------------
+镜头 cam_10:
+  总报警数: 15
+  误报数: 9
+  误报率: 0.6000
+------------------------------
+镜头 cam_11:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_13:
+  总报警数: 9
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_14:
+  总报警数: 22
+  误报数: 13
+  误报率: 0.5909
+------------------------------
+镜头 cam_15:
+  总报警数: 8
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_16:
+  总报警数: 13
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_17:
+  总报警数: 13
+  误报数: 0
+  误报率: 0.0000
+------------------------------

+ 16 - 0
Output/output_20250329_133810_results/performance_stats.txt

@@ -0,0 +1,16 @@
+检测性能统计报告
+==================================================
+
+详细统计信息:
+总样本数(CSV中唯一图像数): 36540
+检测到的目标总数: 347
+真实目标总数(TP): 111
+误报目标数(FP): 236
+真阴性数量(TN): 36193
+
+性能指标:
+准确率: 0.9935
+精确率: 0.3199
+召回率: 1.0000
+F1分数: 0.4847
+误报率(虚警率): 0.0065

+ 0 - 134
Output/output_20250329_140816_results/analysis_report.txt

@@ -1,134 +0,0 @@
-摄像头检测分析报告
-=====================
-
-各摄像头目标数量统计:
-摄像头 00: 11 个目标
-摄像头 01: 60 个目标
-摄像头 02: 36 个目标
-摄像头 03: 22 个目标
-摄像头 04: 47 个目标
-摄像头 05: 77 个目标
-摄像头 06: 43 个目标
-摄像头 07: 29 个目标
-摄像头 08: 5 个目标
-摄像头 09: 13 个目标
-摄像头 10: 10 个目标
-摄像头 11: 5 个目标
-摄像头 13: 2 个目标
-摄像头 14: 8 个目标
-摄像头 15: 3 个目标
-摄像头 16: 6 个目标
-摄像头 17: 2 个目标
-
-确认阳性目标统计:
-摄像头 00: 11 个确认阳性目标
-摄像头 01: 19 个确认阳性目标
-摄像头 02: 23 个确认阳性目标
-摄像头 03: 15 个确认阳性目标
-摄像头 04: 29 个确认阳性目标
-摄像头 05: 12 个确认阳性目标
-摄像头 06: 21 个确认阳性目标
-摄像头 07: 26 个确认阳性目标
-摄像头 08: 5 个确认阳性目标
-摄像头 09: 11 个确认阳性目标
-摄像头 10: 4 个确认阳性目标
-摄像头 11: 5 个确认阳性目标
-摄像头 13: 2 个确认阳性目标
-摄像头 14: 3 个确认阳性目标
-摄像头 15: 3 个确认阳性目标
-摄像头 16: 6 个确认阳性目标
-摄像头 17: 2 个确认阳性目标
-
-真阳性/假阳性统计:
-摄像头 00:
-  总检测数: 11
-  真阳性数: 11 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 01:
-  总检测数: 60
-  真阳性数: 19 (31.67%)
-  假阳性数: 39 (65.00%)
-摄像头 02:
-  总检测数: 36
-  真阳性数: 23 (63.89%)
-  假阳性数: 7 (19.44%)
-摄像头 03:
-  总检测数: 22
-  真阳性数: 15 (68.18%)
-  假阳性数: 5 (22.73%)
-摄像头 04:
-  总检测数: 47
-  真阳性数: 29 (61.70%)
-  假阳性数: 14 (29.79%)
-摄像头 05:
-  总检测数: 77
-  真阳性数: 12 (15.58%)
-  假阳性数: 61 (79.22%)
-摄像头 06:
-  总检测数: 43
-  真阳性数: 21 (48.84%)
-  假阳性数: 22 (51.16%)
-摄像头 07:
-  总检测数: 29
-  真阳性数: 26 (89.66%)
-  假阳性数: 3 (10.34%)
-摄像头 08:
-  总检测数: 5
-  真阳性数: 5 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 09:
-  总检测数: 13
-  真阳性数: 11 (84.62%)
-  假阳性数: 2 (15.38%)
-摄像头 10:
-  总检测数: 10
-  真阳性数: 4 (40.00%)
-  假阳性数: 6 (60.00%)
-摄像头 11:
-  总检测数: 5
-  真阳性数: 5 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 13:
-  总检测数: 2
-  真阳性数: 2 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 14:
-  总检测数: 8
-  真阳性数: 3 (37.50%)
-  假阳性数: 5 (62.50%)
-摄像头 15:
-  总检测数: 3
-  真阳性数: 3 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 16:
-  总检测数: 6
-  真阳性数: 6 (100.00%)
-  假阳性数: 0 (0.00%)
-摄像头 17:
-  总检测数: 2
-  真阳性数: 2 (100.00%)
-  假阳性数: 0 (0.00%)
-
-目标平均尺寸统计:
-摄像头 00: 平均宽度 104.0px, 平均高度 48.45px
-摄像头 01: 平均宽度 297.6px, 平均高度 145.41px
-摄像头 02: 平均宽度 116.57px, 平均高度 68.8px
-摄像头 03: 平均宽度 156.0px, 平均高度 81.0px
-摄像头 04: 平均宽度 136.37px, 平均高度 76.95px
-摄像头 05: 平均宽度 225.97px, 平均高度 82.92px
-摄像头 06: 平均宽度 145.33px, 平均高度 53.05px
-摄像头 07: 平均宽度 88.79px, 平均高度 47.59px
-摄像头 08: 平均宽度 111.8px, 平均高度 52.4px
-摄像头 09: 平均宽度 104.77px, 平均高度 55.62px
-摄像头 10: 平均宽度 148.3px, 平均高度 75.5px
-摄像头 11: 平均宽度 245.0px, 平均高度 112.4px
-摄像头 13: 平均宽度 139.5px, 平均高度 83.5px
-摄像头 14: 平均宽度 116.62px, 平均高度 56.62px
-摄像头 15: 平均宽度 192.33px, 平均高度 134.33px
-摄像头 16: 平均宽度 150.33px, 平均高度 112.17px
-摄像头 17: 平均宽度 197.0px, 平均高度 149.5px
-
-总体统计:
-总检测数: 379
-总真阳性数: 197 (51.98%)
-总假阳性数: 164 (43.27%)

+ 88 - 0
Output/output_20250329_140816_results/performance_stats.txt

@@ -14,3 +14,91 @@
 召回率: 1.0000
 F1分数: 0.7038
 误报率(虚警率): 0.0053
+
+镜头统计信息:
+------------------------------
+镜头 cam_00:
+  总报警数: 11
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_01:
+  总报警数: 58
+  误报数: 39
+  误报率: 0.6724
+------------------------------
+镜头 cam_02:
+  总报警数: 30
+  误报数: 7
+  误报率: 0.2333
+------------------------------
+镜头 cam_03:
+  总报警数: 20
+  误报数: 5
+  误报率: 0.2500
+------------------------------
+镜头 cam_04:
+  总报警数: 43
+  误报数: 14
+  误报率: 0.3256
+------------------------------
+镜头 cam_05:
+  总报警数: 73
+  误报数: 62
+  误报率: 0.8493
+------------------------------
+镜头 cam_06:
+  总报警数: 43
+  误报数: 22
+  误报率: 0.5116
+------------------------------
+镜头 cam_07:
+  总报警数: 29
+  误报数: 3
+  误报率: 0.1034
+------------------------------
+镜头 cam_08:
+  总报警数: 5
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_09:
+  总报警数: 13
+  误报数: 2
+  误报率: 0.1538
+------------------------------
+镜头 cam_10:
+  总报警数: 10
+  误报数: 6
+  误报率: 0.6000
+------------------------------
+镜头 cam_11:
+  总报警数: 5
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_13:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_14:
+  总报警数: 8
+  误报数: 5
+  误报率: 0.6250
+------------------------------
+镜头 cam_15:
+  总报警数: 3
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_16:
+  总报警数: 6
+  误报数: 0
+  误报率: 0.0000
+------------------------------
+镜头 cam_17:
+  总报警数: 2
+  误报数: 0
+  误报率: 0.0000
+------------------------------

+ 61 - 28
src/analysis/performance_analyzer.py

@@ -27,38 +27,50 @@ class PerformanceAnalyzer:
         total_samples = len(df['Image File'].unique())
         
         # 初始化统计
-        stats = {
-            'TP': 0,  # 真阳性
-            'FP': 0,  # 假阳性
+        detection_stats = {
+            'TP': len(true_targets),  # 真阳性:targets_all_True文件夹中的所有文件
+            'FP': len(all_targets - true_targets),  # 假阳性:在targets_all中但不在targets_all_True中的文件
             'FN': 0,  # 假阴性
-            'TN': 0   # 真阴性
+            'TN': total_samples - (len(true_targets) + len(all_targets - true_targets))  # 真阴性:总样本数减去TP和FP
         }
         
-        # 计算真阳性(TP):targets_all_True文件夹中的所有文件
-        stats['TP'] = len(true_targets)
-        
-        # 计算假阳性(FP):在targets_all中但不在targets_all_True中的文件
-        stats['FP'] = len(all_targets - true_targets)
-        
-        # 计算真阴性(TN):总样本数减去TP和FP
-        stats['TN'] = total_samples - (stats['TP'] + stats['FP'])
-        
         # 计算性能指标
-        total = stats['TP'] + stats['FP'] + stats['TN']
-        accuracy = (stats['TP'] + stats['TN']) / total if total > 0 else 0
-        precision = stats['TP'] / (stats['TP'] + stats['FP']) if (stats['TP'] + stats['FP']) > 0 else 0
-        recall = stats['TP'] / (stats['TP'] + stats['FN']) if (stats['TP'] + stats['FN']) > 0 else 0
+        total = detection_stats['TP'] + detection_stats['FP'] + detection_stats['TN']
+        accuracy = (detection_stats['TP'] + detection_stats['TN']) / total if total > 0 else 0
+        precision = detection_stats['TP'] / (detection_stats['TP'] + detection_stats['FP']) if (detection_stats['TP'] + detection_stats['FP']) > 0 else 0
+        recall = detection_stats['TP'] / (detection_stats['TP'] + detection_stats['FN']) if (detection_stats['TP'] + detection_stats['FN']) > 0 else 0
         f1_score = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0
         # 计算误报率(虚警率):FP / (TN + FP)
-        false_alarm_rate = stats['FP'] / (stats['TN'] + stats['FP']) if (stats['TN'] + stats['FP']) > 0 else 0
+        false_alarm_rate = detection_stats['FP'] / (detection_stats['TN'] + detection_stats['FP']) if (detection_stats['TN'] + detection_stats['FP']) > 0 else 0
+        
+        # 统计每个镜头的报警数量
+        camera_stats = {}
+        for target_file in all_targets:
+            # 提取镜头编号(cam_xx)
+            parts = target_file.split('_')
+            camera_id = None
+            for i in range(len(parts)):
+                if parts[i] == 'cam' and i + 1 < len(parts):
+                    camera_id = f"cam_{parts[i+1]}"
+                    break
+            
+            if camera_id:
+                if camera_id not in camera_stats:
+                    camera_stats[camera_id] = {
+                        'total_alarms': 0,
+                        'false_alarms': 0
+                    }
+                camera_stats[camera_id]['total_alarms'] += 1
+                if target_file not in true_targets:
+                    camera_stats[camera_id]['false_alarms'] += 1
         
         # 打印详细统计信息
         print("\n详细统计信息:")
         print(f"总样本数(CSV中唯一图像数): {total_samples}")
         print(f"检测到的目标总数: {len(all_targets)}")
-        print(f"真实目标总数(TP): {len(true_targets)}")
-        print(f"误报目标数(FP): {len(all_targets - true_targets)}")
-        print(f"真阴性数量(TN): {stats['TN']}")
+        print(f"真实目标总数(TP): {detection_stats['TP']}")
+        print(f"误报目标数(FP): {detection_stats['FP']}")
+        print(f"真阴性数量(TN): {detection_stats['TN']}")
         
         # 保存统计结果到文件
         stats_file = os.path.join(self.result_dir, 'performance_stats.txt')
@@ -69,28 +81,39 @@ class PerformanceAnalyzer:
             f.write("详细统计信息:\n")
             f.write(f"总样本数(CSV中唯一图像数): {total_samples}\n")
             f.write(f"检测到的目标总数: {len(all_targets)}\n")
-            f.write(f"真实目标总数(TP): {len(true_targets)}\n")
-            f.write(f"误报目标数(FP): {len(all_targets - true_targets)}\n")
-            f.write(f"真阴性数量(TN): {stats['TN']}\n\n")
+            f.write(f"真实目标总数(TP): {detection_stats['TP']}\n")
+            f.write(f"误报目标数(FP): {detection_stats['FP']}\n")
+            f.write(f"真阴性数量(TN): {detection_stats['TN']}\n\n")
             
             f.write("性能指标:\n")
             f.write(f"准确率: {accuracy:.4f}\n")
             f.write(f"精确率: {precision:.4f}\n")
             f.write(f"召回率: {recall:.4f}\n")
             f.write(f"F1分数: {f1_score:.4f}\n")
-            f.write(f"误报率(虚警率): {false_alarm_rate:.4f}\n")
+            f.write(f"误报率(虚警率): {false_alarm_rate:.4f}\n\n")
+            
+            f.write("镜头统计信息:\n")
+            f.write("-" * 30 + "\n")
+            for camera_id, cam_stats in sorted(camera_stats.items()):
+                f.write(f"镜头 {camera_id}:\n")
+                f.write(f"  总报警数: {cam_stats['total_alarms']}\n")
+                f.write(f"  误报数: {cam_stats['false_alarms']}\n")
+                f.write(f"  误报率: {cam_stats['false_alarms']/cam_stats['total_alarms']:.4f}\n")
+                f.write("-" * 30 + "\n")
         
         print(f"\n统计结果已保存到: {stats_file}")
         
+        # 确保返回的字典结构正确
         return {
-            'stats': stats,
+            'stats': detection_stats,
             'metrics': {
                 'accuracy': accuracy,
                 'precision': precision,
                 'recall': recall,
                 'f1_score': f1_score,
                 'false_alarm_rate': false_alarm_rate
-            }
+            },
+            'camera_stats': camera_stats
         }
     
     def mark_true_targets(self, true_target_files: List[str]):
@@ -104,7 +127,7 @@ class PerformanceAnalyzer:
 
 def main():
     # 示例使用
-    result_dir = r"D:\PythonProject\Model\output_20250329_130338_results"
+    result_dir = r"D:\PythonProject\Model\Output\output_20250329_100448_results"
     analyzer = PerformanceAnalyzer(result_dir)
     
     # 分析性能
@@ -123,6 +146,16 @@ def main():
     print(f"召回率: {results['metrics']['recall']:.4f}")
     print(f"F1分数: {results['metrics']['f1_score']:.4f}")
     print(f"误报率(虚警率): {results['metrics']['false_alarm_rate']:.4f}")
+    
+    # 打印镜头统计信息
+    print("\n镜头统计信息:")
+    print("-" * 30)
+    for camera_id, stats in sorted(results['camera_stats'].items()):
+        print(f"镜头 {camera_id}:")
+        print(f"  总报警数: {stats['total_alarms']}")
+        print(f"  误报数: {stats['false_alarms']}")
+        print(f"  误报率: {stats['false_alarms']/stats['total_alarms']:.4f}")
+        print("-" * 30)
 
 if __name__ == '__main__':
     main()