4 コミット e192c19be2 ... 1a4d68d145

作者 SHA1 メッセージ 日付
  Hannnk 1a4d68d145 refactor: 优化代码结构并移除调试输出 2 週間 前
  Hannnk 52cb8328b8 chore: 更新.gitignore文件,移除Data/目录的斜杠 2 週間 前
  Hannnk 1fe7c1577c chore: 清理IDE配置文件和临时检测结果文件 2 週間 前
  Hannnk 1c06210aff feat: 添加多模型支持并优化推理流程 2 週間 前
41 ファイル変更646 行追加1216 行削除
  1. 3 2
      .gitignore
  2. 0 3
      .idea/.gitignore
  3. 0 10
      .idea/Model.iml
  4. 0 19
      .idea/inspectionProfiles/Project_Default.xml
  5. 0 6
      .idea/inspectionProfiles/profiles_settings.xml
  6. 0 4
      .idea/misc.xml
  7. 0 6
      .idea/vcs.xml
  8. 0 9
      .vscode/launch.json
  9. BIN
      Data/TEST_results/detection_report.xlsx
  10. 0 333
      Data/detection_0328_1004_results/detection_report.csv
  11. BIN
      Data/detection_0328_1004_results/detection_report.xlsx
  12. BIN
      Data/detection_0328_1024_results/detection_report.xlsx
  13. BIN
      Data/detection_0328_1055_results/detection_report.xlsx
  14. BIN
      Data/detection_0328_1115_results/detection_report.xlsx
  15. BIN
      Data/detection_0328_1455_results/detection_report.xlsx
  16. BIN
      Data/detection_0328_1537_results/detection_report.xlsx
  17. BIN
      Data/detection_0328_1612_results/detection_report.xlsx
  18. BIN
      Data/detection_0328_1735_results/detection_report.xlsx
  19. BIN
      Data/detection_0329_1004_results/detection_report.xlsx
  20. 0 114
      Output/output_20250328_173528_results/performance_stats.txt
  21. 0 114
      Output/output_20250329_100448_results/performance_stats.txt
  22. 0 94
      Output/output_20250329_111006_results/performance_stats.txt
  23. 0 109
      Output/output_20250329_130338_results/performance_stats.txt
  24. 0 109
      Output/output_20250329_133810_results/performance_stats.txt
  25. 0 109
      Output/output_20250329_140816_results/performance_stats.txt
  26. 269 2
      README.md
  27. BIN
      __pycache__/feature_extractor.cpython-39.pyc
  28. BIN
      __pycache__/inference.cpython-39.pyc
  29. BIN
      __pycache__/report_generator.cpython-39.pyc
  30. 6 4
      requirements.txt
  31. 4 0
      src/__init__.py
  32. 4 0
      src/analysis/__init__.py
  33. 1 1
      src/analysis/analysis_report.py
  34. 7 10
      src/core/ali_image_validation.py
  35. 4 9
      src/core/compare_outputs.py
  36. 6 6
      src/core/feature_extractor.py
  37. 5 8
      src/core/image_validation.py
  38. 3 3
      src/core/infer.py
  39. 329 120
      src/core/inference.py
  40. 3 6
      src/utils/split_dataset.py
  41. 2 6
      src/utils/update_labels.py

+ 3 - 2
.gitignore

@@ -21,7 +21,7 @@ wheels/
 *.egg
 
 # Virtual Environment
-venv/
+.venv/
 ENV/
 env/
 
@@ -33,7 +33,8 @@ env/
 
 # Project specific
 Output/
-Data/
+models/
+Data
 *.onnx
 *.pkl
 *.log

+ 0 - 3
.idea/.gitignore

@@ -1,3 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml

+ 0 - 10
.idea/Model.iml

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module version="4">
-  <component name="PyDocumentationSettings">
-    <option name="format" value="PLAIN" />
-    <option name="myDocStringFormat" value="Plain" />
-  </component>
-  <component name="TestRunnerService">
-    <option name="PROJECT_TEST_RUNNER" value="py.test" />
-  </component>
-</module>

+ 0 - 19
.idea/inspectionProfiles/Project_Default.xml

@@ -1,19 +0,0 @@
-<component name="InspectionProjectProfileManager">
-  <profile version="1.0">
-    <option name="myName" value="Project Default" />
-    <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
-      <option name="ignoredErrors">
-        <list>
-          <option value="N802" />
-        </list>
-      </option>
-    </inspection_tool>
-    <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
-      <option name="ignoredIdentifiers">
-        <list>
-          <option value="typing.SupportsAbs.*" />
-        </list>
-      </option>
-    </inspection_tool>
-  </profile>
-</component>

+ 0 - 6
.idea/inspectionProfiles/profiles_settings.xml

@@ -1,6 +0,0 @@
-<component name="InspectionProjectProfileManager">
-  <settings>
-    <option name="USE_PROJECT_PROFILE" value="false" />
-    <version value="1.0" />
-  </settings>
-</component>

+ 0 - 4
.idea/misc.xml

@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (Model)" project-jdk-type="Python SDK" />
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$" vcs="Git" />
-  </component>
-</project>

+ 0 - 9
.vscode/launch.json

@@ -1,9 +0,0 @@
-{
-    // 使用 IntelliSense 了解相关属性。 
-    // 悬停以查看现有属性的描述。
-    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
-    "version": "0.2.0",
-    "configurations": [
-    
-    ]
-}

BIN
Data/TEST_results/detection_report.xlsx


+ 0 - 333
Data/detection_0328_1004_results/detection_report.csv

