以下是一个Hampel滤波器的完整C#实现示例适合用于信号处理如IGBT功率循环测试中的Vf波形或TVJ数据去离群点。代码包含经典实现带1.4826尺度因子边界处理边缘复制 padding可配置窗口大小和阈值threshold通常3~5返回滤波后信号 可选的离群点掩码bool数组usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;namespaceSignalProcessing{/// summary/// Hampel滤波器用于检测和替换时间序列中的离群点outliers/// 基于局部中位数 MAD中值绝对偏差/// /summarypublicstaticclassHampelFilter{/// summary/// 对一维信号应用Hampel滤波/// /summary/// param nameinput输入信号double数组/param/// param namewindowHalfWidth窗口半宽k总窗口长度2k1必须奇数/param/// param namethreshold阈值标准差倍数常见值3.0~5.0/param/// param nameuseScaleFactor是否使用1.4826尺度因子默认true使MAD≈σ/param/// param nameoutliers输出离群点掩码true表示该点被替换/param/// returns滤波后的信号与输入长度相同/returnspublicstaticdouble[]Filter(double[]input,intwindowHalfWidth5,doublethreshold5.0,booluseScaleFactortrue,outbool[]outliers){if(inputnull||input.Length0)thrownewArgumentException(输入信号不能为空);intninput.Length;intwindowSize2*windowHalfWidth1;doublescaleuseScaleFactor?1.4826:1.0;double[]outputnewdouble[n];outliersnewbool[n];Array.Copy(input,output,n);// 默认输出输入for(inti0;in;i){// 提取当前窗口ListdoublewindownewListdouble();for(intj-windowHalfWidth;jwindowHalfWidth;j){intidxij;// 边界处理复制边缘值replication paddingif(idx0)idx0;if(idxn)idxn-1;window.Add(input[idx]);}doublemedianMedian(window);doublemadMad(window,median);if(mad1e-10)// 防止mad0导致除零{continue;}doubledeviationMath.Abs(input[i]-median);doublelimitthreshold*scale*mad;if(deviationlimit){output[i]median;// 替换为中位数outliers[i]true;}else{outliers[i]false;}}returnoutput;}/// summary/// 计算数组的中位数/// /summaryprivatestaticdoubleMedian(IEnumerabledoublevalues){varsortedvalues.OrderBy(xx).ToList();intcountsorted.Count;if(count%21)returnsorted[count/2];return(sorted[count/2-1]sorted[count/2])/2.0;}/// summary/// 计算MAD中值绝对偏差/// /summaryprivatestaticdoubleMad(IEnumerabledoublevalues,doublemedian){vardeviationsvalues.Select(xMath.Abs(x-median)).ToList();returnMedian(deviations);}// ---------------- 测试 / 示例用法 ----------------publicstaticvoidExample(){// 模拟带尖峰噪声的信号double[]signalnewdouble[100];RandomrandnewRandom();for(inti0;isignal.Length;i){signal[i]Math.Sin(i*0.1)0.1*(rand.NextDouble()-0.5);}// 人为加入几个离群点signal[20]5.0;signal[50]-4.0;signal[80]6.0;bool[]isOutlier;double[]filteredFilter(signal,windowHalfWidth:5,threshold:4.0,outisOutlier);Console.WriteLine(原始信号部分: string.Join(, ,signal.Take(10)));Console.WriteLine(滤波后信号部分: string.Join(, ,filtered.Take(10)));// 打印离群点位置for(inti0;iisOutlier.Length;i){if(isOutlier[i])Console.WriteLine($离群点 at index{i}: 原值{signal[i]:F3}→ 替换为{filtered[i]:F3});}}}// 使用示例HampelFilter.Example();}关键参数说明参数推荐值说明windowHalfWidth (k)3 ~ 10窗口半宽总窗口2k1越大越平滑但延迟增加threshold3.0经典 / 5.0保守多少倍“标准差”视为离群你的代码用5useScaleFactortrue是否乘1.4826使MAD≈正态σ推荐开启与你原有代码的对比 / 改进点你的原始实现double[]signalnewdouble[tvjCount2*k];Array.Copy(tvj.ToArray(),1,signal,0,k);// 前向复制第2~k1个点Array.Copy(tvj.ToArray(),0,signal,k,tvjCount);Array.Copy(tvj.ToArray(),tvjCount-k-1,signal,ktvjCount,k);double[]hampelSignalthis.HampelFilter(signal,k,5);tvjnewListdouble(hampelSignal);// 注意输出比输入短2k改进建议输出长度与输入一致更符合大多数使用场景边界用复制边缘值replication避免引入不自然的跳变可选输出离群点位置便于调试/日志增加对mad≈0的保护防止全平坦信号除零性能提示对于几千点信号当前实现足够快O(n × w log w)w窗口大小如果信号非常长10万点可考虑使用排序后的滑动窗口中位数更复杂或借助第三方库如Math.NET Numerics 自定义MAD如果需要更高效版本、结合你的TVJ代码的集成示例、或求导/其他变体随时告诉我