using AutoMapper; using FLY.Thick.Base.IService; using FObjBase; using Misc; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; namespace FLY.Thick.Base.Server { //1.剔除 偏离平均值 大于 设定值 //2.权重 滤波 public class Reject : IRejectService, INotifyPropertyChanged { public bool Enable { get; set; } /// /// 规格范围, (value - Target)/Target > LimitRangeRatio 就会被剔除 /// public double LimitRangeRatio { get; set; } public double ThresholdRatio { get; set; } public int SmoothRange { get; set; } public int RejectRange { get; set; } /// /// 调试数据更新时间,用于让客户端 决定什么时候 下载调试数据 /// public DateTime DebugUpdateTime { get; private set; } private RejectDebugData rejectDebug; private string param_path = "reject.json"; public Reject() { SetDefault(); } public Reject(string param_path) { if (!string.IsNullOrEmpty(param_path)) this.param_path = param_path; SetDefault(); Load(); } void SetDefault() { Enable = false; LimitRangeRatio = 0.3; ThresholdRatio = 0.93; SmoothRange = 10; RejectRange = 300; } public bool Load() { return RejectJsonDb.Load(param_path, this); } public bool Save() { return RejectJsonDb.Save(param_path, this); } public void Apply() { Save(); } public void DoFrameFilter(double target, int posOfGrid, int start_grid, double[] frame) { var rejectDatas = (double[])frame.Clone(); int smoothRange = SmoothRange / posOfGrid; if (smoothRange <= 0) smoothRange = 1; int len = frame.Count(); var filterDatas = new double[len]; //滤波 for (int i = 0; i < len; i++) { int b = i - smoothRange; int e = i + smoothRange; if (b < 0) b = 0; if (e >= len) e = len - 1; List datas = new List(); for (int j = b; j <= e; j++) datas.Add(rejectDatas[j]); filterDatas[i] = datas.AverageNoNull(); } double threshold = target * ThresholdRatio; double limitRange = LimitRangeRatio * target; bool[] bfilterdats = new bool[len]; //阀值剔除 for (int i = 0; i < len; i++) { if (!double.IsNaN(rejectDatas[i])) { if (rejectDatas[i] < threshold) { bfilterdats[i] = true; } else if (Math.Abs(target - rejectDatas[i]) > limitRange) { bfilterdats[i] = true; } } } int reject_b_idx = -1; int reject_e_idx = -1; //半径内全部删除 int reject_range = RejectRange / posOfGrid; if (reject_range < 0) reject_range = 0; for (int i = 0; i < len; i++) { if (!bfilterdats[i]) { //之前有需要剔除的 if (reject_b_idx != -1) { int b = reject_b_idx - reject_range; int e = reject_e_idx + reject_range; if (b < 0) b = 0; if (e >= len) e = len - 1; for (int j = b; j <= e; j++) { rejectDatas[j] = double.NaN; } reject_b_idx = -1; i = e; } } else { if (reject_b_idx == -1) { reject_b_idx = i; } reject_e_idx = i; } } if (reject_b_idx != -1) { int b = reject_b_idx - reject_range; int e = reject_e_idx + reject_range; if (b < 0) b = 0; if (e >= len) e = len - 1; for (int j = b; j <= e; j++) { rejectDatas[j] = double.NaN; } reject_b_idx = -1; } if (Enable) { Array.Copy(rejectDatas, 0, frame, 0, len); } var rejectDebug = new RejectDebugData { posOfGrid = posOfGrid, start_grid = start_grid, target = target, filterDatas = filterDatas, rejectDatas = rejectDatas, }; this.rejectDebug = rejectDebug; this.DebugUpdateTime = DateTime.Now; } public void GetDebugData(AsyncCBHandler asyncDelegate, object asyncContext) { asyncDelegate?.Invoke(asyncContext, rejectDebug); } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion } public class RejectJsonDb { static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => { c.CreateMap().ReverseMap(); })); public static bool Save(string file_path, Reject src) { try { var p = Mapper.Map(src); File.WriteAllText(file_path, JsonConvert.SerializeObject(p, Formatting.Indented)); return true; } catch { //异常,没有json 编码失败 } return false; } public static bool Load(string file_path, Reject src) { try { if (File.Exists(file_path)) { string json = File.ReadAllText(file_path); var p = JsonConvert.DeserializeObject(json); Mapper.Map(p, src); } } catch { //异常,没有json 解码失败 } return false; } public bool Enable { get; set; } public double LimitRangeRatio { get; set; } public double ThresholdRatio { get; set; } public int SmoothRange { get; set; } public int RejectRange { get; set; } } }