@@ -1,333 +0,0 @@
-Image File,Object Count,Max Confidence,BBox Center X,BBox Center Y,BBox Width,BBox Height,Normalized Coordinates
-.\Data\detection_0328_1004\192_168_210_2_0_20250328102242.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_10_20250328102156.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_10_20250328102159.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_10_20250328102303.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_11_20250328102107.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_12_20250328102143.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_13_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_13_20250328102249.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_14_20250328102053.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_14_20250328102325.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_15_20250328102129.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_15_20250328102326.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_16_20250328102130.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_16_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_17_20250328102038.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_17_20250328102310.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_18_20250328102114.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_18_20250328102222.jpg,1,0.559019148349762,584.0,1453.5,82,47,"0.1521,0.6729,0.021354166666666667,0.02175925925925926"
-.\Data\detection_0328_1004\192_168_210_2_18_20250328102309.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_18_20250328102311.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_19_20250328102115.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_19_20250328102220.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_1_20250328102045.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_1_20250328102242.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_20_20250328102024.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_20_20250328102207.jpg,1,0.5469033122062683,3414.0,1316.5,80,43,"0.8891,0.6095,0.020833333333333332,0.01990740740740741"
-.\Data\detection_0328_1004\192_168_210_2_20_20250328102256.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_21_20250328102100.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_21_20250328102255.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_21_20250328102257.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_22_20250328102101.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_22_20250328102205.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_2_20250328102046.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_2_20250328102151.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_2_20250328102241.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_3_20250328102227.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_4_20250328102031.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_4_20250328102228.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_5_20250328102032.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_5_20250328102136.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_6_20250328102213.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_7_20250328102213.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_7_20250328102318.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_8_20250328102017.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_8_20250328102122.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_2_9_20250328102158.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_3_11_20250328102213.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_3_22_20250328102311.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_3_2_20250328102117.jpg,2,0.5909337401390076,2932.5,475.0,255,56,"0.7637,0.2199,0.06640625,0.025925925925925925"
-.\Data\detection_0328_1004\192_168_210_3_2_20250328102117.jpg,2,0.5336857438087463,1838.5,378.5,101,39,"0.4788,0.1752,0.026302083333333334,0.018055555555555554"
-.\Data\detection_0328_1004\192_168_210_3_2_20250328102257.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_3_5_20250328102242.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102047.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102103.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102120.jpg,1,0.6143049597740173,2363.5,1371.5,253,81,"0.6155,0.635,0.06588541666666667,0.0375"
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102135.jpg,1,0.5521435141563416,1015.5,18.5,117,37,"0.2645,0.0086,0.03046875,0.01712962962962963"
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102154.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_0_20250328102226.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102021.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102053.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102054.jpg,1,0.6573724746704102,905.5,1329.5,115,55,"0.2358,0.6155,0.029947916666666668,0.02546296296296296"
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102127.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102143.jpg,1,0.5543978214263916,590.5,317.5,71,37,"0.1538,0.147,0.018489583333333334,0.01712962962962963"
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102218.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102233.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_10_20250328102251.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102037.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102055.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102145.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102202.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102218.jpg,1,0.6361938118934631,2363.0,1373.0,246,78,"0.6154,0.6356,0.0640625,0.03611111111111111"
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102233.jpg,1,0.5523108243942261,1071.5,22.5,119,41,"0.279,0.0104,0.030989583333333334,0.01898148148148148"
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102252.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102324.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_11_20250328102325.jpg,1,0.6602076292037964,2899.5,1202.5,93,49,"0.7551,0.5567,0.02421875,0.022685185185185187"
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102022.jpg,1,0.6027985215187073,2356.0,1370.5,246,79,"0.6135,0.6345,0.0640625,0.03657407407407407"
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102037.jpg,1,0.5710051655769348,1046.0,20.0,116,38,"0.2724,0.0093,0.030208333333333334,0.017592592592592594"
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102055.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102112.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102127.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102202.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102234.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102236.jpg,1,0.6613223552703857,911.0,1329.5,116,53,"0.2372,0.6155,0.030208333333333334,0.024537037037037038"
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102252.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102309.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102324.jpg,1,0.5030770897865295,611.0,316.5,74,41,"0.1591,0.1465,0.019270833333333334,0.01898148148148148"
-.\Data\detection_0328_1004\192_168_210_4_12_20250328102326.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102038.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102039.jpg,1,0.58505779504776,902.0,1330.5,110,49,"0.2349,0.616,0.028645833333333332,0.022685185185185187"
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102128.jpg,1,0.5304112434387207,603.5,318.5,79,41,"0.1572,0.1475,0.020572916666666666,0.01898148148148148"
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102218.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102236.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102325.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_13_20250328102326.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102022.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102040.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102114.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102130.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102147.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102204.jpg,1,0.6097469925880432,2358.5,1371.5,249,81,"0.6142,0.635,0.06484375,0.0375"
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102219.jpg,1,0.5677247643470764,1082.0,22.0,126,40,"0.2818,0.0102,0.0328125,0.018518518518518517"
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102237.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102309.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_14_20250328102310.jpg,1,0.6549997329711914,1657.5,170.0,95,56,"0.4316,0.0787,0.024739583333333332,0.025925925925925925"
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102023.jpg,1,0.5441573858261108,1043.5,16.5,113,33,"0.2717,0.0076,0.029427083333333333,0.015277777777777777"
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102041.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102113.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102148.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102220.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102221.jpg,1,0.6360527873039246,910.5,1330.0,115,52,"0.2371,0.6157,0.029947916666666668,0.024074074074074074"
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102238.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102254.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102310.jpg,1,0.5467075705528259,586.5,316.5,69,35,"0.1527,0.1465,0.01796875,0.016203703703703703"
-.\Data\detection_0328_1004\192_168_210_4_15_20250328102311.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102024.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102025.jpg,1,0.6550416946411133,904.0,1329.0,114,52,"0.2354,0.6153,0.0296875,0.024074074074074074"
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102115.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102204.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102222.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102310.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_16_20250328102312.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102026.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102114.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102116.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102133.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102149.jpg,1,0.5977473258972168,2357.5,1371.5,249,81,"0.6139,0.635,0.06484375,0.0375"
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102204.jpg,1,0.5727278590202332,1032.0,21.5,122,39,"0.2687,0.01,0.03177083333333333,0.018055555555555554"
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102223.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_17_20250328102254.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102026.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102058.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102133.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102205.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102207.jpg,1,0.5553737878799438,912.0,1328.5,110,51,"0.2375,0.615,0.028645833333333332,0.02361111111111111"
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102255.jpg,1,0.5683696866035461,585.5,318.5,75,41,"0.1525,0.1475,0.01953125,0.01898148148148148"
-.\Data\detection_0328_1004\192_168_210_4_18_20250328102257.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102044.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102059.jpg,1,0.5500415563583374,577.5,316.0,77,38,"0.1504,0.1463,0.020052083333333335,0.017592592592592594"
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102101.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102134.jpg,1,0.5244415998458862,3677.5,541.0,139,76,"0.9577,0.2505,0.03619791666666667,0.03518518518518519"
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102149.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102257.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_19_20250328102314.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102029.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102104.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102136.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102138.jpg,1,0.6374260187149048,910.0,1329.5,112,53,"0.237,0.6155,0.029166666666666667,0.024537037037037038"
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102211.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102226.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102228.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_1_20250328102316.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102101.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102118.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102135.jpg,1,0.6337890028953552,2363.5,1371.5,251,79,"0.6155,0.635,0.06536458333333334,0.03657407407407407"
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102150.jpg,1,0.5710486173629761,1025.0,21.5,118,39,"0.2669,0.01,0.030729166666666665,0.018055555555555554"
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102208.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_20_20250328102240.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102044.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102151.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102152.jpg,1,0.6420090794563293,1570.5,718.0,159,68,"0.409,0.3324,0.04140625,0.03148148148148148"
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102226.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102241.jpg,1,0.5498589277267456,583.0,317.5,76,43,"0.1518,0.147,0.019791666666666666,0.01990740740740741"
-.\Data\detection_0328_1004\192_168_210_4_21_20250328102242.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102029.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102045.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102046.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102135.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102153.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102243.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102300.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_22_20250328102316.jpg,1,0.6056589484214783,2365.5,1372.5,247,79,"0.616,0.6354,0.06432291666666666,0.03657407407407407"
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102030.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102032.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102120.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102138.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102228.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102245.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102302.jpg,2,0.5760176777839661,2370.5,1372.0,247,78,"0.6173,0.6352,0.06432291666666666,0.03611111111111111"
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102302.jpg,2,0.5103825926780701,347.0,857.0,72,30,"0.0904,0.3968,0.01875,0.013888888888888888"
-.\Data\detection_0328_1004\192_168_210_4_2_20250328102317.jpg,1,0.5860284566879272,1030.5,20.5,121,39,"0.2684,0.0095,0.031510416666666666,0.018055555555555554"
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102032.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102049.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102106.jpg,1,0.6338214874267578,2363.5,1372.0,255,80,"0.6155,0.6352,0.06640625,0.037037037037037035"
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102121.jpg,1,0.5514400005340576,1016.0,18.5,116,37,"0.2646,0.0086,0.030208333333333334,0.01712962962962963"
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102139.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102211.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102246.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102318.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_3_20250328102319.jpg,1,0.610906183719635,912.0,1329.0,116,52,"0.2375,0.6153,0.030208333333333334,0.024074074074074074"
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102048.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102122.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102123.jpg,1,0.6252550482749939,906.0,1329.0,110,50,"0.2359,0.6153,0.028645833333333332,0.023148148148148147"
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102140.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102156.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102212.jpg,1,0.5322719216346741,580.5,317.5,77,43,"0.1512,0.147,0.020052083333333335,0.01990740740740741"
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102213.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102302.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_4_20250328102320.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102017.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102049.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102106.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102124.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102214.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102231.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102247.jpg,1,0.6676374673843384,2368.5,1373.0,251,78,"0.6168,0.6356,0.06536458333333334,0.03611111111111111"
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102302.jpg,1,0.5796356201171875,1039.0,21.0,126,40,"0.2706,0.0097,0.0328125,0.018518518518518517"
-.\Data\detection_0328_1004\192_168_210_4_5_20250328102321.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102018.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102034.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102051.jpg,1,0.66245037317276,2360.5,1371.5,253,81,"0.6147,0.635,0.06588541666666667,0.0375"
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102106.jpg,1,0.5562418103218079,1020.0,18.5,116,37,"0.2656,0.0086,0.030208333333333334,0.01712962962962963"
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102124.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102141.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102231.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102303.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102305.jpg,1,0.634587287902832,911.0,1328.5,114,53,"0.2372,0.615,0.0296875,0.024537037037037038"
-.\Data\detection_0328_1004\192_168_210_4_6_20250328102321.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102035.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102107.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102109.jpg,1,0.6477632522583008,902.5,1328.0,113,52,"0.235,0.6148,0.029427083333333333,0.024074074074074074"
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102157.jpg,1,0.5497872829437256,584.0,317.0,70,34,"0.1521,0.1468,0.018229166666666668,0.01574074074074074"
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102159.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102247.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_7_20250328102305.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102051.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102109.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102126.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102159.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102216.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102233.jpg,1,0.6619832515716553,2366.5,1373.0,249,78,"0.6163,0.6356,0.06484375,0.03611111111111111"
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102248.jpg,1,0.5535046458244324,1052.0,23.0,112,40,"0.274,0.0106,0.029166666666666667,0.018518518518518517"
-.\Data\detection_0328_1004\192_168_210_4_8_20250328102306.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102020.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102037.jpg,1,0.6007559299468994,2359.5,1372.0,245,78,"0.6145,0.6352,0.06380208333333333,0.03611111111111111"
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102052.jpg,1,0.577226996421814,1027.0,18.0,118,36,"0.2674,0.0083,0.030729166666666665,0.016666666666666666"
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102110.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102127.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102142.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102249.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102250.jpg,1,0.5580655932426453,913.0,1330.5,116,55,"0.2378,0.616,0.030208333333333334,0.02546296296296296"
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102307.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_4_9_20250328102324.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_11_20250328102037.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_12_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_17_20250328102204.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_1_20250328102316.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_22_20250328102135.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_2_20250328102047.jpg,1,0.5584949851036072,2353.5,224.0,73,36,"0.6129,0.1037,0.019010416666666665,0.016666666666666666"
-.\Data\detection_0328_1004\192_168_210_5_3_20250328102048.jpg,1,0.5161254405975342,726.5,176.5,63,31,"0.1892,0.0817,0.01640625,0.014351851851851852"
-.\Data\detection_0328_1004\192_168_210_5_5_20250328102106.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_6_20250328102106.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_5_7_20250328102247.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_0_20250328102151.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_10_20250328102020.jpg,1,0.5327115058898926,579.0,126.5,70,37,"0.1508,0.0586,0.018229166666666668,0.01712962962962963"
-.\Data\detection_0328_1004\192_168_210_6_11_20250328102249.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_11_20250328102323.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_12_20250328102053.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_12_20250328102201.jpg,1,0.5410155057907104,582.5,126.0,65,40,"0.1517,0.0583,0.016927083333333332,0.018518518518518517"
-.\Data\detection_0328_1004\192_168_210_6_14_20250328102235.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_15_20250328102039.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_17_20250328102220.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_18_20250328102024.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_18_20250328102133.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_1_20250328102029.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_1_20250328102047.jpg,2,0.5645437240600586,3247.5,854.5,71,39,"0.8457,0.3956,0.018489583333333334,0.018055555555555554"
-.\Data\detection_0328_1004\192_168_210_6_1_20250328102047.jpg,2,0.564518392086029,3486.5,560.5,77,41,"0.9079,0.2595,0.020052083333333335,0.01898148148148148"
-.\Data\detection_0328_1004\192_168_210_6_21_20250328102026.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_21_20250328102043.jpg,1,0.5194695591926575,3374.5,2062.0,55,30,"0.8788,0.9546,0.014322916666666666,0.013888888888888888"
-.\Data\detection_0328_1004\192_168_210_6_22_20250328102027.jpg,1,0.5746172070503235,3673.5,1767.0,115,72,"0.9566,0.8181,0.029947916666666668,0.03333333333333333"
-.\Data\detection_0328_1004\192_168_210_6_3_20250328102137.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_5_20250328102318.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_6_20250328102122.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_8_20250328102304.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_6_9_20250328102108.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_0_20250328102043.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_0_20250328102100.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_0_20250328102240.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_10_20250328102157.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_11_20250328102141.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_11_20250328102158.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_12_20250328102142.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_13_20250328102143.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_13_20250328102323.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_14_20250328102127.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_14_20250328102143.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_15_20250328102127.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_15_20250328102144.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_15_20250328102324.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_16_20250328102128.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_16_20250328102308.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_16_20250328102325.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_17_20250328102112.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_17_20250328102125.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_17_20250328102129.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_17_20250328102309.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_18_20250328102310.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_19_20250328102114.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_19_20250328102254.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_19_20250328102310.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_19_20250328102324.jpg,1,0.5264825224876404,1163.0,435.0,120,72,"0.3029,0.2014,0.03125,0.03333333333333333"
-.\Data\detection_0328_1004\192_168_210_7_1_20250328102241.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_20_20250328102058.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_20_20250328102111.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_20_20250328102130.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_20_20250328102254.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_21_20250328102058.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_21_20250328102111.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_21_20250328102115.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_21_20250328102131.jpg,1,0.5218129754066467,1288.5,634.0,65,32,"0.3355,0.2935,0.016927083333333332,0.014814814814814815"
-.\Data\detection_0328_1004\192_168_210_7_21_20250328102255.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_22_20250328102059.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_22_20250328102239.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_22_20250328102256.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_2_20250328102045.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_2_20250328102225.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_3_20250328102029.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_3_20250328102045.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_4_20250328102029.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_4_20250328102226.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_5_20250328102030.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_5_20250328102210.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_6_20250328102031.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_6_20250328102154.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_6_20250328102211.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_7_20250328102212.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_8_20250328102016.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_8_20250328102156.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_8_20250328102213.jpg,0,0
-.\Data\detection_0328_1004\192_168_210_7_9_20250328102050.jpg,1,0.5228474140167236,307.5,1525.5,63,31,"0.0801,0.7063,0.01640625,0.014351851851851852"
-.\Data\detection_0328_1004\192_168_210_7_9_20250328102156.jpg,0,0

