| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- using o0.Geometry2D.Float;
- using o0.Num;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- namespace o0.Project
- {
- // 大于阈值则猜测是Line,但是这个类不考虑梯度,外部仍需结合梯度评估
- public class LineGuess
- {
- public static float isLineThreshold = 1.0f;
- // 记录分段的线段数据
- class SubLineData
- {
- public List<float> DataList;
- public List<float> DiffList; // 数据与平均值的差
- // 幅度
- float diffExtent = -1;
- float dataExtent = -1;
- public SubLineData(float data, float diff)
- {
- DataList = new List<float> { data };
- DiffList = new List<float> { diff };
- }
- public void Add(float data, float diff)
- {
- DataList.Add(data);
- DiffList.Add(diff);
- }
- // 得到差异的幅度
- public float GetDiffExtent()
- {
- if (diffExtent == -1)
- {
- var sum = 0.0f;
- foreach (var i in DiffList)
- sum += i * i;
- return diffExtent = sum / DiffList.Count;
- }
- else
- return diffExtent;
- }
- // 得到数据的幅度(和0比)
- public float GetDataExtent()
- {
- if (dataExtent == -1)
- {
- var sum = 0.0f;
- foreach (var i in DataList)
- sum += i * i;
- return dataExtent = sum / DataList.Count;
- }
- else
- return dataExtent;
- }
- }
- public List<Matrix> ScreenLocateMatList;
- public float GradientLength;
- public float MinLineLength;
- public LineGuess(List<Matrix> screenLocateMatList, float gradientLength, float minLineLength)
- {
- ScreenLocateMatList = screenLocateMatList;
- GradientLength = gradientLength;
- MinLineLength = minLineLength;
- }
- // 猜测是直线返回true
- public bool GuessIsLine(LineIdentified line) => Guess(line) > isLineThreshold;
- // 越大越可能是直线
- public float Guess(LineIdentified line)
- {
- var dir = (line.Line.B - line.Line.A).Normalized;
- var vertical = new Vector(-dir.y, dir.x) * (GradientLength / 2);
- var verticalNormal = vertical.Normalized;
- int lineABStep = (int)(MinLineLength / 5);
- var ll = line.Line.Length;
- var gradData = new List<float>(); // 直线两侧梯度的平均值,垂直于直线变化
- var a0 = line.Line.A - vertical;
- var gradStep = 1.5f;
- for (float n = 0; n < GradientLength; n += gradStep)
- {
- var aN = a0 + verticalNormal * n;
- var gradThisLine = new List<float>();
- for (int i = 0; i <= ll; i += lineABStep)
- {
- var point = aN + dir * i;
- gradThisLine.Add(ScreenLocateMatList[line.Batch][(int)point.x, (int)point.y]);
- }
- gradData.Add(gradThisLine.Mean());
- }
- //Debug.Log(line.Gradient + ", " + line.GradientDegree + ", " + gradData.ToJson());
- if (gradData.Count <= 3)
- return 400;
- var gradChangeData = new List<float>();
- for (int j = 1; j < gradData.Count; j++)
- gradChangeData.Add(Math.Abs(gradData[j] - gradData[j - 1]));
- var meanChange = gradChangeData.Mean();
- var diff = gradChangeData[0] - meanChange;
- var subList = new List<SubLineData>() { new SubLineData(gradChangeData[0], diff) };
- for (int i = 1; i < gradChangeData.Count; i++)
- {
- var newDiff = gradChangeData[i] - meanChange;
- if ((newDiff <= 0 && diff <= 0) || (newDiff > 0 && diff > 0)) // 同号,是一个分段
- subList.Last().Add(gradChangeData[i], newDiff);
- else
- subList.Add(new SubLineData(gradChangeData[i], newDiff));
- diff = newDiff;
- }
- int maxDiffIndex = -1;
- if (subList.Count >= 3)
- maxDiffIndex = subList.MaxIndex((a, b) => a.GetDiffExtent().CompareTo(b.GetDiffExtent())); // 找到分段里和平均数差异最大的分段,计算数据幅度的时候不计入
- var lineGuessExtent = 0.0f;
- for (int i = 0; i < subList.Count; i++)
- {
- if (i != maxDiffIndex)
- lineGuessExtent += subList[i].GetDataExtent();
- }
- if (maxDiffIndex == -1)
- lineGuessExtent /= subList.Count;
- else
- lineGuessExtent /= subList.Count - 1;
- lineGuessExtent = (float)Math.Sqrt(lineGuessExtent);
- var countFactor = -0.002f * Math.Abs(subList.Count - 3) + 0.015f; // 3时最大
- //Debug.Log("maxDiffIndex: " + maxDiffIndex + ", sub count: " + subList.Count + ", lineGuess: " + (1 - lineGuessExtent + countFactor));
- return 1 - lineGuessExtent + countFactor;
- }
- }
- }
|