From f873ebfd5b6a49ce57d6c70a530adeb360b5a244 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Sun, 8 Jun 2025 16:28:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BA=A2=E5=A4=96=E6=88=90?= =?UTF-8?q?=E5=83=8F=E5=88=B6=E5=AF=BC=E5=AF=BC=E5=BC=B9=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=BA=86=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E7=AE=97=E6=B3=95=E5=90=84=E8=A3=85=E5=A4=87?= =?UTF-8?q?=E7=9A=84=E7=89=B9=E5=BE=81=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Jamming/LaserDecoyTests.cs | 2 +- .../src/Utils/AtmosphereDllWrapperTests.cs | 14 +- .../data/equipments/tanks/mbt_001.toml | 12 +- .../src/Guidance/InfraredImageGenerator.cs | 54 +- .../src/Guidance/InfraredTargetRecognizer.cs | 698 ++++++++++-------- .../Guidance/MillimeterWaveGuidanceSystem.cs | 2 +- .../prtformance_test_result_0605.md | 31 + 算法优化第一阶段任务进度.md | 177 ----- 8 files changed, 489 insertions(+), 501 deletions(-) delete mode 100644 算法优化第一阶段任务进度.md diff --git a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs index 462a6c0..6ae0de4 100644 --- a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs @@ -860,7 +860,7 @@ namespace ThreatSource.Tests.Jamming // 计算功率比值,分析目标选择 double powerRatio = decoyReceivedPower / realReceivedPower; - Debug.WriteLine($"诱偏/真实目标功率比: {powerRatio:F6}"); + Debug.WriteLine($"诱偏/真实目标功率比: {powerRatio:E3}"); Debug.WriteLine($"功率比例分析: {(powerRatio > 1 ? "诱偏目标功率更强" : "真实目标功率更强")}"); } diff --git a/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs b/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs index fa62296..8aa77d0 100644 --- a/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs +++ b/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs @@ -33,7 +33,7 @@ namespace ThreatSource.Tests.Utils ); // Assert - 验证结果在合理范围内 - Debug.WriteLine($"激光透过率: {transmittance:F6}"); + Debug.WriteLine($"激光透过率: {transmittance:E3}"); Assert.True(transmittance >= 0.0); Assert.True(transmittance <= 1.0); Assert.NotEqual(0.0, transmittance); // 确保不是0 @@ -64,7 +64,7 @@ namespace ThreatSource.Tests.Utils ); // Assert - 验证结果在合理范围内 - Debug.WriteLine($"红外透过率: {transmittance:F6}"); + Debug.WriteLine($"红外透过率: {transmittance:E3}"); Assert.True(transmittance >= 0.0); Assert.True(transmittance <= 1.0); Assert.NotEqual(0.0, transmittance); // 确保不是0 @@ -95,7 +95,7 @@ namespace ThreatSource.Tests.Utils ); // Assert - 验证结果在合理范围内 - Debug.WriteLine($"湍流效应: {turbulenceEffect:F6}"); + Debug.WriteLine($"湍流效应: {turbulenceEffect:E3}"); Assert.True(turbulenceEffect >= 0.0); Assert.True(turbulenceEffect <= 1.0); Assert.NotEqual(0.0, turbulenceEffect); // 确保不是0 @@ -116,7 +116,7 @@ namespace ThreatSource.Tests.Utils ); // Assert - 验证结果在合理范围内 - Debug.WriteLine($"烟幕透过率: {smokeTransmittance:F6}"); + Debug.WriteLine($"烟幕透过率: {smokeTransmittance:E3}"); Assert.True(smokeTransmittance >= 0.0); Assert.True(smokeTransmittance <= 1.0); } @@ -164,9 +164,9 @@ namespace ThreatSource.Tests.Utils distance * 1000, radiationType, wavelength, rainyWeather); // 转换为米 // Assert - 验证不同天气条件对透过率有影响 - Debug.WriteLine($"晴天透过率: {clearTransmittance:F6}"); - Debug.WriteLine($"雾天透过率: {foggyTransmittance:F6}"); - Debug.WriteLine($"雨天透过率: {rainyTransmittance:F6}"); + Debug.WriteLine($"晴天透过率: {clearTransmittance:E3}"); + Debug.WriteLine($"雾天透过率: {foggyTransmittance:E3}"); + Debug.WriteLine($"雨天透过率: {rainyTransmittance:E3}"); // 验证所有值在有效范围内 Assert.True(clearTransmittance >= 0.0 && clearTransmittance <= 1.0); diff --git a/ThreatSource/data/equipments/tanks/mbt_001.toml b/ThreatSource/data/equipments/tanks/mbt_001.toml index f4004e5..fabe142 100644 --- a/ThreatSource/data/equipments/tanks/mbt_001.toml +++ b/ThreatSource/data/equipments/tanks/mbt_001.toml @@ -27,14 +27,14 @@ BarrelLength = 5.8 # 炮管长度 (米) [Properties.ThermalPattern] # 热辐射特征模型 StaticPatternSource = [ # 静态时温度分布 - [40, 45, 80], - [35, 40, 90], - [50, 50, 60] + [40, 45, 80], # 前部装甲 + [35, 40, 90], # 中部装甲 + [50, 50, 60] # 后部发动机 ] MovingPatternSource = [ # 移动时温度分布 - [45, 50, 85], - [40, 45, 95], - [65, 65, 75] + [45, 50, 85], # 前部装甲 + [40, 45, 95], # 中部装甲 + [65, 65, 75] # 后部发动机 ] [Properties.RcsPattern] diff --git a/ThreatSource/src/Guidance/InfraredImageGenerator.cs b/ThreatSource/src/Guidance/InfraredImageGenerator.cs index 651e386..b89aabd 100644 --- a/ThreatSource/src/Guidance/InfraredImageGenerator.cs +++ b/ThreatSource/src/Guidance/InfraredImageGenerator.cs @@ -6,6 +6,7 @@ using ThreatSource.Simulation; using System.Diagnostics; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace ThreatSource.Guidance { @@ -98,17 +99,34 @@ namespace ThreatSource.Guidance { if (DoubleArrayPool.TryDequeue(out var array)) { - // 清零重用的数组 - for (int y = 0; y < imageHeight; y++) - { - for (int x = 0; x < imageWidth; x++) - { - array[y, x] = -1.0; - } - } + // 使用优化的数组清零方法 + ClearDoubleArrayToNegativeOne(array); return array; } - return new double[imageHeight, imageWidth]; + + // 创建新数组并初始化为-1.0 + var newArray = new double[imageHeight, imageWidth]; + ClearDoubleArrayToNegativeOne(newArray); + return newArray; + } + + /// + /// 高效清零double数组为-1.0 + /// + private void ClearDoubleArrayToNegativeOne(double[,] array) + { + // 使用安全的多维数组填充方法 + int height = array.GetLength(0); + int width = array.GetLength(1); + + // 优化:按行填充,利用内存局部性 + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + array[y, x] = -1.0; + } + } } /// @@ -241,7 +259,7 @@ namespace ThreatSource.Guidance double angleX = Math.Atan2(x, z); double angleY = Math.Atan2(y, z); - Debug.WriteLine($"投影角度: X={angleX:F6} 弧度, Y={angleY:F6} 弧度"); + Debug.WriteLine($"投影角度: X={angleX:E3} 弧度, Y={angleY:E3} 弧度"); return (angleX, angleY); } @@ -391,7 +409,7 @@ namespace ThreatSource.Guidance smokeIntensityLayer[y, x] = Math.Max(smokeIntensityLayer[y, x], smokeIntensity); } } - Debug.WriteLine($"记录遮蔽烟幕(Wall): 中心({smokeCenterX},{smokeCenterY}), 尺寸{pixelWidth}x{pixelHeight}px, 强度{smokeIntensity:F6}"); + Debug.WriteLine($"记录遮蔽烟幕(Wall): 中心({smokeCenterX},{smokeCenterY}), 尺寸{pixelWidth}x{pixelHeight}px, 强度{smokeIntensity:E3}"); break; case SmokeScreenType.Cloud: @@ -420,7 +438,7 @@ namespace ThreatSource.Guidance } } } - Debug.WriteLine($"记录遮蔽烟幕(Cloud): 中心({smokeCenterX},{smokeCenterY}), 半径{pixelRadius}px, 强度{smokeIntensity:F6}"); + Debug.WriteLine($"记录遮蔽烟幕(Cloud): 中心({smokeCenterX},{smokeCenterY}), 半径{pixelRadius}px, 强度{smokeIntensity:E3}"); break; } } @@ -537,8 +555,8 @@ namespace ThreatSource.Guidance return; } - int halfLength = pixelLength / 2; - int halfWidth = pixelWidth / 2; + int halfLength = Math.Max(1, pixelLength / 2); // 防止除零 + int halfWidth = Math.Max(1, pixelWidth / 2); // 防止除零 int pixelsSet = 0; double maxSetIntensity = 0; @@ -615,9 +633,9 @@ namespace ThreatSource.Guidance int pixelYInBox = dy + halfWidth; int pixelXInBox = dx + halfLength; - // Map to pattern indices [0, 2] - int patternRow = (int)Math.Floor(pixelYInBox / patternPixelWidth); - int patternCol = (int)Math.Floor(pixelXInBox / patternPixelHeight); // X maps to Col + // Map to pattern indices [0, 2] - 修正坐标映射 + int patternRow = (int)Math.Floor(pixelYInBox / patternPixelHeight); // Y坐标用Height + int patternCol = (int)Math.Floor(pixelXInBox / patternPixelWidth); // X坐标用Width // Clamp indices to [0, 2] patternRow = Math.Max(0, Math.Min(2, patternRow)); @@ -658,7 +676,7 @@ namespace ThreatSource.Guidance } } - Debug.WriteLine($"目标基于ThermalPattern强度分布: 像素设置: {pixelsSet}, 最大强度: {maxSetIntensity:F6} W/sr"); + Debug.WriteLine($"目标基于ThermalPattern强度分布: 像素设置: {pixelsSet}, 最大强度: {maxSetIntensity:E3} W/sr"); } /// diff --git a/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs b/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs index c2eeaa2..609bd73 100644 --- a/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs +++ b/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs @@ -86,7 +86,14 @@ namespace ThreatSource.Guidance /// private const double SMOKE_COVERAGE_THRESHOLD = 0.75; - + // **性能优化:静态常量Sobel算子,避免重复分配** + private static readonly double[,] SOBEL_X = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; + private static readonly double[,] SOBEL_Y = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; + + // **性能优化:重用数组,避免频繁分配** + private readonly double[] _histogramBuffer = new double[10]; + private readonly double[,] _gridGradientsBuffer = new double[3, 3]; + private readonly int[,] _gridCountsBuffer = new int[3, 3]; /// /// 图像预扫描结果 @@ -99,29 +106,133 @@ namespace ThreatSource.Guidance public int MaxX { get; set; } public int MaxY { get; set; } public double Density { get; set; } - public int Width => MaxX - MinX + 1; - public int Height => MaxY - MinY + 1; - public double AspectRatio => Height > 0 ? (double)Width / Height : 1.0; + public readonly int Width => MaxX - MinX + 1; + public readonly int Height => MaxY - MinY + 1; + public readonly double AspectRatio => Height > 0 ? (double)Width / Height : 1.0; // 早期退出条件 - public bool IsEmpty => PixelsAboveThreshold == 0; - public bool IsTooSmall => PixelsAboveThreshold < BLOB_MIN_AREA_THRESHOLD; - public bool IsSinglePixel => PixelsAboveThreshold <= 2; - public bool IsLinearTarget => AspectRatio > 10.0 || AspectRatio < 0.1; // 极端长宽比 - public bool IsTooSparse => Density < 0.05; // 密度过低,可能是噪声 - public bool IsSimpleTarget => Density > 0.8 && PixelsAboveThreshold < 1000; // 相对较小且密集 + public readonly bool IsEmpty => PixelsAboveThreshold == 0; + public readonly bool IsTooSmall => PixelsAboveThreshold < BLOB_MIN_AREA_THRESHOLD; + public readonly bool IsSinglePixel => PixelsAboveThreshold <= 2; + public readonly bool IsLinearTarget => AspectRatio > 10.0 || AspectRatio < 0.1; // 极端长宽比 + public readonly bool IsTooSparse => Density < 0.05; // 密度过低,可能是噪声 + public readonly bool IsSimpleTarget => Density > 0.8 && PixelsAboveThreshold < 1000; // 相对较小且密集 // 检查是否位于图像边缘 - public bool IsAtImageEdge(int imageWidth, int imageHeight) + public readonly bool IsAtImageEdge(int imageWidth, int imageHeight) { return MinX <= 1 || MinY <= 1 || MaxX >= imageWidth - 2 || MaxY >= imageHeight - 2; } } + /// + /// 统一图像分析结果 - 单次遍历完成多项计算 + /// + private struct ImageAnalysisResult + { + // 全图统计信息 + public double MinIntensity { get; set; } + public double MaxIntensity { get; set; } + public double MeanIntensity { get; set; } + public double TotalIntensity { get; set; } + public int TotalPixels { get; set; } + public int ValidPixels { get; set; } // 强度 > 0 的像素数 + + // 区域统计信息(如果指定了目标区域) + public double CenterIntensity { get; set; } + public int CenterPixelCount { get; set; } + public readonly double AvgCenterIntensity => CenterPixelCount > 0 ? CenterIntensity / CenterPixelCount : 0; + public readonly double CenterIntensityRatio => TotalPixels > 0 && TotalIntensity > 0 && CenterPixelCount > 0 ? + (CenterIntensity / CenterPixelCount) / (TotalIntensity / TotalPixels) : 0; + + // 直方图数据(10-bin) + public double[]? Histogram { get; set; } + public double ConcentrationScore { get; set; } // 高强度bin的集中度 + + // 梯度信息(3x3网格) + public double[,]? GridGradients { get; set; } + public int[,]? GridCounts { get; set; } + public double AvgGradient { get; set; } + public double MaxGradient { get; set; } + + // 烟幕覆盖信息 + public int SmokeCoveredPixels { get; set; } + public readonly double SmokeCoverageRatio => TotalPixels > 0 ? (double)SmokeCoveredPixels / TotalPixels : 0; + + // 计算动态阈值 + public readonly double CalculateThreshold(double thresholdFactor = 0.05) + { + if (ValidPixels == 0 || MaxIntensity <= MinIntensity) return 0; + double dynamicRange = MaxIntensity - MinIntensity; + return MinIntensity + dynamicRange * thresholdFactor; + } + + // 计算强度模式得分 + public readonly double CalculateIntensityPattern() + { + if (Histogram == null || ConcentrationScore == 0) return 0; + + // 通用强度模式计算:适用于Tank、APC、Helicopter等所有目标类型 + // 基于热分布的两个核心特征:集中度 + 分布特征 + + // 1. 高温区域集中度(所有目标都有发动机等热源) + double hotRegionScore = ConcentrationScore; + + // 2. 温度分布的非均匀性(不同目标有不同的分布模式) + double distributionScore = 0; + if (Histogram.Length >= 10) + { + // 计算温度分布的多样性和对比度 + double lowTempRegion = 0; // 低温区域(前30%的bin) + double midTempRegion = 0; // 中温区域(中40%的bin) + double highTempRegion = 0; // 高温区域(后30%的bin) + + for (int i = 0; i < 3; i++) lowTempRegion += Histogram[i]; // 前30% + for (int i = 3; i < 7; i++) midTempRegion += Histogram[i]; // 中40% + for (int i = 7; i < 10; i++) highTempRegion += Histogram[i]; // 后30% + + // 通用特征:良好的目标应该有明显的温度对比 + // - Tank: 前部低温 + 后部高温 + // - APC: 相对均匀但有温度差异 + // - Helicopter: 中部极高温 + 其他区域低温 + + if (highTempRegion > 0.05) // 必须有高温区域 + { + // 温度对比度:高温区域与低温区域的差异 + double temperatureContrast = highTempRegion - lowTempRegion; + + // 温度分布的复杂度:三个区域都有分布表示目标结构复杂 + double distributionComplexity = 0; + if (lowTempRegion > 0.02 && midTempRegion > 0.02 && highTempRegion > 0.02) + { + distributionComplexity = 0.3; // 奖励复杂的温度分布 + } + + // 综合分布得分 + distributionScore = Math.Min(1.0, + Math.Max(0, temperatureContrast) * 2.0 + distributionComplexity); + } + } + + // 3. 中心强度特征(保留原有逻辑作为补充) + double centerScore = CenterIntensityRatio > 0 ? Math.Min(1.0, CenterIntensityRatio) : 0; + + // 4. 综合得分:集中度50% + 分布特征30% + 中心特征20% + return Math.Max(0, Math.Min(1, + hotRegionScore * 0.5 + distributionScore * 0.3 + centerScore * 0.2)); + } + + // 计算温度梯度得分 + public readonly double CalculateTemperatureGradient() + { + return Math.Max(0, Math.Min(1, AvgGradient)); + } + } + /// /// 创建简单分割结果(跳过Union-Find) /// - private ImageSegment CreateSimpleSegment(int minX, int minY, int maxX, int maxY) + private static ImageSegment CreateSimpleSegment(int minX, int minY, int maxX, int maxY) { int width = maxX - minX + 1; int height = maxY - minY + 1; @@ -137,28 +248,236 @@ namespace ThreatSource.Guidance ); } + /// + /// 统一图像区域分析 - 单次遍历完成多项计算 + /// + /// 红外图像 + /// 目标区域(null表示全图分析) + /// 是否包含梯度计算 + /// 是否包含直方图计算 + /// 统一分析结果 + private static ImageAnalysisResult AnalyzeImageRegion( + InfraredImage image, + ImageSegment? targetRegion = null, + bool includeGradient = false, + bool includeHistogram = false) + { + var result = new ImageAnalysisResult + { + MinIntensity = double.MaxValue, + MaxIntensity = double.MinValue, + TotalIntensity = 0, + TotalPixels = 0, + ValidPixels = 0, + CenterIntensity = 0, + CenterPixelCount = 0, + SmokeCoveredPixels = 0 + }; + + // 确定分析区域 + int startX, endX, startY, endY; + if (targetRegion.HasValue) + { + var region = targetRegion.Value; + startX = Math.Max(0, region.Center.X - region.Size.Width / 2); + endX = Math.Min(image.Width - 1, region.Center.X + region.Size.Width / 2); + startY = Math.Max(0, region.Center.Y - region.Size.Height / 2); + endY = Math.Min(image.Height - 1, region.Center.Y + region.Size.Height / 2); + } + else + { + startX = 0; endX = image.Width - 1; + startY = 0; endY = image.Height - 1; + } + + // 初始化可选计算组件 + const int BINS = 10; + double[]? histogram = includeHistogram ? new double[BINS] : null; + double[,]? gridGradients = includeGradient ? new double[3, 3] : null; + int[,]? gridCounts = includeGradient ? new int[3, 3] : null; + + // 中心区域定义(用于区域分析) + int centerRegionWidth = 0, centerRegionHeight = 0; + int centerStartX = 0, centerEndX = 0, centerStartY = 0, centerEndY = 0; + + if (targetRegion.HasValue) + { + var region = targetRegion.Value; + centerRegionWidth = region.Size.Width / 3; + centerRegionHeight = region.Size.Height / 3; + centerStartX = region.Center.X - centerRegionWidth / 2; + centerEndX = region.Center.X + centerRegionWidth / 2; + centerStartY = region.Center.Y - centerRegionHeight / 2; + centerEndY = region.Center.Y + centerRegionHeight / 2; + } + + // Sobel算子(用于梯度计算) + double[,]? sobelX = includeGradient ? new double[,] {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}} : null; + double[,]? sobelY = includeGradient ? new double[,] {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}} : null; + + // 第一遍扫描:收集基本统计信息 + for (int y = startY; y <= endY; y++) + { + for (int x = startX; x <= endX; x++) + { + double intensity = image.GetIntensity(y, x); + result.TotalPixels++; + result.TotalIntensity += intensity; + + if (intensity > 0) + { + result.ValidPixels++; + result.MinIntensity = Math.Min(result.MinIntensity, intensity); + result.MaxIntensity = Math.Max(result.MaxIntensity, intensity); + } + + // 中心区域统计(仅在区域分析时) + if (targetRegion.HasValue && + x >= centerStartX && x <= centerEndX && + y >= centerStartY && y <= centerEndY) + { + result.CenterIntensity += intensity; + result.CenterPixelCount++; + } + } + } + + // 处理无效情况 + if (result.ValidPixels == 0) + { + result.MinIntensity = 0; + result.MaxIntensity = 0; + result.MeanIntensity = 0; + return result; + } + + result.MeanIntensity = result.TotalIntensity / result.TotalPixels; + double binSize = includeHistogram ? (result.MaxIntensity - result.MinIntensity) / BINS : 0; + + // 计算网格尺寸(用于梯度分析) + int regionWidth = endX - startX + 1; + int regionHeight = endY - startY + 1; + int gridWidth = includeGradient ? regionWidth / 3 : 0; + int gridHeight = includeGradient ? regionHeight / 3 : 0; + + double totalGradient = 0; + int gradientCount = 0; + + // 第二遍扫描:直方图和梯度计算 + for (int y = startY; y <= endY; y++) + { + for (int x = startX; x <= endX; x++) + { + double intensity = image.GetIntensity(y, x); + + // 直方图计算 + if (includeHistogram && intensity > 0 && binSize > 0) + { + int bin = Math.Min(BINS - 1, Math.Max(0, (int)((intensity - result.MinIntensity) / binSize))); + histogram![bin]++; + } + + // 梯度计算(需要边界检查) + if (includeGradient && + y >= startY + 1 && y <= endY - 1 && + x >= startX + 1 && x <= endX - 1) + { + // 计算当前点属于哪个网格 + int gridRow = Math.Min(2, Math.Max(0, (y - startY) * 3 / regionHeight)); + int gridCol = Math.Min(2, Math.Max(0, (x - startX) * 3 / regionWidth)); + + double gradX = 0, gradY = 0; + + // 应用Sobel算子 + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + double value = image.GetIntensity(y + i, x + j); + gradX += value * sobelX![i + 1, j + 1]; + gradY += value * sobelY![i + 1, j + 1]; + } + } + + // 计算归一化梯度 + double gradient = result.MaxIntensity > 0 ? + Math.Sqrt(gradX * gradX + gradY * gradY) / result.MaxIntensity : 0; + + gridGradients![gridRow, gridCol] += gradient; + gridCounts![gridRow, gridCol]++; + totalGradient += gradient; + gradientCount++; + result.MaxGradient = Math.Max(result.MaxGradient, gradient); + } + } + } + + // 完成直方图处理 + if (includeHistogram && histogram != null) + { + // 归一化直方图 + for (int i = 0; i < BINS; i++) + { + histogram[i] /= result.TotalPixels; + } + + // 计算集中度得分(最高30%的bin) + double concentrationScore = 0; + int topBinsStart = (int)(BINS * 0.7); + for (int i = topBinsStart; i < BINS; i++) + { + concentrationScore += histogram[i]; + } + + result.Histogram = histogram!; + result.ConcentrationScore = concentrationScore; + } + + // 完成梯度处理 + if (includeGradient && gridGradients != null) + { + // 计算网格平均梯度 + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + if (gridCounts![i, j] > 0) + { + gridGradients![i, j] /= gridCounts[i, j]; + } + } + } + + result.GridGradients = gridGradients!; + result.GridCounts = gridCounts!; + result.AvgGradient = gradientCount > 0 ? totalGradient / gradientCount : 0; + } + + return result; + } + /// /// 初始化红外图像目标识别器 /// public InfraredTargetRecognizer() { - // 初始化目标特征数据库 - 使用相对特征值 + // 初始化目标特征数据库 - 基于通用强度模式计算方法调整期望值 targetFeatures = new Dictionary { { EquipmentType.Tank, new TargetFeature( aspectRatio: 2.9, // 典型主战坦克长宽比 - intensityPattern: 0.5, // 热量集中分布 - temperatureGradient: 0.3 // 高温度梯度 + intensityPattern: 0.8, // Tank:后部发动机高温,前部装甲低温,温度对比明显 + temperatureGradient: 0.7 // Tank的ThermalPattern实际输出约0.6-0.8 )}, { EquipmentType.APC, new TargetFeature( aspectRatio: 2.1, // 较短的车身 - intensityPattern: 0.8, // 均匀热分布 - temperatureGradient: 0.8 // 中等温度梯度 + intensityPattern: 0.7, // APC:温度分布相对均匀,但仍有发动机热源 + temperatureGradient: 0.5 // APC的ThermalPattern实际输出约0.4-0.6 )}, { EquipmentType.Helicopter, new TargetFeature( aspectRatio: 4.8, // 考虑旋翼长度 - intensityPattern: 0.8, // 发动机热量集中 - temperatureGradient: 0.8 // 较低的温度梯度 + intensityPattern: 0.9, // Helicopter:中部发动机极高温,上下温度差异极大 + temperatureGradient: 0.3 // Helicopter的ThermalPattern实际输出约0.2-0.4 )} }; } @@ -212,7 +531,7 @@ namespace ThreatSource.Guidance int width = image.Width; int height = image.Height; - Debug.WriteLine($"开始图像分割,阈值: {threshold:F6}"); + Debug.WriteLine($"开始图像分割,阈值: {threshold:E3}"); // 🎯 第一步:快速预扫描,统计高于阈值的像素 var scanResult = PerformQuickScan(image, threshold, width, height); @@ -268,7 +587,7 @@ namespace ThreatSource.Guidance /// /// 执行快速预扫描 /// - private ImageScanResult PerformQuickScan(InfraredImage image, double threshold, int width, int height) + private static ImageScanResult PerformQuickScan(InfraredImage image, double threshold, int width, int height) { int pixelsAboveThreshold = 0; int minX = width, minY = height, maxX = -1, maxY = -1; @@ -307,11 +626,11 @@ namespace ThreatSource.Guidance } /// - /// 执行完整的Union-Find连通区域分析 + /// 用BFS执行完整的连通区域分析 /// - private ImageSegment PerformBFSAnalysis(InfraredImage image, double threshold, int width, int height) + private static ImageSegment PerformBFSAnalysis(InfraredImage image, double threshold, int width, int height) { - Debug.WriteLine($"开始BFS连通区域分析,阈值: {threshold:F6}"); + Debug.WriteLine($"开始BFS连通区域分析,阈值: {threshold:E3}"); var visited = new bool[height, width]; var blobs = new List(); @@ -394,7 +713,7 @@ namespace ThreatSource.Guidance /// /// 检查并入队邻居像素 /// - private void CheckAndEnqueue(InfraredImage image, bool[,] visited, Queue<(int, int)> queue, + private static void CheckAndEnqueue(InfraredImage image, bool[,] visited, Queue<(int, int)> queue, int x, int y, int width, int height, double threshold) { if (x >= 0 && x < width && y >= 0 && y < height && @@ -408,7 +727,7 @@ namespace ThreatSource.Guidance /// /// 检查烟幕覆盖率 /// - private bool CheckSmokeCoverage(InfraredImage image, OptimizedBlob blob, double threshold) + private static bool CheckSmokeCoverage(InfraredImage image, OptimizedBlob blob, double threshold) { int smokeCoveredPixels = 0; int totalPixels = 0; @@ -447,52 +766,21 @@ namespace ThreatSource.Guidance /// /// 计算图像分割阈值 /// - private double CalculateThreshold(InfraredImage image) + private static double CalculateThreshold(InfraredImage image) { - // 计算图像统计信息 - double sum = 0, count = 0; - double maxIntensity = double.MinValue; - double minIntensity = double.MaxValue; - - for (int y = 0; y < image.Height; y++) - { - for (int x = 0; x < image.Width; x++) - { - double value = image.GetIntensity(y, x); - // Skip completely black pixels if necessary, or handle potential division by zero later - if (value > 0) // Avoid issues if minIntensity remains double.MaxValue - { - maxIntensity = Math.Max(maxIntensity, value); - minIntensity = Math.Min(minIntensity, value); - sum += value; - count++; - } - } - } + // 使用统一分析方法获取全图统计信息 + var analysis = AnalyzeImageRegion(image, targetRegion: null, includeGradient: false, includeHistogram: false); - // Handle case where image is entirely black or has no valid pixels - if (count == 0 || maxIntensity <= minIntensity) - { - Debug.WriteLine("图像全黑或无有效强度信息,无法计算阈值,返回0"); - return 0; // Or handle appropriately - } + // 使用预计算的结果计算阈值 + double threshold = analysis.CalculateThreshold(0.05); - - double mean = sum / count; - - // --- 修改为基于动态范围的阈值计算 --- - double thresholdFactor = 0.05; // 基于动态范围的因子 - double dynamicRange = maxIntensity - minIntensity; - double threshold = minIntensity + dynamicRange * thresholdFactor; - - - Debug.WriteLine($"图像统计:"); - Debug.WriteLine($" 最大强度: {maxIntensity:F6}"); - Debug.WriteLine($" 最小强度: {minIntensity:F6}"); - Debug.WriteLine($" 平均强度: {mean:F6}"); - Debug.WriteLine($" 动态范围: {dynamicRange:F6}"); - Debug.WriteLine($" 动态阈值因子: {thresholdFactor:P1}"); - Debug.WriteLine($" 最终阈值: {threshold:F6}"); + Debug.WriteLine($"图像统计 (统一分析):"); + Debug.WriteLine($" 最大强度: {analysis.MaxIntensity:E3}"); + Debug.WriteLine($" 最小强度: {analysis.MinIntensity:E3}"); + Debug.WriteLine($" 平均强度: {analysis.MeanIntensity:E3}"); + Debug.WriteLine($" 有效像素: {analysis.ValidPixels}/{analysis.TotalPixels}"); + Debug.WriteLine($" 动态范围: {(analysis.MaxIntensity - analysis.MinIntensity):E3}"); + Debug.WriteLine($" 最终阈值: {threshold:E3}"); return threshold; } @@ -508,14 +796,14 @@ namespace ThreatSource.Guidance // 计算考虑姿态的长宽比 double aspectRatio = CalculateOrientedAspectRatio(segment, orientation); - // 计算相对尺寸(相对于图像宽度的比例) - double relativeSize = Math.Max(segment.Size.Width, segment.Size.Height) / (image.Width * 0.1); // 假设坦克基准尺寸约为图像宽度的10% - - // 计算强度模式特征 - double intensityPattern = CalculateIntensityPattern(image, segment); + // **性能优化:单次统一分析,同时获取强度模式和梯度信息** + var analysis = AnalyzeImageRegion(image, targetRegion: segment, includeGradient: true, includeHistogram: true); - // 计算温度梯度特征 - double temperatureGradient = CalculateTemperatureGradient(image, segment, target); + // 计算强度模式特征(使用预计算结果) + double intensityPattern = analysis.CalculateIntensityPattern(); + + // 计算温度梯度特征(优先使用ThermalPattern,回退到预计算结果) + double temperatureGradient = CalculateTemperatureGradientOptimized(analysis, target); return new TargetFeature(aspectRatio, intensityPattern, temperatureGradient); } @@ -523,7 +811,7 @@ namespace ThreatSource.Guidance /// /// 计算目标主方向 /// - private double CalculateOrientation(InfraredImage image, ImageSegment segment) + private static double CalculateOrientation(InfraredImage image, ImageSegment segment) { double m11 = 0, m20 = 0, m02 = 0; double centerX = segment.Center.X; @@ -553,7 +841,7 @@ namespace ThreatSource.Guidance /// /// 计算考虑姿态的长宽比 /// - private double CalculateOrientedAspectRatio(ImageSegment segment, double orientation) + private static double CalculateOrientedAspectRatio(ImageSegment segment, double orientation) { // 计算旋转后的边界框 double cos = Math.Cos(orientation); @@ -565,221 +853,49 @@ namespace ThreatSource.Guidance } /// - /// 计算温度梯度特征 - **修正:强制基于图像计算** + /// 优化的温度梯度计算 - 减少重复计算 /// + private double CalculateTemperatureGradientOptimized(ImageAnalysisResult analysis, IEquipment target) + { + // 快速检查:优先尝试使用ThermalPattern(无Debug输出) + if (target is BaseEquipment equipment && + equipment.Properties?.ThermalPattern != null && + target.KState.Speed > 0.1) + { + try + { + return equipment.Properties.ThermalPattern.CalculateGradientFeature(true); + } + catch + { + // 静默回退到图像计算 + } + } + + // 回退到预计算的图像梯度结果 + return analysis.CalculateTemperatureGradient(); + } + + /// + /// 计算温度梯度特征 - **保留原接口,但标记为过时** + /// + [Obsolete("使用CalculateTemperatureGradientOptimized以获得更好性能")] private double CalculateTemperatureGradient(InfraredImage image, ImageSegment segment, IEquipment target) - { - Debug.WriteLine("计算基于图像的温度梯度特征"); - return CalculateImageBasedGradient(image, segment); - } - - /// - /// 基于图像计算温度梯度(当没有温度分布模式数据时使用) - /// - private double CalculateImageBasedGradient(InfraredImage image, ImageSegment segment) { - // Sobel算子 - double[,] sobelX = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; - double[,] sobelY = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; - - // 获取目标区域最大强度用于归一化 - double maxIntensity = double.MinValue; - - // 将目标区域划分为3x3的网格 - int gridRows = 3; - int gridCols = 3; - double[,] gridGradients = new double[gridRows, gridCols]; - int[,] gridCounts = new int[gridRows, gridCols]; - - // 第一遍扫描:获取最大强度 - for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++) - { - for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++) - { - if (y >= 0 && y < image.Height && x >= 0 && x < image.Width) - { - maxIntensity = Math.Max(maxIntensity, image.GetIntensity(y, x)); - } - } - } - - if (maxIntensity <= 0) return 0; - - // 计算每个网格的大小 - int gridWidth = segment.Size.Width / gridCols; - int gridHeight = segment.Size.Height / gridRows; - - // 第二遍扫描:计算每个网格的梯度 - for (int y = segment.Center.Y - segment.Size.Height/2 + 1; - y < segment.Center.Y + segment.Size.Height/2 - 1; y++) - { - for (int x = segment.Center.X - segment.Size.Width/2 + 1; - x < segment.Center.X + segment.Size.Width/2 - 1; x++) - { - if (y >= 1 && y < image.Height - 1 && x >= 1 && x < image.Width - 1) - { - // 计算当前点属于哪个网格 - int gridRow = (y - (segment.Center.Y - segment.Size.Height/2)) * gridRows / segment.Size.Height; - int gridCol = (x - (segment.Center.X - segment.Size.Width/2)) * gridCols / segment.Size.Width; - - gridRow = Math.Min(Math.Max(gridRow, 0), gridRows - 1); - gridCol = Math.Min(Math.Max(gridCol, 0), gridCols - 1); - - double gradX = 0, gradY = 0; - - // 应用Sobel算子 - for (int i = -1; i <= 1; i++) - { - for (int j = -1; j <= 1; j++) - { - double value = image.GetIntensity(y + i, x + j); - gradX += value * sobelX[i + 1, j + 1]; - gradY += value * sobelY[i + 1, j + 1]; - } - } - - // 计算归一化梯度 - double normalizedGradient = Math.Sqrt(gradX * gradX + gradY * gradY) / maxIntensity; - - // 累加到对应的网格 - gridGradients[gridRow, gridCol] += normalizedGradient; - gridCounts[gridRow, gridCol]++; - } - } - } - - // 计算每个网格的平均梯度 - double[,] avgGridGradients = new double[gridRows, gridCols]; - for (int i = 0; i < gridRows; i++) - { - for (int j = 0; j < gridCols; j++) - { - avgGridGradients[i, j] = gridCounts[i, j] > 0 ? - gridGradients[i, j] / gridCounts[i, j] : 0; - } - } - - // 计算后部区域(发动机舱)的梯度特征 - double engineAreaGradient = (avgGridGradients[1, 2] + avgGridGradients[2, 2]) / 2.0; - - // 计算前部区域的梯度特征 - double frontAreaGradient = (avgGridGradients[1, 0] + avgGridGradients[2, 0]) / 2.0; - - // 计算中部区域的梯度特征 - double middleAreaGradient = avgGridGradients[1, 1]; - - // 计算梯度分布特征 (调整除零保护) - double gradientDistribution = engineAreaGradient / (frontAreaGradient + 1e-6); - double gradientContrast = engineAreaGradient / (middleAreaGradient + 1e-6); - - // 最终得分:调整权重 (engine*0.5 + dist*0.3 + contrast*0.2) - return engineAreaGradient * 0.5 + - Math.Min(gradientDistribution, 3.0) / 3.0 * 0.3 + - Math.Min(gradientContrast, 3.0) / 3.0 * 0.2; + // 为了向后兼容,保留此方法,但实际使用优化版本 + var analysis = AnalyzeImageRegion(image, targetRegion: segment, includeGradient: true, includeHistogram: false); + return CalculateTemperatureGradientOptimized(analysis, target); } /// - /// 判断目标是否在运动 - /// - private bool IsTargetMoving(InfraredImage image, ImageSegment segment) - { - // TODO: 实现运动检测逻辑 - // 可以基于: - // 1. 连续帧之间的位置变化 - // 2. 速度传感器数据 - // 3. 运动检测算法 - return false; - } - - /// - /// 计算强度模式特征 + /// 计算强度模式特征 - **保留原接口,但标记为过时** /// + [Obsolete("在ExtractFeatures中直接使用AnalyzeImageRegion结果以获得更好性能")] private double CalculateIntensityPattern(InfraredImage image, ImageSegment segment) { - const int BINS = 10; - double[] histogram = new double[BINS]; - - // 获取目标区域最大和最小强度 - double maxIntensity = double.MinValue; - double minIntensity = double.MaxValue; - double centerIntensity = 0; - int centerPixelCount = 0; - double totalIntensity = 0; - int totalPixels = 0; - - // 定义中心区域大小(目标尺寸的1/3) - int centerRegionWidth = segment.Size.Width / 3; - int centerRegionHeight = segment.Size.Height / 3; - - // 第一遍扫描:获取强度范围和中心区域强度 - for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++) - { - for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++) - { - if (y >= 0 && y < image.Height && x >= 0 && x < image.Width) - { - double intensity = image.GetIntensity(y, x); - maxIntensity = Math.Max(maxIntensity, intensity); - minIntensity = Math.Min(minIntensity, intensity); - totalIntensity += intensity; - totalPixels++; - - // 检查是否在中心区域 - if (Math.Abs(x - segment.Center.X) <= centerRegionWidth/2 && - Math.Abs(y - segment.Center.Y) <= centerRegionHeight/2) - { - centerIntensity += intensity; - centerPixelCount++; - } - } - } - } - - if (totalPixels == 0 || maxIntensity <= minIntensity) return 0; - - // 计算平均中心强度 - double avgCenterIntensity = centerPixelCount > 0 ? centerIntensity / centerPixelCount : 0; - // 计算平均总强度 - double avgTotalIntensity = totalIntensity / totalPixels; - - // 填充直方图 - double binSize = (maxIntensity - minIntensity) / BINS; - - // 第二遍扫描:填充直方图 - for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++) - { - for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++) - { - if (y >= 0 && y < image.Height && x >= 0 && x < image.Width) - { - double intensity = image.GetIntensity(y, x); - int bin = Math.Min(BINS - 1, (int)((intensity - minIntensity) / binSize)); - histogram[bin]++; - } - } - } - - // 归一化直方图 - for (int i = 0; i < BINS; i++) - { - histogram[i] /= totalPixels; - } - - // 计算集中度得分:改为计算最高 30% bin 的占比 - double concentrationScore = 0; - int topBinsStart = (int)(BINS * 0.7); // Start from the 70th percentile bin (e.g., index 7 for BINS=10) - for (int i = topBinsStart; i < BINS; i++) - { - concentrationScore += histogram[i]; - } - - // 计算中心区域相对强度比 - double centerIntensityRatio = avgTotalIntensity > 0 ? avgCenterIntensity / avgTotalIntensity : 0; // Avoid division by zero - - // 最终得分:集中度得分(0.6)和中心强度比(0.4)的加权和 - // 同时确保最终结果在 [0, 1] 范围内 - double finalScore = concentrationScore * 0.6 + centerIntensityRatio * 0.4; - return Math.Max(0, Math.Min(1, finalScore)); // Clamp result to [0, 1] + // 为了向后兼容,保留此方法 + var analysis = AnalyzeImageRegion(image, targetRegion: segment, includeGradient: false, includeHistogram: true); + return analysis.CalculateIntensityPattern(); } /// @@ -816,7 +932,7 @@ namespace ThreatSource.Guidance /// /// 计算特征权重 /// - private double[] CalculateFeatureWeights(TargetFeature features) + private static double[] CalculateFeatureWeights(TargetFeature features) { // 使用固定权重,基于特征的重要性 // 长宽比: 0.4, 强度模式: 0.3, 温度梯度: 0.3 @@ -844,7 +960,7 @@ namespace ThreatSource.Guidance /// /// 计算特征匹配得分 /// - private double CalculateMatchScore(TargetFeature features, TargetFeature template, double[] weights) + private static double CalculateMatchScore(TargetFeature features, TargetFeature template, double[] weights) { // 计算各个特征的匹配度,使用相对误差 double aspectRatioScore = 1 - Math.Min(1, Math.Abs(features.AspectRatio - template.AspectRatio) / Math.Max(features.AspectRatio, template.AspectRatio)); @@ -869,7 +985,7 @@ namespace ThreatSource.Guidance /// /// 目标特征结构 /// - private struct TargetFeature + private readonly struct TargetFeature { public double AspectRatio { get; } public double IntensityPattern { get; } @@ -889,7 +1005,7 @@ namespace ThreatSource.Guidance /// /// 图像分割结果结构 /// - private struct ImageSegment + private readonly struct ImageSegment { public bool IsValid { get; } public (int X, int Y) Center { get; } @@ -911,9 +1027,9 @@ namespace ThreatSource.Guidance public int MaxX { get; set; } public int MaxY { get; set; } public int Area { get; set; } - public int Width => MaxX - MinX + 1; - public int Height => MaxY - MinY + 1; - public (double x, double y) Center => ((MinX + MaxX) / 2.0, (MinY + MaxY) / 2.0); + public readonly int Width => MaxX - MinX + 1; + public readonly int Height => MaxY - MinY + 1; + public readonly (double x, double y) Center => ((MinX + MaxX) / 2.0, (MinY + MaxY) / 2.0); } // --- 结束新增 --- } diff --git a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs index 0cc272b..41169c7 100644 --- a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs @@ -950,7 +950,7 @@ namespace ThreatSource.Guidance if (snr_linear <= 0) return -100.0; double snr_dB_no_smoke = 10 * Math.Log10(snr_linear); - Debug.WriteLine($"[SNR计算] SNR_dB (烟幕前): {snr_dB_no_smoke:F2} dB. Incoming SmokeTransmittance_Linear: {smokeTransmittanceLinear:F6}"); + Debug.WriteLine($"[SNR计算] SNR_dB (烟幕前): {snr_dB_no_smoke:F2} dB. Incoming SmokeTransmittance_Linear: {smokeTransmittanceLinear:E3}"); // 应用烟幕透过率 if (smokeTransmittanceLinear <= 1e-6) // 防止log(0)或非常大的负数 diff --git a/docs/test_result/prtformance_test_result_0605.md b/docs/test_result/prtformance_test_result_0605.md index d6225b6..6fb2ca1 100644 --- a/docs/test_result/prtformance_test_result_0605.md +++ b/docs/test_result/prtformance_test_result_0605.md @@ -323,4 +323,35 @@ Gen2 GC次数: 0 (0.0 次/秒) 【性能评级】 帧时间表现: 优秀 ✅ 内存管理: 优秀 ✅ +GC频率: 优秀 ✅ + +### 2025-06-08 10:00:00 + +#### 随机导弹组合 + +=== 详细性能测试结果 === +【基本统计】 +测试时长: 30.0 秒 +总更新次数: 1416 +平均FPS: 47.2 +平均帧时间: 0.33 ms +【帧时间分析】 +最小帧时间: 0.01 ms +最大帧时间: 8.53 ms +95%分位数: 1.31 ms +99%分位数: 1.94 ms +【内存使用分析】 +起始内存: 2.96 MB +结束内存: 9.79 MB +峰值内存: 11.33 MB +内存增长: 6.84 MB +平均内存增长率: 0.23 MB/s +【垃圾回收分析】 +Gen0 GC次数: 9 (0.3 次/秒) +Gen1 GC次数: 0 (0.0 次/秒) +Gen2 GC次数: 0 (0.0 次/秒) +总GC次数: 9 +【性能评级】 +帧时间表现: 优秀 ✅ +内存管理: 优秀 ✅ GC频率: 优秀 ✅ \ No newline at end of file diff --git a/算法优化第一阶段任务进度.md b/算法优化第一阶段任务进度.md deleted file mode 100644 index be17e27..0000000 --- a/算法优化第一阶段任务进度.md +++ /dev/null @@ -1,177 +0,0 @@ -# 算法优化第一阶段任务进度 - -## 任务描述 -实施高影响、中等复杂度的算法优化,预期获得40-50%的性能提升。 - -## 执行状态 - -### ✅ 已完成的步骤 - -#### 步骤1:创建优化数据结构 -- **文件**:`ThreatSource/src/Guidance/InfraredTargetRecognizer.cs`, `ThreatSource/src/Guidance/InfraredImageGenerator.cs` -- **修改**: - - 添加ImageAnalysisResult结构体,存储单次遍历的所有统计信息 - - 添加DirtyRegion结构体,用于跟踪数组使用区域 - - 添加SmokeRegion结构体,用于烟幕影响区域预计算 -- **更改摘要**:成功创建所有优化数据结构,为后续算法优化奠定基础 -- **原因**:执行计划步骤 1 -- **阻碍**:无 -- **状态**:成功 ✅ - -#### 步骤2:实现AnalyzeImageRegion统一分析方法 -- **文件**:`ThreatSource/src/Guidance/InfraredTargetRecognizer.cs` -- **修改**: - - 创建AnalyzeImageRegion方法,单次遍历完成多项计算 - - 支持全图分析和指定区域分析 - - 同时计算阈值统计、强度模式、烟幕覆盖等信息 -- **更改摘要**:成功实现统一图像分析,减少重复遍历 -- **原因**:执行计划步骤 2 -- **阻碍**:无 -- **状态**:成功 ✅ - -#### 步骤3:重构CalculateThreshold方法 -- **文件**:`ThreatSource/src/Guidance/InfraredTargetRecognizer.cs` -- **修改**: - - 移除独立的图像遍历循环 - - 使用AnalyzeImageRegion的预计算结果 - - 保持相同的阈值计算逻辑 -- **更改摘要**:成功消除一次完整的图像遍历,提升效率 -- **原因**:执行计划步骤 3 -- **阻碍**:无 -- **状态**:成功 ✅ - -#### 步骤4:重构CalculateIntensityPattern方法 -- **文件**:`ThreatSource/src/Guidance/InfraredTargetRecognizer.cs` -- **修改**: - - 移除两次重复的图像遍历 - - 使用预计算的直方图和统计信息 - - 优化集中度和中心强度比计算 -- **更改摘要**:成功消除两次图像遍历,大幅提升特征计算效率 -- **原因**:执行计划步骤 4 -- **阻碍**:无 -- **状态**:成功 ✅ - -#### 步骤5:优化数组管理策略 -- **文件**:`ThreatSource/src/Guidance/InfraredImageGenerator.cs` -- **修改**: - - 实现智能数组池,跟踪脏区域 - - 修改GetDoubleArray和GetBoolArray使用增量清零 - - 更新ReturnDoubleArray和ReturnBoolArray记录脏区域 - - 修复所有相关的方法调用 -- **更改摘要**:成功实现智能数组重用,减少不必要的清零操作 -- **原因**:执行计划步骤 5 -- **阻碍**:无 -- **状态**:成功 ✅ - -#### 步骤6:实现烟幕区域预计算功能 -- **文件**:`ThreatSource/src/Guidance/InfraredImageGenerator.cs` -- **修改**: - - 实现CalculateSmokeInfluenceRegions方法,预计算所有烟幕影响区域 - - 重构ApplyObscuringSmokeOverlay方法,使用预计算区域避免重复计算 - - 优化烟幕处理逻辑,减少几何投影和边界检查的重复执行 -- **更改摘要**:成功实现烟幕区域预计算,大幅减少烟幕处理的计算开销 -- **原因**:执行计划步骤 6 -- **阻碍**:无 -- **状态**:成功 ✅ - -### 🔄 当前执行步骤 - -#### 步骤7:运行性能测试验证优化效果 -- **计划**:对比优化前后的性能指标 -- **状态**:待执行 - -### 📋 待执行步骤 - -#### 步骤7:重构烟幕覆盖方法 -- **计划**:修改ApplyObscuringSmokeOverlay方法使用区域限制 -- **状态**:待执行 - -#### 步骤8:更新调用链 -- **计划**:修改SegmentTarget方法集成所有优化 -- **状态**:待执行 - -#### 步骤9:添加错误处理和降级机制 -- **计划**:确保优化后的代码具有良好的错误处理 -- **状态**:待执行 - -#### 步骤10:运行性能测试验证优化效果 -- **计划**:对比优化前后的性能指标 -- **状态**:待执行 - -## 优化效果预期 - -### 已实现的优化 -1. **图像遍历次数减少**:从3-4次减少到1次(75%减少) -2. **数组清零优化**:从全数组清零改为增量清零(预期50-80%减少) -3. **特征计算优化**:消除重复计算,提升算法效率 - -### 预期性能提升 -- **图像分析阶段**:60-70%性能提升 -- **数组管理开销**:50-80%减少 -- **整体帧时间**:预期从1.67ms降至1.0-1.2ms - -## 技术要点 - -### 关键优化策略 -1. **统一遍历模式**:一次遍历完成多项计算任务 -2. **智能内存管理**:脏区域跟踪,减少不必要操作 -3. **预计算策略**:避免重复的几何计算 - -### 代码质量保证 -- 保持向后兼容性 -- 维护原有的计算精度 -- 添加适当的调试信息 - -## 任务进度 (由 EXECUTE 模式在每步完成后追加) - -* [2024-12-30 12:58] - * 步骤:检查清单项目1-5和描述:实施烟幕条件分配优化 - * 修改:ThreatSource/src/Guidance/InfraredImageGenerator.cs, ThreatSource/src/Guidance/InfraredImage.cs - 烟幕数组条件分配逻辑 - * 更改摘要:成功实施延迟分配策略,避免无烟幕场景下的不必要数组分配 - * 原因:执行计划步骤 [1-5] - 烟幕条件分配优化 - * 阻碍:无 - * 用户确认状态:成功 - -* [2024-12-30 13:12] - * 步骤:检查清单项目1-4和描述:实施Union-Find连通区域算法优化 - * 修改:ThreatSource/src/Guidance/InfraredTargetRecognizer.cs - 添加UnionFind类,重构SegmentTarget方法,优化Blob结构 - * 更改摘要:成功实施Union-Find连通区域算法,替换原有BFS算法,移除像素坐标存储,只保留边界框信息 - * 原因:执行计划步骤 [1-4] - Union-Find算法优化 - * 阻碍:微小类型转换问题已修正 - * 用户确认状态:[待确认] - -* [2024-12-30 13:44] - * 步骤:检查清单项目1-6和描述:实施预扫描+早期退出优化策略 - * 修改:ThreatSource/src/Guidance/InfraredTargetRecognizer.cs - 添加ImageScanResult结构体,CreateSimpleSegment方法,重构SegmentTarget方法 - * 更改摘要:成功实施预扫描逻辑,在简单场景下跳过Union-Find计算,减少不必要的内存分配 - * 原因:执行计划步骤 [1-6] - 预扫描+早期退出优化 - * 阻碍:无 - * 用户确认状态:[待确认] - -**性能测试结果对比:** - -**优化前(Union-Find修复后):** -- targetRecognizer.RecognizeTarget: 1.517ms, -556,998 bytes -- imageGenerator.GenerateImage: 0.680ms, 568,519 bytes -- Gen0 GC频率: 12.3次/秒 -- 平均帧时间: 1.38ms - -**优化后(预扫描+早期退出):** -- targetRecognizer.RecognizeTarget: 0.467ms (-69.2%), 689 bytes -- imageGenerator.GenerateImage: 1.253ms (+84.3%), 292,976 bytes -- Gen0 GC频率: 9.7次/秒 (-21.1%) -- 平均帧时间: 1.27ms (-8.0%) - -**关键成功指标:** -- targetRecognizer.RecognizeTarget性能提升69.2%,从1.517ms降至0.467ms -- 内存分配从负值变为正值689 bytes,说明预扫描策略有效避免了Union-Find分配 -- GC频率从12.3次/秒降至9.7次/秒,改善21.1% -- 最大帧时间从19.11ms降至12.82ms,尖峰控制改善32.9% -- 95%分位数从6.27ms降至6.62ms,基本保持稳定 -- 系统整体性能达到生产级别,测试通过✅ - -**优化机制验证:** -- 预扫描成功识别简单场景,跳过Union-Find计算 -- 早期退出条件有效减少不必要的内存分配 -- 复杂场景仍使用完整Union-Find算法,保证准确性 -- 算法正确性完全保持,功能无任何损失 \ No newline at end of file