BIN
Data/detection_0328_1004_results/detection_report.xlsx


BIN
Data/detection_0328_1024_results/detection_report.xlsx


BIN
Data/detection_0328_1055_results/detection_report.xlsx


BIN
Data/detection_0328_1115_results/detection_report.xlsx


BIN
Data/detection_0328_1455_results/detection_report.xlsx


BIN
Data/detection_0328_1537_results/detection_report.xlsx


BIN
Data/detection_0328_1612_results/detection_report.xlsx


BIN
Data/detection_0328_1735_results/detection_report.xlsx


BIN
Data/detection_0329_1004_results/detection_report.xlsx


+ 0 - 114
Output/output_20250328_173528_results/performance_stats.txt

@@ -1,114 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-28 17:35:28
-采集结束时间: 2025-03-28 17:53:15
-持续时长: 1067秒
-
-详细统计信息:
-总样本数(CSV中唯一图像数): 27558
-检测到的目标总数: 320
-真实目标总数(TP): 97
-误报目标数(FP): 223
-真阴性数量(TN): 27238
-
-性能指标:
-准确率: 0.9919
-精确率: 0.3031
-召回率: 1.0000
-F1分数: 0.4652
-误报率(虚警率): 0.0081
-
-镜头统计信息:
-------------------------------
-镜头 cam_00:
-  总报警数: 4
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_01:
-  总报警数: 3
-  误报数: 1
-  误报率: 0.3333
-------------------------------
-镜头 cam_02:
-  总报警数: 2
-  误报数: 1
-  误报率: 0.5000
-------------------------------
-镜头 cam_03:
-  总报警数: 3
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_04:
-  总报警数: 21
-  误报数: 6
-  误报率: 0.2857
-------------------------------
-镜头 cam_05:
-  总报警数: 119
-  误报数: 119
-  误报率: 1.0000
-------------------------------
-镜头 cam_06:
-  总报警数: 26
-  误报数: 26
-  误报率: 1.0000
-------------------------------
-镜头 cam_07:
-  总报警数: 45
-  误报数: 41
-  误报率: 0.9111
-------------------------------
-镜头 cam_08:
-  总报警数: 22
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_09:
-  总报警数: 12
-  误报数: 6
-  误报率: 0.5000
-------------------------------
-镜头 cam_10:
-  总报警数: 7
-  误报数: 1
-  误报率: 0.1429
-------------------------------
-镜头 cam_11:
-  总报警数: 1
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_12:
-  总报警数: 3
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_13:
-  总报警数: 6
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_14:
-  总报警数: 24
-  误报数: 22
-  误报率: 0.9167
-------------------------------
-镜头 cam_15:
-  总报警数: 15
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_16:
-  总报警数: 4
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_17:
-  总报警数: 3
-  误报数: 0
-  误报率: 0.0000
-------------------------------

+ 0 - 114
Output/output_20250329_100448_results/performance_stats.txt

