|
@@ -9,6 +9,7 @@ using System.Linq;
|
|
|
using System.Threading.Tasks;
|
|
using System.Threading.Tasks;
|
|
|
using UnityEngine;
|
|
using UnityEngine;
|
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.UIElements;
|
|
|
|
|
+using UnityStandardAssets.Utility;
|
|
|
using ZIM;
|
|
using ZIM;
|
|
|
using ZIM.Unity;
|
|
using ZIM.Unity;
|
|
|
|
|
|
|
@@ -144,6 +145,9 @@ namespace o0.Project
|
|
|
|
|
|
|
|
//bStartLocateScreen = false;
|
|
//bStartLocateScreen = false;
|
|
|
|
|
|
|
|
|
|
+ ScreenWhiteTexture = null;
|
|
|
|
|
+ ScreenBlackTexture = null;
|
|
|
|
|
+
|
|
|
OnLocateScreenEnter?.Invoke();
|
|
OnLocateScreenEnter?.Invoke();
|
|
|
}
|
|
}
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -667,15 +671,18 @@ namespace o0.Project
|
|
|
// 屏幕黑白差值,存放多批次的图像用于识别, 该List数量不能等于 0
|
|
// 屏幕黑白差值,存放多批次的图像用于识别, 该List数量不能等于 0
|
|
|
List<UnityEngine.Color[]> PixelsMultipleBatches = new List<UnityEngine.Color[]>();
|
|
List<UnityEngine.Color[]> PixelsMultipleBatches = new List<UnityEngine.Color[]>();
|
|
|
|
|
|
|
|
- var sw = new System.Diagnostics.Stopwatch();
|
|
|
|
|
- sw.Start();
|
|
|
|
|
|
|
+ //var sw = new System.Diagnostics.Stopwatch();
|
|
|
|
|
+ //sw.Start();
|
|
|
|
|
|
|
|
//读取数据
|
|
//读取数据
|
|
|
if (debugImages != null && debugImages.Count != 0)
|
|
if (debugImages != null && debugImages.Count != 0)
|
|
|
{
|
|
{
|
|
|
|
|
+ var dSize = debugImages.First().Size();
|
|
|
foreach (var i in debugImages)
|
|
foreach (var i in debugImages)
|
|
|
{
|
|
{
|
|
|
Debug.Log($"<color=aqua>Debug {i.name}</color>");
|
|
Debug.Log($"<color=aqua>Debug {i.name}</color>");
|
|
|
|
|
+ if (i.Size() != dSize)
|
|
|
|
|
+ throw new InvalidOperationException("Multiple Debug textures have different sizes");
|
|
|
PixelsMultipleBatches.Add(i.GetPixels());
|
|
PixelsMultipleBatches.Add(i.GetPixels());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -698,8 +705,8 @@ namespace o0.Project
|
|
|
for (int y = 0; y < Size.y; y++)
|
|
for (int y = 0; y < Size.y; y++)
|
|
|
{
|
|
{
|
|
|
var i = y * Size.x + x;
|
|
var i = y * Size.x + x;
|
|
|
- var d = ScreenWhiteTexture[i] - ScreenBlackTexture[i];
|
|
|
|
|
- differPixel[i] = new UnityEngine.Color(d.x, d.y, d.z) * scale;
|
|
|
|
|
|
|
+ var d = ScreenWhiteTexture[i] * scale - ScreenBlackTexture[i];
|
|
|
|
|
+ differPixel[i] = new UnityEngine.Color(d.x, d.y, d.z);
|
|
|
whitePixel[i] = new UnityEngine.Color(ScreenWhiteTexture[i].x, ScreenWhiteTexture[i].y, ScreenWhiteTexture[i].z) * scale;
|
|
whitePixel[i] = new UnityEngine.Color(ScreenWhiteTexture[i].x, ScreenWhiteTexture[i].y, ScreenWhiteTexture[i].z) * scale;
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
@@ -710,8 +717,8 @@ namespace o0.Project
|
|
|
int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1;
|
|
int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1;
|
|
|
conSize = Math.Max(conSize, 7); // 设置最小为7
|
|
conSize = Math.Max(conSize, 7); // 设置最小为7
|
|
|
|
|
|
|
|
- float minLength = conSize * 7.7f;
|
|
|
|
|
- minLength = locateIndex == -1 ? minLength : minLength * areaPercent; // minLength需要按比例缩小
|
|
|
|
|
|
|
+ float minLength = conSize * 6f;
|
|
|
|
|
+ minLength = locateIndex == -1 ? minLength : minLength * areaPercent; // minLength需要按areaPercent比例缩小
|
|
|
string log = $"[Log][ScreenLocate Auto] Size: ({Size.x},{Size.y}), 卷积核Size: {conSize}, 最小线段长度: {minLength}";
|
|
string log = $"[Log][ScreenLocate Auto] Size: ({Size.x},{Size.y}), 卷积核Size: {conSize}, 最小线段长度: {minLength}";
|
|
|
|
|
|
|
|
var allLines = new List<LineIdentified>();
|
|
var allLines = new List<LineIdentified>();
|
|
@@ -722,20 +729,47 @@ namespace o0.Project
|
|
|
var locateTex = ToLocateTex(PixelsMultipleBatches[batch]);
|
|
var locateTex = ToLocateTex(PixelsMultipleBatches[batch]);
|
|
|
LocateTexTemp.Add(locateTex);
|
|
LocateTexTemp.Add(locateTex);
|
|
|
var ScreenLocateMat = locateTex.Too0Mat(); // 用于获取Lines的Matrix
|
|
var ScreenLocateMat = locateTex.Too0Mat(); // 用于获取Lines的Matrix
|
|
|
- var lineCount = ZIMIdentifyQuadLSD(ref allLines, batch, ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize), minLength);
|
|
|
|
|
|
|
+ var lineCount = ZIMIdentifyQuadLSD(
|
|
|
|
|
+ ref allLines,
|
|
|
|
|
+ batch,
|
|
|
|
|
+ ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize),
|
|
|
|
|
+ minLength,
|
|
|
|
|
+ new Vector(minLength * 0.4f, conSize * 1.6f));
|
|
|
log += $"\r\n识别图片{batch}, 识别到的线段数量为: {lineCount}";
|
|
log += $"\r\n识别图片{batch}, 识别到的线段数量为: {lineCount}";
|
|
|
ScreenLocateMatList.Add(ScreenLocateMat);
|
|
ScreenLocateMatList.Add(ScreenLocateMat);
|
|
|
}
|
|
}
|
|
|
Texture2D ScreenLocateTexture = LocateTexTemp[0]; // for output
|
|
Texture2D ScreenLocateTexture = LocateTexTemp[0]; // for output
|
|
|
|
|
|
|
|
|
|
+ // LSD计算得到的矩阵尺寸较小(因为卷积),这里必须进行位移
|
|
|
|
|
+ // 新增:根据阈值筛去梯度太低的线段
|
|
|
|
|
+ float minGradient = 0.09f;
|
|
|
|
|
+ var offset = new Vector((conSize - 1) / 2, (conSize - 1) / 2);
|
|
|
|
|
+ var tempList = new List<LineIdentified>();
|
|
|
|
|
+ for (int i = 0; i < allLines.Count; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ var l = allLines[i];
|
|
|
|
|
+ if (l.Gradient > minGradient * l.Line.Length)
|
|
|
|
|
+ {
|
|
|
|
|
+ l.Offset(offset);
|
|
|
|
|
+ tempList.Add(l);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ allLines = tempList;
|
|
|
|
|
+ log += $"\r\n根据梯度阈值筛选,最终线段数量为: {allLines.Count}";
|
|
|
|
|
+
|
|
|
// 如果有手动数据,刷新一下Size
|
|
// 如果有手动数据,刷新一下Size
|
|
|
QuadManual?.ReSize(new Vector(Size.x, Size.y), ScreenMap.ViewAspectRatioSetting);
|
|
QuadManual?.ReSize(new Vector(Size.x, Size.y), ScreenMap.ViewAspectRatioSetting);
|
|
|
// 估算屏幕中点,如果已有手动定位数据,根据现有数据取平均即可,否则从色差计算,ScreenLocateMatList[0]默认是屏幕的黑白色差
|
|
// 估算屏幕中点,如果已有手动定位数据,根据现有数据取平均即可,否则从色差计算,ScreenLocateMatList[0]默认是屏幕的黑白色差
|
|
|
Vector AvgPoint = QuadManual != null ? QuadManual.Quad.Centroid : GetAvgPoint(ScreenLocateMatList[0]);
|
|
Vector AvgPoint = QuadManual != null ? QuadManual.Quad.Centroid : GetAvgPoint(ScreenLocateMatList[0]);
|
|
|
// 过滤得到四边形的四条边,
|
|
// 过滤得到四边形的四条边,
|
|
|
- var (quadLinesSemiAuto, quadLinesAuto) = FilterLines(ScreenLocateMatList, allLines, AvgPoint,
|
|
|
|
|
- out LineIdentified[] manualLines, out List<LineIdentified> possibleLines,
|
|
|
|
|
- conSize, conSize, minLength);
|
|
|
|
|
|
|
+ var (quadLinesSemiAuto, quadLinesAuto) = FilterLines(
|
|
|
|
|
+ ScreenLocateMatList,
|
|
|
|
|
+ allLines,
|
|
|
|
|
+ AvgPoint,
|
|
|
|
|
+ out LineIdentified[] manualLines,
|
|
|
|
|
+ out List<LineIdentified> possibleLines,
|
|
|
|
|
+ conSize,
|
|
|
|
|
+ minLength);
|
|
|
|
|
|
|
|
#region 全自动识别的结果
|
|
#region 全自动识别的结果
|
|
|
List<LineIdentified> LineIdentifiedAuto = new List<LineIdentified>(); // 线段顺序: 下、右、上、左
|
|
List<LineIdentified> LineIdentifiedAuto = new List<LineIdentified>(); // 线段顺序: 下、右、上、左
|
|
@@ -808,7 +842,7 @@ namespace o0.Project
|
|
|
o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 5, new Geometry2D.Float.Vector(0, 10));
|
|
o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 5, new Geometry2D.Float.Vector(0, 10));
|
|
|
else
|
|
else
|
|
|
o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 3, new Geometry2D.Float.Vector(0, 6), true);
|
|
o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 3, new Geometry2D.Float.Vector(0, 6), true);
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 绘制全自动
|
|
// 绘制全自动
|
|
|
foreach (var i in LineIdentifiedAuto.Index())
|
|
foreach (var i in LineIdentifiedAuto.Index())
|
|
@@ -910,9 +944,9 @@ namespace o0.Project
|
|
|
|
|
|
|
|
// 返回查找到的线段数量,0是查找失败
|
|
// 返回查找到的线段数量,0是查找失败
|
|
|
int ZIMIdentifyQuadLSD(ref List<LineIdentified> allLines, int batch, (Matrix edgeMat, Matrix edgeDirMat) edgeGradient,
|
|
int ZIMIdentifyQuadLSD(ref List<LineIdentified> allLines, int batch, (Matrix edgeMat, Matrix edgeDirMat) edgeGradient,
|
|
|
- float minLength = 100)
|
|
|
|
|
|
|
+ float minLength, Vector LineCaptureSize)
|
|
|
{
|
|
{
|
|
|
- var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 50, LineCaptureSize: new Vector(10, 6));
|
|
|
|
|
|
|
+ var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 25, LineCaptureSize);
|
|
|
if (l == null || l.Count == 0)
|
|
if (l == null || l.Count == 0)
|
|
|
return 0;
|
|
return 0;
|
|
|
allLines.AddRange(l.Select((i) => new LineIdentified(batch, i)));
|
|
allLines.AddRange(l.Select((i) => new LineIdentified(batch, i)));
|
|
@@ -921,14 +955,8 @@ namespace o0.Project
|
|
|
|
|
|
|
|
// 返回四边形的四条边(半自动、全自动),List长度一定是4 (如果没有识别到就是null),且线段顺序是: 下、右、上、左
|
|
// 返回四边形的四条边(半自动、全自动),List长度一定是4 (如果没有识别到就是null),且线段顺序是: 下、右、上、左
|
|
|
(List<LineIdentified>, List<LineIdentified>) FilterLines(List<Matrix> screenLocateMatList, List<LineIdentified> allLines, Vector avgPoint,
|
|
(List<LineIdentified>, List<LineIdentified>) FilterLines(List<Matrix> screenLocateMatList, List<LineIdentified> allLines, Vector avgPoint,
|
|
|
- out LineIdentified[] manualLines, out List<LineIdentified> possibleLines, float conSize, float gradientLength, float minLength = 100)
|
|
|
|
|
|
|
+ out LineIdentified[] manualLines, out List<LineIdentified> possibleLines, float gradientLength, float minLength = 100)
|
|
|
{
|
|
{
|
|
|
- //Debug.Log("[IdentifyLineLSD] lines.Count: " + lines.Count);
|
|
|
|
|
- var offset = new Vector((conSize - 1) / 2, (conSize - 1) / 2);
|
|
|
|
|
- // LSD计算得到的矩阵尺寸较小(因为卷积),这里必须进行位移
|
|
|
|
|
- for (int i = 0; i < allLines.Count; i++)
|
|
|
|
|
- allLines[i].Offset(offset);
|
|
|
|
|
-
|
|
|
|
|
// 筛掉椭圆框外的线段(超出一半会筛掉)
|
|
// 筛掉椭圆框外的线段(超出一半会筛掉)
|
|
|
var innerLines = new List<LineIdentified>();
|
|
var innerLines = new List<LineIdentified>();
|
|
|
for (int i = 0; i < allLines.Count; i++)
|
|
for (int i = 0; i < allLines.Count; i++)
|
|
@@ -955,12 +983,12 @@ namespace o0.Project
|
|
|
// 角度阈值,用来判断线段的梯度方向是否指向屏幕中心(avgPoint)
|
|
// 角度阈值,用来判断线段的梯度方向是否指向屏幕中心(avgPoint)
|
|
|
var avaAngleHalf = 75f;
|
|
var avaAngleHalf = 75f;
|
|
|
|
|
|
|
|
- // 沿直线计算综合梯度(梯度乘以长度系数,再乘以距离系数), distanceRatio是实际距离除以最大距离
|
|
|
|
|
- float estimateGradient(LineIdentified line, float distanceRatio)
|
|
|
|
|
|
|
+ #region 内部函数
|
|
|
|
|
+ float ScreenGrad(LineIdentified line)
|
|
|
{
|
|
{
|
|
|
var dir = (line.Line.B - line.Line.A).Normalized;
|
|
var dir = (line.Line.B - line.Line.A).Normalized;
|
|
|
var vertical = new Vector(-dir.y, dir.x) * (gradientLength / 2);
|
|
var vertical = new Vector(-dir.y, dir.x) * (gradientLength / 2);
|
|
|
- var step = 2;
|
|
|
|
|
|
|
+ int step = (int)(minLength / 5);
|
|
|
var ll = line.Line.Length;
|
|
var ll = line.Line.Length;
|
|
|
var lg = new List<float>();
|
|
var lg = new List<float>();
|
|
|
for (int i = 0; i <= ll; i += step)
|
|
for (int i = 0; i <= ll; i += step)
|
|
@@ -970,17 +998,24 @@ namespace o0.Project
|
|
|
var gb = point - vertical;
|
|
var gb = point - vertical;
|
|
|
lg.Add(screenLocateMatList[line.Batch][(int)ga.x, (int)ga.y] - screenLocateMatList[line.Batch][(int)gb.x, (int)gb.y]);
|
|
lg.Add(screenLocateMatList[line.Batch][(int)ga.x, (int)ga.y] - screenLocateMatList[line.Batch][(int)gb.x, (int)gb.y]);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ return Math.Abs(lg.Mean());
|
|
|
|
|
+ }
|
|
|
|
|
+ // 沿直线计算综合梯度(梯度乘以长度系数,再乘以距离系数), distanceRatio是实际距离除以最大距离
|
|
|
|
|
+ float estimateGradient(LineIdentified line, float distanceRatio)
|
|
|
|
|
+ {
|
|
|
|
|
+ var gM = ScreenGrad(line);
|
|
|
float e = (float)Math.Sqrt(Math.Ceiling(line.Line.Length / minLength)); // 长度系数,筛选时梯度更大、长度更长的线段更优
|
|
float e = (float)Math.Sqrt(Math.Ceiling(line.Line.Length / minLength)); // 长度系数,筛选时梯度更大、长度更长的线段更优
|
|
|
- float d = (3 - distanceRatio) / 2; // 距离系数,距离越近,系数越大
|
|
|
|
|
- return e * d * Math.Abs(lg.Mean());
|
|
|
|
|
|
|
+ float d = (5 - distanceRatio) / 4; // 距离系数,距离越近,系数越大
|
|
|
|
|
+
|
|
|
|
|
+ line.ZIMGradient = e * d * gM; // 记录一下综合梯度,全自动新增的功能会二次使用
|
|
|
|
|
+ return line.ZIMGradient;
|
|
|
}
|
|
}
|
|
|
- // 根据线段梯度的角度,判断是不是屏幕的边,out index代表是哪条边(顺序是: 下、右、上、左)
|
|
|
|
|
- bool isScreenLine(LineIdentified line, out int index)
|
|
|
|
|
|
|
+ // 根据线段梯度的角度,判断是不是屏幕的边,index代表是哪条边(顺序是: 下、右、上、左)
|
|
|
|
|
+ void GetScreenLineIndex(LineIdentified line)
|
|
|
{
|
|
{
|
|
|
var a = (avgPoint - (line.Line.A + line.Line.B) / 2).DegreeToXAxis();
|
|
var a = (avgPoint - (line.Line.A + line.Line.B) / 2).DegreeToXAxis();
|
|
|
//Debug.Log(a + ", " + gradient + ", " + sum);
|
|
//Debug.Log(a + ", " + gradient + ", " + sum);
|
|
|
- index = -1;
|
|
|
|
|
|
|
+ var index = -1;
|
|
|
if (Math.Abs(a - line.GradientDegree) < avaAngleHalf || Math.Abs(a - 360 - line.GradientDegree) < avaAngleHalf || Math.Abs(a + 360 - line.GradientDegree) < avaAngleHalf)
|
|
if (Math.Abs(a - line.GradientDegree) < avaAngleHalf || Math.Abs(a - 360 - line.GradientDegree) < avaAngleHalf || Math.Abs(a + 360 - line.GradientDegree) < avaAngleHalf)
|
|
|
{
|
|
{
|
|
|
if (line.GradientDegree > 45 && line.GradientDegree < 135) // 下
|
|
if (line.GradientDegree > 45 && line.GradientDegree < 135) // 下
|
|
@@ -991,11 +1026,14 @@ namespace o0.Project
|
|
|
index = 2;
|
|
index = 2;
|
|
|
else
|
|
else
|
|
|
index = 3;
|
|
index = 3;
|
|
|
- return true;
|
|
|
|
|
}
|
|
}
|
|
|
- return false;
|
|
|
|
|
|
|
+ line.ScreenLineIndex = index;
|
|
|
}
|
|
}
|
|
|
|
|
+ #endregion
|
|
|
|
|
|
|
|
|
|
+ // 根据梯度方向,判断是哪条边
|
|
|
|
|
+ foreach (var l in innerLines)
|
|
|
|
|
+ GetScreenLineIndex(l);
|
|
|
|
|
|
|
|
// 下、右、上、左, 半自动和自动
|
|
// 下、右、上、左, 半自动和自动
|
|
|
var quadLinesSemiAuto = new List<(float, LineIdentified)>[4] { new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>() };
|
|
var quadLinesSemiAuto = new List<(float, LineIdentified)>[4] { new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>() };
|
|
@@ -1015,17 +1053,17 @@ namespace o0.Project
|
|
|
foreach (var line in innerLines)
|
|
foreach (var line in innerLines)
|
|
|
{
|
|
{
|
|
|
// 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-线段的AB点均在旧线段外部, 4-新的线段的中点,到旧线段的垂足,要在旧线段内
|
|
// 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-线段的AB点均在旧线段外部, 4-新的线段的中点,到旧线段的垂足,要在旧线段内
|
|
|
- if (isScreenLine(line, out int index))
|
|
|
|
|
|
|
+ if (line.ScreenLineIndex >= 0)
|
|
|
{
|
|
{
|
|
|
- var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[index]).Length;
|
|
|
|
|
|
|
+ var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[line.ScreenLineIndex]).Length;
|
|
|
if (distanceToOld < calibration &&
|
|
if (distanceToOld < calibration &&
|
|
|
- manualLines[index].Line.LineCrossWithPoint(line.Line.A) * avgPointCross[index] <= 0 &&
|
|
|
|
|
- manualLines[index].Line.LineCrossWithPoint(line.Line.B) * avgPointCross[index] <= 0)
|
|
|
|
|
|
|
+ manualLines[line.ScreenLineIndex].Line.LineCrossWithPoint(line.Line.A) * avgPointCross[line.ScreenLineIndex] <= 0 &&
|
|
|
|
|
+ manualLines[line.ScreenLineIndex].Line.LineCrossWithPoint(line.Line.B) * avgPointCross[line.ScreenLineIndex] <= 0)
|
|
|
{
|
|
{
|
|
|
- var middleToOldLine = o0Extension.PointPedal(manualLines[index].Line, (line.Line.A + line.Line.B) / 2, out bool inLineSegment);
|
|
|
|
|
|
|
+ var middleToOldLine = o0Extension.PointPedal(manualLines[line.ScreenLineIndex].Line, (line.Line.A + line.Line.B) / 2, out bool inLineSegment);
|
|
|
if (inLineSegment)
|
|
if (inLineSegment)
|
|
|
{
|
|
{
|
|
|
- quadLinesSemiAuto[index].Add((estimateGradient(line, distanceToOld / calibration), line));
|
|
|
|
|
|
|
+ quadLinesSemiAuto[line.ScreenLineIndex].Add((estimateGradient(line, distanceToOld / calibration), line));
|
|
|
possibleLines.Add(line);
|
|
possibleLines.Add(line);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1034,29 +1072,96 @@ namespace o0.Project
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 全自动
|
|
// 全自动
|
|
|
- foreach (var line in allLines)
|
|
|
|
|
|
|
+ foreach (var line in innerLines)
|
|
|
{
|
|
{
|
|
|
- if (isScreenLine(line, out int index))
|
|
|
|
|
|
|
+ if (line.ScreenLineIndex >= 0 && line.Batch < 1) // 全自动只处理第一张图,默认是色差图
|
|
|
{
|
|
{
|
|
|
- if (line.Batch < 1) // 全自动只处理第一张图,默认是色差图
|
|
|
|
|
- {
|
|
|
|
|
- quadLinesAuto[index].Add((estimateGradient(line, 1), line));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ quadLinesAuto[line.ScreenLineIndex].Add((estimateGradient(line, 1), line));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 获得半自动和全自动的结果
|
|
|
var resultSemiAuto = new LineIdentified[4];
|
|
var resultSemiAuto = new LineIdentified[4];
|
|
|
var resultAuto = new LineIdentified[4];
|
|
var resultAuto = new LineIdentified[4];
|
|
|
|
|
+ var resultAutoPedal = new Vector[4]; // 用于找全自动的平行线
|
|
|
for (int i = 0; i < 4; i++)
|
|
for (int i = 0; i < 4; i++)
|
|
|
{
|
|
{
|
|
|
if (quadLinesSemiAuto[i].Count > 0)
|
|
if (quadLinesSemiAuto[i].Count > 0)
|
|
|
resultSemiAuto[i] = quadLinesSemiAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
|
|
resultSemiAuto[i] = quadLinesSemiAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
|
|
|
if (quadLinesAuto[i].Count > 0)
|
|
if (quadLinesAuto[i].Count > 0)
|
|
|
|
|
+ {
|
|
|
resultAuto[i] = quadLinesAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
|
|
resultAuto[i] = quadLinesAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
|
|
|
|
|
+ if (resultAuto[i] != null)
|
|
|
|
|
+ resultAutoPedal[i] = o0Extension.PointPedal(resultAuto[i].Line, avgPoint, out _);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 新增功能(全自动,为了解决黑边问题):根据 resultAuto 再找平行线,判断是否替换(1-在 resultAuto 内部,2-接近平行,3-LineGuess判断是直线)
|
|
|
|
|
+ // 半自动不增加这个功能,直接通过增加到手动数据的距离阈值来解决黑边问题
|
|
|
|
|
+ var interSelectable = new List<LineIdentified>();
|
|
|
|
|
+ foreach (var line in innerLines)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (line.ScreenLineIndex >= 0 && line.Batch < 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (line != resultAuto[line.ScreenLineIndex])
|
|
|
|
|
+ {
|
|
|
|
|
+ var pedal = o0Extension.PointPedal(line.Line, avgPoint, out _);
|
|
|
|
|
+ var a0 = pedal - avgPoint;
|
|
|
|
|
+ var a0L = a0.Length;
|
|
|
|
|
+ line.DistanceToMiddle = a0L;
|
|
|
|
|
+ var a1 = resultAutoPedal[line.ScreenLineIndex] - avgPoint;
|
|
|
|
|
+ var a1L = a1.Length;
|
|
|
|
|
+ if (a0L < a1L)
|
|
|
|
|
+ {
|
|
|
|
|
+ var dotN = a0.Dot(a1) / a0L / a1L;
|
|
|
|
|
+ if (Math.Abs(dotN - 1) < 0.001) // 接近平行即可
|
|
|
|
|
+ interSelectable.Add(line);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ var (interA, interB) = FindInterLinePair(new LineGuess(screenLocateMatList, gradientLength * 2, minLength), interSelectable, 12);
|
|
|
|
|
+ if (interA != null && interB != null) // 替换上一步筛选的结果中的一对边,得到最终的结果
|
|
|
|
|
+ {
|
|
|
|
|
+ resultAuto[interA.ScreenLineIndex] = interA;
|
|
|
|
|
+ resultAuto[interB.ScreenLineIndex] = interB;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return (resultSemiAuto.ToList(), resultAuto.ToList());
|
|
return (resultSemiAuto.ToList(), resultAuto.ToList());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (LineIdentified a, LineIdentified b) FindInterLinePair(LineGuess lineGuess, List<LineIdentified> interSelectable, int maxCountToSelect = 12)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log("[ScreenIdentification] selectable inter line count: " + interSelectable.Count);
|
|
|
|
|
+ interSelectable.Sort((a, b) => b.ZIMGradient.CompareTo(a.ZIMGradient));
|
|
|
|
|
+ int count = 0;
|
|
|
|
|
+ LineIdentified[] selected = new LineIdentified[4];
|
|
|
|
|
+ foreach (var line in interSelectable)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (lineGuess.GuessIsLine(line)) // 评价是不是Line, 并且找到离中心点最近的
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log("[ScreenIdentification] guess is line: (index)" + line.ScreenLineIndex);
|
|
|
|
|
+ if (selected[line.ScreenLineIndex] == null || selected[line.ScreenLineIndex].DistanceToMiddle > line.DistanceToMiddle)
|
|
|
|
|
+ selected[line.ScreenLineIndex] = line;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (count++ >= maxCountToSelect)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (selected[0] != null && selected[1] != null && selected[2] != null && selected[3] != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (selected[0].ZIMGradient + selected[2].ZIMGradient > selected[1].ZIMGradient + selected[3].ZIMGradient)
|
|
|
|
|
+ return (selected[0], selected[2]);
|
|
|
|
|
+ else
|
|
|
|
|
+ return (selected[1], selected[3]);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (selected[0] != null && selected[2] != null)
|
|
|
|
|
+ return (selected[0], selected[2]);
|
|
|
|
|
+ else if (selected[1] != null && selected[3] != null)
|
|
|
|
|
+ return (selected[1], selected[3]);
|
|
|
|
|
+ else
|
|
|
|
|
+ return (null, null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
void SaveImages(string FileDirectory, string log,
|
|
void SaveImages(string FileDirectory, string log,
|
|
|
Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ChoosableLineTex, Texture2D ScreenQuadTex)
|
|
Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ChoosableLineTex, Texture2D ScreenQuadTex)
|
|
|
{
|
|
{
|