测试页面
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
using Modbus.Device;
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32;
|
||||
using Modbus.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -7,6 +7,7 @@ using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using 头罩视野.Services.Data;
|
||||
using static 头罩视野.TestDataStore;
|
||||
|
||||
public static class ModbusHelper
|
||||
{
|
||||
@@ -23,8 +24,6 @@ public static class ModbusHelper
|
||||
// 判断是否连接成功
|
||||
public static bool IsConnected => TcpClient != null && TcpClient.Connected;
|
||||
|
||||
public static ushort ValidThreshold { get; private set; }
|
||||
|
||||
|
||||
// <summary>
|
||||
/// 公共保存方法(用户自选文件夹)
|
||||
@@ -67,376 +66,4 @@ public static class ModbusHelper
|
||||
MessageBox.Show("保存成功!\n" + filePath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 剔除异常值,用相邻数据插值
|
||||
private static List<ushort> RemoveOutliers(List<ushort> data)
|
||||
{
|
||||
for (int i = 1; i < data.Count - 1; i++)
|
||||
{
|
||||
if (Math.Abs(data[i] - data[i - 1]) > 30 && Math.Abs(data[i] - data[i + 1]) > 30)
|
||||
{
|
||||
data[i] = (ushort)((data[i - 1] + data[i + 1]) / 2);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//// 过滤无效信号
|
||||
private const int ValidSignalThreshold = 12;
|
||||
|
||||
private static void FilterInvalidSignals(List<ushort> data)
|
||||
{
|
||||
for (int i = 0; i < data.Count; i++)
|
||||
{
|
||||
if (data[i] < ValidSignalThreshold)
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算单眼视野面积
|
||||
/// </summary>
|
||||
/// <param name="groupData">20组数据,每组72个通道</param>
|
||||
/// <param name="threshold">有效亮度阈值(如12)</param>
|
||||
/// <param name="standardTotalArea">标准视野面积(如140)</param>
|
||||
/// <returns>计算好的面积</returns>
|
||||
///
|
||||
public static double CalculateEyeArea(List<double[]> groupData, double threshold, double standardArea)
|
||||
{
|
||||
double[] avg = new double[72];
|
||||
for (int c = 0; c < 72; c++)
|
||||
{
|
||||
double sum = 0;
|
||||
foreach (var g in groupData) sum += g[c];
|
||||
avg[c] = sum / groupData.Count;
|
||||
}
|
||||
|
||||
int valid = avg.Count(v => v >= threshold);
|
||||
return (valid / 72.0) * standardArea;
|
||||
}
|
||||
//计算单眼面积调用的方法
|
||||
|
||||
//double leftArea = CalculateEyeArea(
|
||||
// leftEye20Groups, // 左眼20组数据
|
||||
// 80, // 阈值
|
||||
// 120 // 标准面积
|
||||
//);
|
||||
//double rightArea = .CalculateEyeArea(
|
||||
// rightEye20Groups, // 右眼20组数据
|
||||
// 80, // 阈值
|
||||
// 120 // 标准面积
|
||||
//);
|
||||
|
||||
|
||||
|
||||
//计算双目视野面积
|
||||
/// <summary>
|
||||
/// 计算双目视野面积(左右眼同时可见)
|
||||
/// </summary>
|
||||
public static double CalcBinocularArea(
|
||||
List<double[]> leftGroups,
|
||||
List<double[]> rightGroups,
|
||||
double threshold,
|
||||
double standardArea)
|
||||
{
|
||||
// 1. 左眼平均数据
|
||||
double[] leftAvg = new double[72];
|
||||
for (int i = 0; i < 72; i++)
|
||||
{
|
||||
double sum = 0;
|
||||
foreach (var g in leftGroups) sum += g[i];
|
||||
leftAvg[i] = sum / leftGroups.Count;
|
||||
}
|
||||
|
||||
// 2. 右眼平均数据
|
||||
double[] rightAvg = new double[72];
|
||||
for (int i = 0; i < 72; i++)
|
||||
{
|
||||
double sum = 0;
|
||||
foreach (var g in rightGroups) sum += g[i];
|
||||
rightAvg[i] = sum / rightGroups.Count;
|
||||
}
|
||||
|
||||
// 3. 双目同时有效点数(左右都亮才算)
|
||||
int biValid = 0;
|
||||
for (int i = 0; i < 72; i++)
|
||||
{
|
||||
if (leftAvg[i] >= threshold && rightAvg[i] >= threshold)
|
||||
biValid++;
|
||||
}
|
||||
|
||||
// 4. 双目视野面积
|
||||
return (biValid / 72.0) * standardArea;
|
||||
}
|
||||
|
||||
//调用公式
|
||||
|
||||
// 你从Modbus拿到的20组数据
|
||||
//List<double[]> left20Groups = ...;
|
||||
//List<double[]> right20Groups = ...;
|
||||
|
||||
//double threshold = 80;
|
||||
//double standardArea = 120;
|
||||
|
||||
//// 左眼
|
||||
//double left = VisionCalculator.CalcEyeArea(left20Groups, threshold, standardArea);
|
||||
|
||||
//// 右眼
|
||||
//double right = VisionCalculator.CalcEyeArea(right20Groups, threshold, standardArea);
|
||||
|
||||
//// 双目视野面积
|
||||
//double binocular = VisionCalculator.CalcBinocularArea(left20Groups, right20Groups, threshold, standardArea);
|
||||
|
||||
//// 总视野面积
|
||||
//double total = left + right - binocular;
|
||||
|
||||
|
||||
//下方视野角度
|
||||
/// <summary>
|
||||
/// GB2890-2022 计算 单眼下方视野角度
|
||||
/// eyeData:单眼72路平均数据数组
|
||||
/// threshold:有效亮度阈值
|
||||
/// </summary>
|
||||
public static double CalcLowerAngle(double[] eyeData, double threshold = 12)
|
||||
{
|
||||
// 总72点 每点5°
|
||||
int totalPoint = 72;
|
||||
double perAngle = 5;
|
||||
|
||||
// 国标:最下方起始点位(第54号开始为正下方)
|
||||
int startDownIndex = 54;
|
||||
|
||||
int validCount = 0;
|
||||
|
||||
// 从最下方向上 连续检测有效点
|
||||
for (int i = 0; i < 36; i++)
|
||||
{
|
||||
int idx = (startDownIndex + i) % totalPoint;
|
||||
|
||||
if (eyeData[idx] >= threshold)
|
||||
{
|
||||
validCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 断开直接停止
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 下方视野角度 = 有效点数 × 单步角度
|
||||
return validCount * perAngle;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 计算单眼72点通道平均值数组
|
||||
/// </summary>
|
||||
/// <param name="eyeGroups">多组采样数据集合</param>
|
||||
/// <returns>72点通道平均值数组</returns>
|
||||
private static double[] GetEyeAvgArray(List<double[]> eyeGroups)
|
||||
{
|
||||
if (eyeGroups == null || eyeGroups.Count == 0)
|
||||
return new double[72]; // 无数据时返回全0数组
|
||||
|
||||
double[] avg = new double[72];
|
||||
|
||||
for (int i = 0; i < 72; i++)
|
||||
{
|
||||
double sum = 0;
|
||||
foreach (var group in eyeGroups)
|
||||
{
|
||||
sum += group[i];
|
||||
}
|
||||
avg[i] = sum / eyeGroups.Count;
|
||||
}
|
||||
|
||||
return avg;
|
||||
}
|
||||
//下方视野计算方法
|
||||
////1. 先拿到左右眼 72点平均数组
|
||||
//double[] leftAvg = GetLeftEyeAvgArray();
|
||||
//double[] rightAvg = GetRightEyeAvgArray();
|
||||
|
||||
////2. 分别算下方角度
|
||||
//double leftLowerAngle = CalcLowerAngle(leftAvg, 10);
|
||||
//double rightLowerAngle = CalcLowerAngle(rightAvg, 10);
|
||||
|
||||
////3. 最终报告取值(国标取双眼较小值)
|
||||
//double finalLowerAngle = Math.Min(leftLowerAngle, rightLowerAngle);
|
||||
//bool lowerAngleOk = finalLowerAngle >= 35;
|
||||
|
||||
//空白视野面积计算
|
||||
|
||||
//空白视野面积 = 标准视野总面积 − 实测总视野面积
|
||||
//总视野面积 = 左眼面积 + 右眼面积 − 双目重叠面积
|
||||
// 前面已经算出来的
|
||||
//double leftArea = ...;
|
||||
//double rightArea = ...;
|
||||
//double binocularArea = ...;
|
||||
|
||||
//// 总视野
|
||||
//double totalVisionArea = leftArea + rightArea - binocularArea;
|
||||
|
||||
//// 标准总面积(设备固定值,比如 120)
|
||||
//double standardTotalArea = 120;
|
||||
|
||||
//// 空白视野面积
|
||||
//double blankArea = standardTotalArea - totalVisionArea;
|
||||
|
||||
|
||||
|
||||
|
||||
//视野保存率
|
||||
//double totalSaveRate = (总视野面积 / 标准总视野面积) * 100;
|
||||
public static class VisionCalculator
|
||||
{
|
||||
/// <summary>
|
||||
/// 计算视野保存率
|
||||
/// </summary>
|
||||
/// <param name="actualArea">实测面积</param>
|
||||
/// <param name="standardArea">标准面积</param>
|
||||
/// <returns>保存率 %</returns>
|
||||
public static double CalculateVisionSaveRate(double actualArea, double standardArea)
|
||||
{
|
||||
if (standardArea == 0) return 0;
|
||||
return (actualArea / standardArea) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 空头模(无面罩)标定的标准面积(GB2890-2022)
|
||||
//public static double StandardSingleEye = 5200;
|
||||
//// 双眼总标准面积(左+右)
|
||||
//public static double StandardTotalEye = 10400;
|
||||
//// 双目重叠标准面积
|
||||
////public static double StandardBinocular = 4200;
|
||||
//// 下方视野标准角度
|
||||
//public static double StandardLowerAngle = 75;
|
||||
//===== 1. 你预先标定的 空模标准面积 =====
|
||||
// 单眼标准、总标准(左+右)、双目重叠标准
|
||||
public static double StandardLeftEye = 5180;
|
||||
|
||||
public static double StandardRightEye = 5180;
|
||||
|
||||
public static double StandardTotal = 10360;
|
||||
|
||||
|
||||
public static double StandardBinocular = 4150;
|
||||
|
||||
//===== 2. 传入你采集的实测面积 =====
|
||||
// leftArea:左眼实测 rightArea:右眼实测 binArea:双目重叠实测
|
||||
public static double CalcVisionRate(double leftArea, double rightArea)
|
||||
{
|
||||
// 总视野实测 = 左+右
|
||||
double totalSi = leftArea + rightArea;
|
||||
|
||||
// 1. 总视野保存率
|
||||
double ratioTotal = totalSi / StandardTotal;
|
||||
double gammaTotal = GetVisionGamma(ratioTotal);
|
||||
double totalRate = gammaTotal * ratioTotal * 100;
|
||||
return (totalRate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GB2890-2022 自动获取 总视野/双目视野 校正系数γ
|
||||
/// </summary>
|
||||
/// <param name="ratio">实测面积/标准面积 比值(0~1)</param>
|
||||
/// <returns>校正系数 γ</returns>
|
||||
public static double GetVisionGamma(double ratio)
|
||||
{
|
||||
// X:视野残存率 Si/S0
|
||||
double[] xData = { 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
|
||||
|
||||
// 总视野 γ 对应值
|
||||
double[] gammaTotal = { 1.22, 1.18, 1.14, 1.10, 1.06, 1.03, 1.02, 1.01, 1.00 };
|
||||
|
||||
double[] yData = gammaTotal;
|
||||
|
||||
// 边界限制
|
||||
if (ratio <= xData[0]) return yData[0];
|
||||
if (ratio >= xData.Last()) return 1.0;
|
||||
|
||||
// 线性插值
|
||||
for (int i = 0; i < xData.Length - 1; i++)
|
||||
{
|
||||
if (ratio >= xData[i] && ratio <= xData[i + 1])
|
||||
{
|
||||
double t = (ratio - xData[i]) / (xData[i + 1] - xData[i]);
|
||||
return yData[i] + t * (yData[i + 1] - yData[i]);
|
||||
}
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
internal static double CalculateEyeArea(List<dynamic> leftEyeDataList, int v1, int v2)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static double CalcBinocularArea(List<dynamic> leftEyeDataList, List<dynamic> rightEyeDataList, int v1, int v2)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static double[] GetEyeAvgArray(List<dynamic> leftEyeDataList)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal static List<dynamic> RemoveOutliers(List<dynamic> leftEyeDataList)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
// 你算出来的实际面积
|
||||
//double left = 4250;
|
||||
//double right = 4320;
|
||||
//double bin = 2860;
|
||||
|
||||
//// 一键算出 国标保存率
|
||||
//var result = CalcVisionRate(left, right, bin);
|
||||
|
||||
//double 总视野保存率 = result.totalRate;
|
||||
//double 双目视野保存率 = result.binRate;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//// 1. 总视野保存率
|
||||
//double gammaTotal = 查国标图D.4的总视野γ;
|
||||
//double totalRate = gammaTotal * totalArea / GlobalData.StandardTotalEye * 100;
|
||||
|
||||
// // 2. 双目视野保存率
|
||||
// double gammaBinoc = 查国标图D.4的双目视野γ;
|
||||
//double binocRate = gammaBinoc * binocArea / GlobalData.StandardBinocular * 100;
|
||||
|
||||
//// 3. 下方视野(直接比角度,不用面积)
|
||||
//bool lowerPass = lowerAngle >= 35;
|
||||
|
||||
|
||||
|
||||
// 四、关键澄清(你之前问的)
|
||||
//下方视野:国标是角度(°),不是面积
|
||||
//按左右眼视野曲线下方交点位置直接读出角度
|
||||
//合格:≥35°
|
||||
|
||||
//总视野 = 左眼 + 右眼(国标明确)
|
||||
|
||||
//双目视野 = 左右眼重叠部分(单独算面积)
|
||||
|
||||
//五、最简总结(国标一句话)
|
||||
|
||||
//总视野保存率 =(γ ×(左 + 右实测面积))/ 标准总面积 ×100%
|
||||
|
||||
//双目视野保存率 =(γ × 重叠实测面积)/ 标准重叠面积 ×100%
|
||||
|
||||
//下方视野:直接看角度 ≥35°
|
||||
//}
|
||||
}
|
||||
Reference in New Issue
Block a user