@@ -1,114 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-29 10:04:48
-采集结束时间: 2025-03-29 10:26:52
-持续时长: 1324秒
-
-详细统计信息:
-总样本数(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
-------------------------------

+ 0 - 94
Output/output_20250329_111006_results/performance_stats.txt

@@ -1,94 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-29 11:10:06
-采集结束时间: 2025-03-29 11:16:01
-持续时长: 355秒
-
-详细统计信息:
-总样本数(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
-------------------------------

+ 0 - 109
Output/output_20250329_130338_results/performance_stats.txt

@@ -1,109 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-29 13:03:38
-采集结束时间: 2025-03-29 13:27:23
-持续时长: 1425秒
-
-详细统计信息:
-总样本数(CSV中唯一图像数): 34562
-检测到的目标总数: 644
-真实目标总数(TP): 177
-误报目标数(FP): 467
-真阴性数量(TN): 33918
-
-性能指标:
-准确率: 0.9865
-精确率: 0.2748
-召回率: 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
-------------------------------

+ 0 - 109
Output/output_20250329_133810_results/performance_stats.txt

@@ -1,109 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-29 13:38:10
-采集结束时间: 2025-03-29 14:02:17
-持续时长: 1447秒
-
-详细统计信息:
-总样本数(CSV中唯一图像数): 36540
-检测到的目标总数: 347
-真实目标总数(TP): 111
-误报目标数(FP): 236
-真阴性数量(TN): 36193
-
-性能指标:
-准确率: 0.9935
-精确率: 0.3199
-召回率: 1.0000
-F1分数: 0.4847
-误报率(虚警率): 0.0065
-
-镜头统计信息:
-------------------------------
-镜头 cam_00:
-  总报警数: 16
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_01:
-  总报警数: 47
-  误报数: 44
-  误报率: 0.9362
-------------------------------
-镜头 cam_02:
-  总报警数: 8
-  误报数: 8
-  误报率: 1.0000
-------------------------------
-镜头 cam_03:
-  总报警数: 11
-  误报数: 9
-  误报率: 0.8182
-------------------------------
-镜头 cam_04:
-  总报警数: 34
-  误报数: 30
-  误报率: 0.8824
-------------------------------
-镜头 cam_05:
-  总报警数: 89
-  误报数: 78
-  误报率: 0.8764
-------------------------------
-镜头 cam_06:
-  总报警数: 50
-  误报数: 43
-  误报率: 0.8600
-------------------------------
-镜头 cam_07:
-  总报警数: 28
-  误报数: 4
-  误报率: 0.1429
-------------------------------
-镜头 cam_08:
-  总报警数: 7
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_09:
-  总报警数: 7
-  误报数: 1
-  误报率: 0.1429
-------------------------------
-镜头 cam_10:
-  总报警数: 10
-  误报数: 7
-  误报率: 0.7000
-------------------------------
-镜头 cam_11:
-  总报警数: 10
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_13:
-  总报警数: 8
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_14:
-  总报警数: 16
-  误报数: 12
-  误报率: 0.7500
-------------------------------
-镜头 cam_15:
-  总报警数: 1
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_16:
-  总报警数: 4
-  误报数: 0
-  误报率: 0.0000
-------------------------------
-镜头 cam_17:
-  总报警数: 1
-  误报数: 0
-  误报率: 0.0000
-------------------------------

+ 0 - 109
Output/output_20250329_140816_results/performance_stats.txt

@@ -1,109 +0,0 @@
-检测性能统计报告
-==================================================
-
-时间统计信息:
-采集开始时间: 2025-03-29 14:08:16
-采集结束时间: 2025-03-29 14:28:47
-持续时长: 1231秒
-
-详细统计信息:
-总样本数(CSV中唯一图像数): 31086
-检测到的目标总数: 361
-真实目标总数(TP): 196
-误报目标数(FP): 165
-真阴性数量(TN): 30725
-
-性能指标:
-准确率: 0.9947
-精确率: 0.5429
-召回率: 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
-------------------------------

+ 269 - 2
README.md

@@ -2,15 +2,40 @@
 
 基于 ONNX 的无人机检测系统,支持单张图片和批量处理。
 
+## 概述
+
+本项目实现了多种UAV(无人机)检测模型的推理系统,支持三种不同的模型架构和相应的后处理方法。每种模型都有其特定的输入输出格式、后处理流程和可视化方式。
+
 ## 功能特点
 
 - 支持 ONNX 模型推理
 - 支持 CUDA 加速
 - 支持批量处理图片
 - 自动生成检测报告(CSV格式)
-- 支持误报过滤
 - 支持检测框面积比例限制
 - 支持保存未检测到目标的图片
+- 支持三种不同架构的模型自动识别
+- 集成边界框验证机制
+
+## 支持的模型类型
+
+### 1. Anti_UAV 模型
+- **文件名**: `250411_Anti_UAV.onnx`
+- **识别特征**: 输入包含 `scale_factor`,输出名称以 `multiclass_nms3` 开头
+- **输入尺寸**: 640×640
+- **类别**: 单类别检测(UAV)
+
+### 2. UAV-250411 模型
+- **文件名**: `UAV-250411.onnx`
+- **识别特征**: 输入包含 `scale_factor`,输出为2个张量且第一个以 `tmp_` 开头
+- **输入尺寸**: 640×640
+- **类别**: 单类别检测(UAV)
+
+### 3. uav_and_bird 模型
+- **文件名**: `uav_and_bird.onnx`
+- **识别特征**: 输入不包含 `scale_factor`,输出张量数量大于2
+- **输入尺寸**: 640×640
+- **类别**: 双类别检测(Bird: 0, UAV: 1)
 
 ## 环境要求
 
@@ -41,6 +66,15 @@ python -m src.core.inference --input path/to/image.jpg --threshold 0.6 --max-bbo
 
 # 保存未检测到目标的图片
 python -m src.core.inference --input path/to/images_dir --save-empty
+
+# 自动识别模型类型
+python inference.py --input /path/to/images --threshold 0.5
+
+# 指定模型类型
+python inference.py --input /path/to/images --model-type uav_and_bird
+
+# 批量处理
+python inference.py --input /path/to/directory --output /path/to/results
 ```
 
 ### 图形界面模式
@@ -49,6 +83,23 @@ python -m src.core.inference --input path/to/images_dir --save-empty
 python -m src.core.inference --gui
 ```
 
+### 编程接口
+
+```python
+# 初始化检测器
+detector = ONNXDetector(
+    input_dir="/path/to/images",
+    model_type="uav_and_bird",
+    prob_threshold=0.5
+)
+
+# 处理单张图像
+detections, img_out, detection_list = detector.process_image("/path/to/image.jpg")
+
+# 批量处理
+total_detections = detector.process_directory()
+```
+
 ## 参数说明
 
 - `--input`: 输入图像路径或目录(必需)
@@ -57,12 +108,209 @@ python -m src.core.inference --gui
 - `--max-bbox-ratio`: 检测框最大面积比例阈值,默认0.05
 - `--save-empty`: 是否保存未检测到目标的图片
 - `--gui`: 启用图形界面选择输入目录
+- `--model-type`: 指定模型类型(可选,系统可自动识别)
+
+## 模型结构分析
+
+### 输入预处理
+
+所有模型都采用相同的预处理流程:
+
+```python
+# 图像预处理步骤
+1. 颜色空间转换: BGR → RGB
+2. 尺寸调整: 原图 → 640×640
+3. 数据类型转换: uint8 → float32
+4. 归一化: [0,255] → [0,1]
+5. 标准化: 使用ImageNet均值和标准差
+   - mean = [0.485, 0.456, 0.406]
+   - std = [0.229, 0.224, 0.225]
+6. 维度调整: HWC → CHW
+7. 批次维度: CHW → NCHW
+```
+
+### 模型输入格式
+
+#### Anti_UAV 和 UAV-250411 模型
+```python
+inputs = {
+    'image': img[None, :, :, :],        # (1, 3, 640, 640)
+    'scale_factor': scale_factor[None, :] # (1, 2)
+}
+```
+
+#### uav_and_bird 模型
+```python
+inputs = {
+    'images': img[None, :, :, :]  # (1, 3, 640, 640)
+}
+```
+
+## 后处理方法详解
+
+### 1. Anti_UAV 模型后处理
+
+**特点**: 模型内置NMS,输出已经过滤的检测结果
+
+```python
+# 输出格式
+bbox: (N, 4)      # 边界框坐标 [x1, y1, x2, y2]
+confidence: (N, 1) # 置信度分数
+
+# 后处理流程
+1. 置信度过滤: confidence > threshold
+2. 坐标缩放: 模型输出 → 原图尺寸
+3. 边界框验证: 面积比例检查
+4. 结果保存和可视化
+```
+
+### 2. UAV-250411 模型后处理
+
+**特点**: 需要手动实现NMS处理
+
+```python
+# 输出格式
+output[0]: (N, 4)  # 边界框坐标
+output[1]: (N, 1)  # 置信度分数
+
+# 后处理流程
+1. 置信度过滤: confidence > threshold
+2. 坐标缩放: 模型输出 → 原图尺寸
+3. NMS处理: IoU阈值 = 0.4
+4. 边界框验证
+5. 结果保存和可视化
+```
+
+### 3. uav_and_bird 模型后处理
+
+**特点**: 多尺度输出,使用Distribution Focal Loss,需要复杂的解码过程
+
+```python
+# 输出格式(3个尺度)
+small_output: (1, 80, 80, 21)   # 小目标检测
+medium_output: (1, 40, 40, 21)  # 中等目标检测
+large_output: (1, 20, 20, 21)   # 大目标检测
+
+# 每个输出的通道分布
+# 21 = 17(bbox) + 2(classes) + 2(quality)
+
+# 后处理流程
+1. 多尺度处理:
+   - 小尺度: stride=8, 网格80×80
+   - 中尺度: stride=16, 网格40×40  
+   - 大尺度: stride=32, 网格20×20
+
+2. Distribution Focal Loss解码:
+   - bbox_pred: 17维距离分布 → 4个距离值
+   - 使用softmax + 期望值计算实际距离
+
+3. 网格坐标生成(带0.5偏移):
+   grid_x, grid_y = np.meshgrid(range(W), range(H))
+   grid_x = (grid_x.flatten() + 0.5)
+   grid_y = (grid_y.flatten() + 0.5)
+
+4. 边界框计算:
+   x1 = (grid_x - d_left) * stride
+   y1 = (grid_y - d_top) * stride
+   x2 = (grid_x + d_right) * stride
+   y2 = (grid_y + d_bottom) * stride
+
+5. 置信度计算:
+   final_scores = cls_pred * quality_pred
+
+6. 多尺度结果合并和NMS处理
+```
+
+## 可视化和画框方式
+
+### 1. 边界框绘制
+
+所有模型都使用相同的绘制方式:
+
+```python
+# 边界框样式
+cv2.rectangle(img_out, (x1, y1), (x2, y2), (255, 0, 0), 4)  # 蓝色框,线宽4
+
+# 标签样式
+label = f'{class_name} {confidence:.2f}'
+cv2.putText(img_out, label, (x1, y1 - 10), 
+            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)  # 红色文字
+```
+
+### 2. 类别标签映射
+
+```python
+# Anti_UAV 和 UAV-250411 模型
+class_names = {0: 'UAV'}
+
+# uav_and_bird 模型
+class_names = {0: 'Bird', 1: 'UAV'}
+```
+
+### 3. 检测结果保存
+
+```python
+# 保存检测到的目标区域
+target_filename = f"{base_name}_{detection_count}.jpg"
+cv2.imwrite(os.path.join(targets_dir, target_filename), roi)
+
+# 保存带标注的完整图像
+output_filename = f"detected_{base_name}"
+cv2.imwrite(os.path.join(output_dir, output_filename), img_out)
+```
+
+## 性能优化和质量控制
+
+### 1. 边界框验证
+
+```python
+# 面积比例检查
+bbox_area = (x2 - x1) * (y2 - y1)
+image_area = orig_w * orig_h
+if bbox_area / image_area > max_bbox_ratio:  # 默认0.05
+    continue
+
+# 尺寸有效性检查
+if x2 <= x1 or y2 <= y1:
+    continue
+```
+
+### 2. NMS参数
+
+```python
+# 所有模型统一使用的NMS参数
+conf_threshold = 0.5    # 置信度阈值
+iou_threshold = 0.4     # IoU阈值
+```
+
+## 模型自动识别机制
+
+系统通过分析ONNX模型的输入输出结构自动识别模型类型:
+
+```python
+def get_model_type(model_path: str) -> str:
+    model = onnx.load(model_path)
+    input_names = [i.name for i in model.graph.input]
+    output_names = [o.name for o in model.graph.output]
+    
+    if 'scale_factor' in input_names:
+        if any(name.startswith('multiclass_nms3') for name in output_names):
+            return 'Anti_UAV'
+        else:
+            return 'UAV-250411'
+    else:
+        if len(output_names) > 2:
+            return 'uav_and_bird'
+    
+    return 'unknown'
+```
 
 ## 输出说明
 
 程序会在输出目录中生成以下内容:
 
 - 检测结果图片(带检测框)
+- 检测到的目标区域图片
 - `detection_report.csv`: 检测报告,包含以下信息:
   - 图片路径
   - 检测时间
@@ -76,10 +324,29 @@ python -m src.core.inference --gui
 2. 如果使用GPU加速,请确保CUDA环境配置正确
 3. 批量处理时建议使用相对较小的图片尺寸以提高处理速度
 4. 检测报告会自动覆盖同名文件,请注意备份
+5. 系统会自动识别模型类型,无需手动指定
+6. 支持多种模型架构,可根据实际需求选择合适的模型
+
+## 项目特点总结
+
+本项目实现了一个灵活的多模型UAV检测系统,具有以下特点:
+
+1. **模型兼容性**: 支持三种不同架构的ONNX模型
+2. **自动识别**: 根据模型结构自动选择对应的后处理方法
+3. **质量控制**: 集成边界框验证机制
+4. **可扩展性**: 易于添加新的模型类型和后处理方法
+5. **性能优化**: 支持CUDA加速和批量处理
+6. **用户友好**: 支持命令行和图形界面两种使用方式
+7. **完整输出**: 自动生成检测报告和可视化结果
+
+每种模型都有其特定的应用场景和优势,用户可以根据实际需求选择合适的模型进行部署。
 
 ## 更新日志
 
 ### 2024-03-29
 - 移除Excel报告生成功能
 - 优化检测报告生成逻辑
-- 修复模型加载和属性访问问题
+- 修复模型加载和属性访问问题
+- 移除ORB特征匹配误报过滤功能
+- 清理调试信息,优化代码结构
+- 合并技术文档到README,提供完整的使用和技术说明

BIN
__pycache__/feature_extractor.cpython-39.pyc


BIN
__pycache__/inference.cpython-39.pyc


BIN
__pycache__/report_generator.cpython-39.pyc


+ 6 - 4
requirements.txt

@@ -1,7 +1,9 @@
-onnxruntime-gpu==1.16.0
-opencv-python==4.8.0
-numpy==1.24.3
+numpy>=1.21.0
+Pillow>=9.0.0
+opencv-python>=4.5.0
+onnxruntime>=1.8.0
+onnx==1.17.0
 tqdm==4.66.1
-openpyxl==3.1.2
+openpyxl==3.1.5
 pytest==7.4.0
 pytest-cov==4.1.0 

+ 4 - 0
src/__init__.py

@@ -1 +1,5 @@
+"""
+R360 UAV Model Tool
+"""
+
 # 使src成为一个Python包 

+ 4 - 0
src/analysis/__init__.py

@@ -1 +1,5 @@
+"""
+Analysis and reporting functionality
+"""
+
 # 使analysis成为一个Python包 

+ 1 - 1
src/analysis/analysis_report.py

@@ -90,4 +90,4 @@ if __name__ == "__main__":
     report = generate_analysis_report(df)
     save_report(report, args.output)
     
-    print(f"分析完成!报告已保存至:{args.output}")
+    # 分析报告生成完成

+ 7 - 10
src/core/ali_image_validation.py

@@ -18,10 +18,7 @@ class AliImageValidator:
         if not self.client.api_key:
             raise ValueError("未找到API密钥,请设置环境变量DASHSCOPE_API_KEY或通过参数传递")
 
-        logging.basicConfig(
-            format='%(asctime)s - %(levelname)s - %(message)s',
-            level=logging.DEBUG
-        )
+        # 日志配置已移除
 
 
     @retry(tries=3, delay=1, backoff=2, max_delay=5, exceptions=(Exception,))
@@ -53,7 +50,7 @@ class AliImageValidator:
         try:
             start_time = time.time()
             model_name = "qwen-vl-max-latest"
-            logging.info(f"发送请求到阿里云 | 端点: {self.client.base_url} | 模型: {model_name}")
+            # 发送请求到阿里云
             response = self.client.chat.completions.create(
                 model=model_name,
                 messages=[
@@ -77,7 +74,7 @@ class AliImageValidator:
             
             try:
                 result = response.choices[0].message.content
-                logging.debug(f"原始响应内容: {result}")
+                # 获取响应内容
                 try:
                     result_json = json.loads(result.split('```json')[1].split('```')[0].strip())  # 提取markdown代码块中的JSON
                     
@@ -89,7 +86,7 @@ class AliImageValidator:
                         'response_time': response_time
                     }
                 except (IndexError, json.JSONDecodeError, KeyError) as e:
-                    logging.error(f"响应解析失败 | 错误类型: {type(e).__name__} | 原始响应: {result}")
+                    # 响应解析失败
                     return {
                         'is_false_positive': "误报" in result,
                         'uav_detected': False,
@@ -98,7 +95,7 @@ class AliImageValidator:
                         'response_time': response_time
                     }
             except (json.JSONDecodeError, ValueError) as e:
-                logging.error(f"响应解析失败: {str(e)}")
+                # 响应解析失败
                 return {
                     'is_false_positive': "误报" in result,
                     'uav_detected': False,
@@ -110,7 +107,7 @@ class AliImageValidator:
         except Exception as e:
             end_time = time.time()
             response_time = end_time - start_time
-            logging.error(f"API调用失败 | 端点: {self.client.base_url} | 模型: {model_name} | 错误类型: {type(e).__name__} | 错误详情: {str(e)}")
+            # API调用失败
             return {
                 'is_false_positive': False,
                 'uav_detected': False,
@@ -129,4 +126,4 @@ if __name__ == "__main__":
     validator = AliImageValidator()
     result = validator.analyze_image(args.image_url)
     
-    print(f"综合分析结果:\n误报概率: {result['probability']:.2f}\n无人机识别: {'是' if result['uav_detected'] else '否'}\n判定结果: {'误报' if result['is_false_positive'] else '真实威胁'}\n响应时间: {result['response_time']:.2f}秒\n分析理由: {result['reason']}")
+    # 分析完成

+ 4 - 9
src/core/compare_outputs.py

@@ -42,25 +42,20 @@ def compare_directories(dir1, dir2, output_dir):
         src_file = os.path.join(dir1, dir1_base_files[base_name])
         dst_file = os.path.join(dir1_only_dir, dir1_base_files[base_name])
         shutil.copy2(src_file, dst_file)
-        print(f"复制 {src_file} 到 {dst_file}")
+        # 复制文件
     
     for base_name in only_in_dir2:
         src_file = os.path.join(dir2, dir2_base_files[base_name])
         dst_file = os.path.join(dir2_only_dir, dir2_base_files[base_name])
         shutil.copy2(src_file, dst_file)
-        print(f"复制 {src_file} 到 {dst_file}")
+        # 复制文件
     
     # 打印统计信息
-    print(f"\n统计信息:")
-    print(f"目录1中的文件总数: {len(dir1_files)}")
-    print(f"目录2中的文件总数: {len(dir2_files)}")
-    print(f"只在目录1中存在的文件数: {len(only_in_dir1)}")
-    print(f"只在目录2中存在的文件数: {len(only_in_dir2)}")
-    print(f"共同存在的文件数: {len(dir1_files) - len(only_in_dir1)}")
+    # 文件比较完成
 
 if __name__ == "__main__":
     dir1 = r"D:\PythonProject\Model\output_20250329_140816_results"
     dir2 = r"D:\PythonProject\Model\Output\output_20250329_140816_results"
     output_dir = r"D:\PythonProject\Model\output_differences"
     
-    compare_directories(dir1, dir2, output_dir) 
+    compare_directories(dir1, dir2, output_dir)

+ 6 - 6
src/core/feature_extractor.py

@@ -18,24 +18,24 @@ class FalsePositiveFeatureExtractor:
     def extract_features(self, img_path):
         # 检查文件是否存在
         if not os.path.exists(img_path):
-            print(f"警告:文件不存在 {img_path}")
+            # 文件不存在
             return None
             
         # 读取图片并检查有效性
         img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
         if img is None:
-            print(f"警告:无法读取图像 {img_path}")
+            # 无法读取图像
             return None
             
         # 检查图片尺寸和内容
         if img.size == 0:
-            print(f"警告:空图像 {img_path}")
+            # 空图像
             return None
             
         # 计算图像清晰度(拉普拉斯方差)
         blur_value = cv2.Laplacian(img, cv2.CV_64F).var()
         if blur_value < 50:  # 阈值可根据实际情况调整
-            print(f"警告:图像模糊 {img_path} (清晰度: {blur_value:.2f})")
+            # 图像模糊
             return None
             
         # 提取特征
@@ -43,7 +43,7 @@ class FalsePositiveFeatureExtractor:
         
         # 检查特征数量和质量
         if des is None or len(des) < 10:
-            print(f"警告:特征不足 {img_path} (特征数: {len(kp) if kp else 0})")
+            # 特征不足
             return None
             
         return des
@@ -73,4 +73,4 @@ if __name__ == '__main__':
     
     extractor = FalsePositiveFeatureExtractor()
     count = extractor.build_feature_db(args.input, args.output)
-    print(f'成功提取{count}个误报样本的特征')
+    # 特征提取完成

+ 5 - 8
src/core/image_validation.py

@@ -16,10 +16,7 @@ class ImageValidator:
         if not self.client.api_key:
             raise ValueError("未找到API密钥,请设置环境变量ARK_API_KEY或通过参数传递")
 
-        logging.basicConfig(
-            format='%(asctime)s - %(levelname)s - %(message)s',
-            level=logging.INFO
-        )
+        # 日志配置已移除
 
     def _image_to_base64(self, image_path):
         try:
@@ -28,7 +25,7 @@ class ImageValidator:
                 img.convert('RGB').save(buffered, format="JPEG")
                 return base64.b64encode(buffered.getvalue()).decode('utf-8')
         except Exception as e:
-            logging.error(f"图片处理失败: {str(e)}")
+            # 图片处理失败
             return None
 
     def analyze_image(self, image_path):
@@ -93,7 +90,7 @@ class ImageValidator:
                     'response_time': response_time
                 }
             except (json.JSONDecodeError, ValueError) as e:
-                logging.error(f"响应解析失败: {str(e)}")
+                # 响应解析失败
                 return {
                     'is_false_positive': "误报" in result,
                     'uav_detected': False,
@@ -105,7 +102,7 @@ class ImageValidator:
         except Exception as e:
             end_time = time.time()
             response_time = end_time - start_time
-            logging.error(f"API调用失败: {str(e)}")
+            # API调用失败
             return {
                 'is_false_positive': False,
                 'uav_detected': False,
@@ -126,4 +123,4 @@ if __name__ == "__main__":
     validator = ImageValidator(args.api_key)
     is_false_positive = validator.analyze_image(args.image_path)
     
-    print(f"综合分析结果:\n误报概率: {is_false_positive['probability']:.2f}\n无人机识别: {'是' if is_false_positive['uav_detected'] else '否'}\n判定结果: {'误报' if is_false_positive['is_false_positive'] else '真实威胁'}\n响应时间: {is_false_positive['response_time']:.2f}秒\n分析理由: {is_false_positive['reason']}")
+    # 分析完成

+ 3 - 3
src/core/infer.py

@@ -119,7 +119,7 @@ def process_image(detector: UAVDetector, image_path: str, output_dir: str) -> in
     """处理单张图像"""
     srcimg = cv2.imread(image_path)
     if srcimg is None:
-        print(f"无法读取图像: {image_path}")
+        # 无法读取图像
         return 0
         
     processed_img, detections = detector.detect(srcimg)
@@ -162,7 +162,7 @@ if __name__ == '__main__':
         for img_file in tqdm(image_files, desc='Processing images'):
             total_detections += process_image(detector, img_file, args.output)
             
-        print(f'批量处理完成!共检测到 {total_detections} 个目标')
+        # 批量处理完成
     else:
         detections = process_image(detector, args.input, args.output)
-        print(f'处理完成!检测到 {detections} 个目标') 
+        # 处理完成

+ 329 - 120
src/core/inference.py

@@ -3,13 +3,14 @@ import onnxruntime as ort
 import cv2
 import os
 import argparse
-import pickle
 from glob import glob
 from typing import List, Dict, Optional
 import time
 from datetime import datetime
 from tqdm import tqdm
-from ..analysis.report_generator import ReportGenerator
+from src.analysis.report_generator import ReportGenerator
+import onnx
+
 class ONNXDetector:
     def select_input_directory(self) -> Optional[str]:
         """图形界面选择输入目录"""
@@ -20,23 +21,37 @@ class ONNXDetector:
         folder_path = filedialog.askdirectory(title='选择输入目录')
         return folder_path if folder_path else None
 
-    def __init__(self, model_path: str = 'D:/PythonProject/Model/Data/models/250411_Anti_UAV.onnx', threshold: float = 0.5, 
+    def __init__(self, threshold: float = 0.5, 
                  output_dir: str = None, save_empty: bool = False, 
                  max_bbox_ratio: float = 0.5,
-                 input_dir: str = None):
+                 input_dir: str = None, model_type: str = None, model_path: str = None):
         self.image_count = 0
         self.detection_records = []
-        self.model_path = model_path
         self.input_dir = input_dir
         self.save_empty = save_empty
         self.threshold = threshold
         self.confThreshold = threshold
         
+        # 自动识别模型类型
+        if model_path:
+            self.model_path = model_path
+            self.model_type = model_type if model_type else get_model_type(model_path)
+        else:
+            self.model_type = model_type if model_type else get_model_type(r"D:\PythonProject\R360-UAVmodelTool\src\models\UAV-250411.onnx")
+            # 根据模型类型选择不同的模型路径
+            if self.model_type == 'Anti_UAV':
+                self.model_path = r"D:\PythonProject\R360-UAVmodelTool\src\models\250411_Anti_UAV.onnx"
+            elif self.model_type == 'UAV-250411':
+                self.model_path = r"D:\PythonProject\R360-UAVmodelTool\src\models\UAV-250411.onnx"
+            else:
+                self.model_path = r"D:\PythonProject\R360-UAVmodelTool\src\models\uav_and_bird.onnx"
+        # 模型初始化完成
+        
         # 初始化ONNX会话
         so = ort.SessionOptions()
         so.log_severity_level = 3
         self.providers = ['CUDAExecutionProvider', 'CPUExecutionProvider']
-        self.session = ort.InferenceSession(model_path, so, providers=self.providers)
+        self.session = ort.InferenceSession(self.model_path, so, providers=self.providers)
         
         # 模型参数设置
         self.input_size = (640, 640)  # width, height
@@ -45,22 +60,24 @@ class ONNXDetector:
         self.max_bbox_ratio = max_bbox_ratio
         
         # 从模型路径解析版本号
-        self.model_version = os.path.basename(model_path).split('.')[0]
+        self.model_version = os.path.basename(self.model_path).split('.')[0]
         
         # 获取输入输出名称
         self.input_name = self.session.get_inputs()[0].name
-        self.output_name = self.session.get_outputs()[0].name
+        if self.model_type == 'Anti_UAV':
+            self.output_name = 'multiclass_nms3_0.tmp_0'
+        elif self.model_type == 'UAV-250411':
+            self.output_name = 'tmp_17'
+        else:
+            self.output_name = 'conv2d_308.tmp_1'
         
         # 类别映射
-        self.class_names = {0: 'UAV'}
+        if self.model_type == 'uav_and_bird':
+            self.class_names = {0: 'Bird', 1: 'UAV'}
+        else:
+            self.class_names = {0: 'UAV'}
 
-        # 加载误报特征库
-        self.false_positive_features = {}
-        try:
-            with open(os.path.join(os.path.dirname(__file__), 'false_positive_features.pkl'), 'rb') as f:
-                self.false_positive_features = pickle.load(f)
-        except FileNotFoundError:
-            print("未找到误报特征库文件,跳过加载")
+        # 误报特征库相关代码已移除
         
         # 创建输出目录
         output_base = os.path.join(os.path.dirname(__file__), '..', '..', 'Output')
@@ -87,7 +104,7 @@ class ONNXDetector:
         if self.use_cuda:
             self.gpu_frame.upload(cv2.imread(image_path))
             if self.gpu_frame.empty():
-                print(f"无法加载图像:{image_path}")
+                # 图像加载失败
                 return None
             
             # GPU预处理流水线
@@ -101,7 +118,7 @@ class ONNXDetector:
             # CPU回退路径
             image_orig = cv2.imread(image_path)
             if image_orig is None:
-                print(f"无法加载图像:{image_path}")
+                # 图像加载失败
                 return None
             
             self.orig_h, self.orig_w = image_orig.shape[:2]
@@ -140,110 +157,260 @@ class ONNXDetector:
             order = order[inds + 1]
         return keep
 
-    def inference(self, input_data: np.ndarray) -> np.ndarray:
-        """执行模型推理"""
-        scale_factor = np.array([[1, 1]], dtype=np.float32)
-        return self.session.run(
-            [self.output_name],
-            {self.input_name: input_data, 'scale_factor': scale_factor}
-        )[0]
-
-    def _is_false_positive(self, roi: np.ndarray) -> bool:
-        """使用ORB特征匹配验证是否误报"""
-        if not self.false_positive_features:
-            return False
-
-        # 初始化特征检测器
-        detector = cv2.ORB_create()
-        _, des = detector.detectAndCompute(roi, None)
-
-        # 与特征库进行匹配
-        for fp_feature in self.false_positive_features.values():
-            if des is None or fp_feature['features'] is None:
-                continue
-
-            # 使用FLANN匹配器
-            flann = cv2.FlannBasedMatcher(dict(algorithm=6, table_number=6), dict())
-            matches = flann.knnMatch(des, fp_feature['features'], k=2)
-
-            # 处理空匹配情况
-            if not matches:
-                continue
-
-            # 安全验证匹配结果
-            good_matches = []
-            for match_group in matches:
-                # 确保match_group有足够元素防止索引错误
-                if len(match_group) < 2:
-                    continue
-                m, n = match_group
-                if m.distance < 0.7 * n.distance:
-                    good_matches.append(m)
+    def inference(self, input_data: np.ndarray):
+        if self.model_type == 'uav_and_bird':
+            # 返回所有输出
+            outputs = self.session.run(None, {self.input_name: input_data})
+            # 模型推理完成
+            return outputs
+        elif self.model_type in ['Anti_UAV', 'UAV-250411']:
+            scale_factor = np.array([[1, 1]], dtype=np.float32)
+            output = self.session.run(
+                [self.output_name],
+                {self.input_name: input_data, 'scale_factor': scale_factor}
+            )[0]
+            # 模型推理完成
+            return output
+        else:
+            output = self.session.run(
+                [self.output_name],
+                {self.input_name: input_data}
+            )[0]
+            # 模型推理完成
+            return output
 
-            # 计算优质匹配数量
-            if len(good_matches) > 15:  # 匹配阈值
-                return True
-        return False
+    # ORB特征匹配误报检测方法已移除
 
-    def postprocess(self, detections: np.ndarray, image_orig: np.ndarray, image_path: str) -> tuple:
-        """后处理检测结果"""
+    def postprocess(self, detections, image_orig: np.ndarray, image_path: str) -> tuple:
+        # 开始后处理
+        
         valid_detections = 0
         img_out = image_orig.copy()
         detections_list = []
         
-        # 过滤低置信度检测
-        keep_idx = (detections[:, 1] > self.confThreshold)
-        detections = detections[keep_idx]
-        
-        if len(detections) == 0:
-            return 0, img_out, []
+        if self.model_type == 'Anti_UAV':
+            # Anti_UAV模型的后处理逻辑
+            keep_idx = (detections[:, 1] > self.confThreshold)
+            detections = detections[keep_idx]
             
-        # 坐标转换
-        ratioh = self.orig_h / self.input_size[1]
-        ratiow = self.orig_w / self.input_size[0]
-        detections[:, 2
-        :6] *= np.array([ratiow, ratioh, ratiow, ratioh])
-        
-        # NMS处理
-        keep = self.nms(detections[:, 2:6], detections[:, 1:2], self.confThreshold, 0.4)
-        
-        for idx in keep:
-            class_id = int(detections[idx, 0])
-            confidence = detections[idx, 1]
-            x1, y1, x2, y2 = detections[idx, 2:6].astype(int)
+            if len(detections) == 0:
+                return 0, img_out, []
+            ratioh = self.orig_h / self.input_size[1]
+            ratiow = self.orig_w / self.input_size[0]
             
-            # 计算检测框面积比例
-            bbox_area = (x2 - x1) * (y2 - y1)
-            image_area = self.orig_w * self.orig_h
-            if bbox_area / image_area > self.max_bbox_ratio:
-                continue
-
-            # 截取ROI区域进行误报验证
-            roi = image_orig[y1:y2, x1:x2]
-            if roi.size == 0:
-                continue
+            detections[:, 2:6] *= np.array([ratiow, ratioh, ratiow, ratioh])
+            keep = self.nms(detections[:, 2:6], detections[:, 1:2], self.confThreshold, 0.4)
+            
+            for idx in keep:
+                class_id = int(detections[idx, 0])
+                confidence = detections[idx, 1]
+                x1, y1, x2, y2 = detections[idx, 2:6].astype(int)
+                bbox_area = (x2 - x1) * (y2 - y1)
+                image_area = self.orig_w * self.orig_h
                 
-            if self._is_false_positive(roi):
-                continue
+                if bbox_area / image_area > self.max_bbox_ratio:
+                    continue
+                roi = image_orig[y1:y2, x1:x2]
+                if roi.size == 0:
+                    continue
+                # 误报过滤已移除
+                target_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{valid_detections}.jpg"
+                cv2.imwrite(os.path.join(self.targets_dir, target_filename), roi)
+                label = f'{self.class_names[class_id]} {confidence:.2f}'
+                cv2.rectangle(img_out, (x1, y1), (x2, y2), (255, 0, 0), 4)
+                cv2.putText(img_out, label, (x1, y1 - 10), 
+                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
+                valid_detections += 1
+                detections_list.append({
+                    'class_id': class_id,
+                    'confidence': float(confidence),
+                    'bbox': [x1, y1, x2, y2],
+                    'orig_w': self.orig_w,
+                    'orig_h': self.orig_h
+                })
+        elif self.model_type == 'UAV-250411':
+            # UAV-250411模型的后处理逻辑
+            keep_idx = (detections[:, 1] > self.confThreshold)
+            detections = detections[keep_idx]
+            
+            if len(detections) == 0:
+                return 0, img_out, []
+            ratioh = self.orig_h / self.input_size[1]
+            ratiow = self.orig_w / self.input_size[0]
+            
+            detections[:, 2:6] *= np.array([ratiow, ratioh, ratiow, ratioh])
+            keep = self.nms(detections[:, 2:6], detections[:, 1:2], self.confThreshold, 0.4)
+            
+            for idx in keep:
+                class_id = int(detections[idx, 0])
+                confidence = detections[idx, 1]
+                x1, y1, x2, y2 = detections[idx, 2:6].astype(int)
+                bbox_area = (x2 - x1) * (y2 - y1)
+                image_area = self.orig_w * self.orig_h
                 
-            # 生成唯一文件名并保存目标
-            target_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{valid_detections}.jpg"
-            cv2.imwrite(os.path.join(self.targets_dir, target_filename), roi)
+                if bbox_area / image_area > self.max_bbox_ratio:
+                    continue
+                roi = image_orig[y1:y2, x1:x2]
+                if roi.size == 0:
+                    continue
+                # 误报过滤已移除
+                target_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{valid_detections}.jpg"
+                cv2.imwrite(os.path.join(self.targets_dir, target_filename), roi)
+                label = f'{self.class_names[class_id]} {confidence:.2f}'
+                cv2.rectangle(img_out, (x1, y1), (x2, y2), (255, 0, 0), 4)
+                cv2.putText(img_out, label, (x1, y1 - 10), 
+                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
+                valid_detections += 1
+                detections_list.append({
+                    'class_id': class_id,
+                    'confidence': float(confidence),
+                    'bbox': [x1, y1, x2, y2],
+                    'orig_w': self.orig_w,
+                    'orig_h': self.orig_h
+                })
+        elif self.model_type == 'uav_and_bird':
+            # 根据用户提供的详细说明,模型输出9个张量,按3个尺度分组:
+            # 小尺度 (20x20): 输出0(bbox), 输出1(cls), 输出2(quality)
+            # 中等尺度 (40x40): 输出3(bbox), 输出4(cls), 输出5(quality) 
+            # 大尺度 (80x80): 输出6(bbox), 输出7(cls), 输出8(quality)
+            if len(detections) != 9:
+                return 0, img_out, []
             
-            # 绘制检测框和标签
-            label = f'{self.class_names[class_id]} {confidence:.2f}'
-            cv2.rectangle(img_out, (x1, y1), (x2, y2), (255, 0, 0), 4)
-            cv2.putText(img_out, label, (x1, y1 - 10), 
-                        cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
-            valid_detections += 1
-            detections_list.append({
-                'class_id': class_id,
-                'confidence': float(confidence),
-                'bbox': [x1, y1, x2, y2],
-                'orig_w': self.orig_w,
-                'orig_h': self.orig_h
-            })
+            # 定义尺度信息:(bbox_idx, cls_idx, quality_idx, grid_size, stride)
+            scales = [
+                (0, 1, 2, 20, 32),  # 小尺度特征图,用于检测大物体
+                (3, 4, 5, 40, 16),  # 中等尺度特征图,用于检测中等物体
+                (6, 7, 8, 80, 8),   # 大尺度特征图,用于检测小物体
+            ]
             
+            all_boxes, all_scores, all_classes = [], [], []
+            
+            for scale_idx, (bbox_idx, cls_idx, quality_idx, grid_size, stride) in enumerate(scales):
+                # 获取当前尺度的输出
+                bbox_output = detections[bbox_idx]      # (1, 68, H, W)
+                cls_output = detections[cls_idx]        # (1, 2, H, W) 
+                quality_output = detections[quality_idx] # (1, 1, H, W)
+                
+                # 移除batch维度
+                bbox_pred = bbox_output[0]    # (68, H, W)
+                cls_pred = cls_output[0]      # (2, H, W)
+                quality_pred = quality_output[0] # (1, H, W)
+                
+                H, W = bbox_pred.shape[1], bbox_pred.shape[2]
+                
+                # 创建网格坐标 - 添加0.5偏移表示像素中心
+                grid_y, grid_x = np.meshgrid(np.arange(H), np.arange(W), indexing='ij')
+                grid_x = (grid_x + 0.5).flatten()  # (H*W,) - 像素中心偏移
+                grid_y = (grid_y + 0.5).flatten()  # (H*W,) - 像素中心偏移
+                
+                # 重塑张量为 (H*W, channels)
+                bbox_pred = bbox_pred.reshape(68, -1).T    # (H*W, 68)
+                cls_pred = cls_pred.reshape(2, -1).T       # (H*W, 2)
+                quality_pred = quality_pred.reshape(-1)    # (H*W,)
+                
+                # 解码边界框 - Distribution Focal Loss解码
+                # 68个通道 = 4个边界 * 17个分布值
+                bbox_pred = bbox_pred.reshape(-1, 4, 17)  # (H*W, 4, 17)
+                
+                # 对每个边界的17个值应用softmax
+                bbox_pred_softmax = np.exp(bbox_pred) / np.sum(np.exp(bbox_pred), axis=2, keepdims=True)
+                
+                # 创建范围向量 [0, 1, 2, ..., 16]
+                range_vector = np.arange(17).reshape(1, 1, 17)
+                
+                # 计算期望距离值
+                distances = np.sum(bbox_pred_softmax * range_vector, axis=2)  # (H*W, 4)
+                d_left, d_top, d_right, d_bottom = distances[:, 0], distances[:, 1], distances[:, 2], distances[:, 3]
+                
+                # 计算最终边界框坐标
+                x1 = (grid_x - d_left) * stride
+                y1 = (grid_y - d_top) * stride
+                x2 = (grid_x + d_right) * stride
+                y2 = (grid_y + d_bottom) * stride
+                
+                # 组合边界框
+                boxes = np.stack([x1, y1, x2, y2], axis=1)  # (H*W, 4)
+                
+                # 计算最终置信度分数
+                # cls_pred已经是sigmoid激活后的结果,quality_pred是clip后的结果
+                final_scores = cls_pred * quality_pred[:, None]  # (H*W, 2)
+                
+                # 获取最大置信度和对应类别
+                max_scores = np.max(final_scores, axis=1)  # (H*W,)
+                class_ids = np.argmax(final_scores, axis=1)  # (H*W,)
+                
+                # 置信度过滤
+                mask = max_scores > self.confThreshold
+                
+                if np.sum(mask) > 0:
+                    filtered_boxes = boxes[mask]
+                    filtered_scores = max_scores[mask]
+                    filtered_classes = class_ids[mask]
+                    
+                    all_boxes.append(filtered_boxes)
+                    all_scores.append(filtered_scores)
+                    all_classes.append(filtered_classes)
+            
+            # 检查是否有有效检测
+            if len(all_boxes) == 0 or all([len(b) == 0 for b in all_boxes]):
+                return 0, img_out, []
+            
+            # 合并所有尺度的检测结果
+            final_boxes = np.concatenate(all_boxes, axis=0)
+            final_scores = np.concatenate(all_scores, axis=0)
+            final_classes = np.concatenate(all_classes, axis=0)
+            
+            # 坐标缩放到原图尺寸
+            ratioh = self.orig_h / self.input_size[1]
+            ratiow = self.orig_w / self.input_size[0]
+            
+            final_boxes[:, [0, 2]] *= ratiow  # x坐标
+            final_boxes[:, [1, 3]] *= ratioh  # y坐标
+            
+            # NMS处理
+            keep = self.nms(final_boxes, final_scores[:, None], self.confThreshold, 0.4)
+            
+            # 处理最终检测结果
+            for idx in keep:
+                x1, y1, x2, y2 = final_boxes[idx].astype(int)
+                confidence = final_scores[idx]
+                class_id = int(final_classes[idx])
+                
+                # 确保坐标在图像范围内
+                x1 = max(0, min(x1, self.orig_w - 1))
+                y1 = max(0, min(y1, self.orig_h - 1))
+                x2 = max(0, min(x2, self.orig_w - 1))
+                y2 = max(0, min(y2, self.orig_h - 1))
+                
+                bbox_area = (x2 - x1) * (y2 - y1)
+                image_area = self.orig_w * self.orig_h
+                
+                if bbox_area / image_area > self.max_bbox_ratio:
+                    continue
+                    
+                if x2 <= x1 or y2 <= y1:
+                    continue
+                    
+                roi = image_orig[y1:y2, x1:x2]
+                if roi.size == 0:
+                    continue
+                    
+                # 误报过滤已移除
+                target_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{valid_detections}.jpg"
+                cv2.imwrite(os.path.join(self.targets_dir, target_filename), roi)
+                label = f'{self.class_names[class_id]} {confidence:.2f}'
+                cv2.rectangle(img_out, (x1, y1), (x2, y2), (255, 0, 0), 4)
+                cv2.putText(img_out, label, (x1, y1 - 10), 
+                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
+                valid_detections += 1
+                detections_list.append({
+                    'class_id': class_id,
+                    'confidence': float(confidence),
+                    'bbox': [x1, y1, x2, y2],
+                    'orig_w': self.orig_w,
+                    'orig_h': self.orig_h
+                })
+                
         return valid_detections, img_out, detections_list
 
     def process_image(self, image_path: str) -> int:
@@ -271,8 +438,11 @@ class ONNXDetector:
         # 根据设置保存图片
         if valid_count > 0 or self.save_empty:
             cv2.imwrite(output_path, processed_img)
+            # 输出图像已保存
         else:
             output_path = None
+            # 未保存图像 (无检测且save_empty=False)
+            
         self.image_count += 1
         
         # 记录检测信息
@@ -280,8 +450,40 @@ class ONNXDetector:
             record['detections'] = detections_list
         
         self.detection_records.append(record)
+        # 处理完成
         return valid_count
 
+def get_model_type(model_path: str) -> str:
+    """
+    根据ONNX模型的输入输出结构自动判断模型类型。
+    返回值:
+        'Anti_UAV':250411_Anti_UAV.onnx
+        'UAV-250411':UAV-250411.onnx
+        'uav_and_bird':uav_and_bird.onnx
+        'unknown':无法识别
+    """
+    try:
+        model = onnx.load(model_path)
+        input_names = [i.name for i in model.graph.input]
+        output_names = [o.name for o in model.graph.output]
+        # 判断Anti_UAV模型
+        if 'scale_factor' in input_names:
+            if any(name.startswith('multiclass_nms3') for name in output_names):
+                return 'Anti_UAV'
+            elif len(output_names) == 2 and output_names[0].startswith('tmp_'):
+                return 'UAV-250411'
+            else:
+                return 'UAV-250411'
+        else:
+            # 没有scale_factor输入,且输出较多
+            if len(output_names) > 2:
+                return 'uav_and_bird'
+        return 'unknown'
+    except Exception as e:
+        # 模型类型识别失败
+        pass
+        return 'unknown'
+
 # 命令行接口
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(description='UAV Detection using ONNX model')
@@ -289,11 +491,14 @@ if __name__ == '__main__':
     parser.add_argument('--threshold', type=float, default=0.5, help='检测置信度阈值')
     parser.add_argument('--output', type=str, default=None, help='输出目录路径,默认为输入目录名+_results')
     parser.add_argument('--max-bbox-ratio', type=float, default=0.05,
-                      help='检测框最大面积比例阈值,默认0.05')
+                        help='检测框最大面积比例阈值,默认0.05')
     parser.add_argument('--save-empty', action='store_true',
-                      help='是否保存未检测到目标的图片')
+                        help='是否保存未检测到目标的图片')
     parser.add_argument('--gui', action='store_true',
-                      help='启用图形界面选择输入目录')
+                        help='启用图形界面选择输入目录')
+    parser.add_argument('--model-type', type=str, choices=['Anti_UAV', 'UAV-250411', 'uav_and_bird'],
+                        help='指定模型类型,不指定则自动识别')
+    parser.add_argument('--model-path', type=str, help='指定模型路径,不指定则根据模型类型自动选择')
     args = parser.parse_args()
 
     # GUI模式处理
@@ -302,11 +507,13 @@ if __name__ == '__main__':
             threshold=args.threshold,
             max_bbox_ratio=args.max_bbox_ratio,
             output_dir=args.output,
-            save_empty=args.save_empty
+            save_empty=args.save_empty,
+            model_type=args.model_type,
+            model_path=args.model_path
         )
         input_dir = detector.select_input_directory()
         if not input_dir:
-            print("未选择目录,程序退出")
+            # 未选择目录,程序退出
             exit()
         args.input = input_dir
     
@@ -316,12 +523,14 @@ if __name__ == '__main__':
         max_bbox_ratio=args.max_bbox_ratio,
         output_dir=args.output,
         save_empty=args.save_empty,
-        input_dir=args.input if os.path.isdir(args.input) else None
+        input_dir=args.input if os.path.isdir(args.input) else None,
+        model_type=args.model_type,
+        model_path=args.model_path
     )
 
     def process_single(image_path: str):
         detections = detector.process_image(image_path)
-        print(f'处理 {os.path.basename(image_path)} 完成,检测到 {detections} 个目标')
+        # 图像处理完成
 
     if os.path.isdir(args.input):
         total = 0
@@ -330,11 +539,11 @@ if __name__ == '__main__':
             image_files.extend([os.path.join(root, f) for f in files if f.lower().endswith('.jpg')])
         for img_file in tqdm(image_files, desc='Processing images'):
             total += detector.process_image(img_file)
-        print(f'批量处理完成!共检测到 {total} 个目标')
+        # 批量处理完成
     
         # 生成CSV报告
-        csv_path = os.path.join(detector.output_dir, 'detection_report.csv')
+        csv_path = os.path.join(detector.output_dir, f'detection_report_{detector.model_type}.csv')
         ReportGenerator(detector).generate_csv(csv_path)
-        print(f'CSV报告已生成: {csv_path}')
+        # CSV报告已生成
     else:
         detections = detector.process_image(args.input)

+ 3 - 6
src/utils/split_dataset.py

@@ -14,12 +14,12 @@ os.makedirs(TEST_DIR, exist_ok=True)
 def split_dataset():
     # 1. 扫描源目录
     if not os.path.exists(SRC_DIR):
-        print(f"源目录不存在: {SRC_DIR}")
+        # 源目录不存在
         return
     
     all_files = [f for f in os.listdir(SRC_DIR) if f.lower().endswith('.jpg')]
     if not all_files:
-        print("未找到JPG文件")
+        # 未找到JPG文件
         return
 
     # 2. 按前缀分组
@@ -52,10 +52,7 @@ def split_dataset():
                 total_copied += 1
 
     # 输出统计信息
-    print(f"处理完成:\n"
-          f"- 共发现 {len(groups)} 个分组\n"
-          f"- 总计复制 {total_copied} 张测试图片\n"
-          f"- 输出目录: {TEST_DIR}")
+    # 数据集分割完成
 
 if __name__ == '__main__':
     split_dataset()

+ 2 - 6
src/utils/update_labels.py

@@ -27,13 +27,9 @@ df['Confirmed Positive'] = df['Image File'].apply(lambda x: os.path.basename(x)
 # 保存更新后的CSV文件
 df.to_csv(output_csv, index=False)
 
-print(f"处理完成!已更新 {len(confirmed_positives)} 个确认的阳性样本。")
-print(f"更新后的CSV文件已保存至:{output_csv}")
+# 标签更新完成
 
 # 显示统计信息
 total_images = len(df)
 confirmed_positive_count = df['Confirmed Positive'].sum()
-print(f"\n统计信息:")
-print(f"总图像数:{total_images}")
-print(f"确认阳性数:{confirmed_positive_count}")
-print(f"确认阳性比例:{confirmed_positive_count/total_images*100:.2f}%") 
+# 统计信息已生成