|
@@ -77,8 +77,8 @@ namespace o0.Project
|
|
|
public ScreenIdentification()
|
|
public ScreenIdentification()
|
|
|
{
|
|
{
|
|
|
Screen = new ScreenMap();
|
|
Screen = new ScreenMap();
|
|
|
- //OnLocateScreenEnter += () => Debug.Log("OnLocateScreenEnter");
|
|
|
|
|
- //OnLocateScreenEnd += () => Debug.Log("OnLocateScreenEnd");
|
|
|
|
|
|
|
+ OnLocateScreenEnter += () => Application.targetFrameRate = 30; // 固定识别的帧率,确保摄像机拍到正确的画面
|
|
|
|
|
+ OnLocateScreenEnd += () => Application.targetFrameRate = 60;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void SetScreenQuad(QuadrilateralInCamera quad) => Screen.QuadInCamera = quad;
|
|
public void SetScreenQuad(QuadrilateralInCamera quad) => Screen.QuadInCamera = quad;
|
|
@@ -88,7 +88,7 @@ namespace o0.Project
|
|
|
public bool bStartLocateScreen { get; set; } = false;//是否进行捕获
|
|
public bool bStartLocateScreen { get; set; } = false;//是否进行捕获
|
|
|
|
|
|
|
|
// 自动识别开始的入口
|
|
// 自动识别开始的入口
|
|
|
- public void LocateScreen(int Capture = 45, int Delay = 45) //数值单位是frame
|
|
|
|
|
|
|
+ public void LocateScreen(int Capture = 30, int Delay = 30) //数值单位是frame
|
|
|
{
|
|
{
|
|
|
if (ScreenLocate.Main.DebugScreenImages.Count != 0 && ScreenLocate.Main.DebugOnZIMDemo) // 这段仅用于测试图片
|
|
if (ScreenLocate.Main.DebugScreenImages.Count != 0 && ScreenLocate.Main.DebugOnZIMDemo) // 这段仅用于测试图片
|
|
|
{
|
|
{
|
|
@@ -631,11 +631,8 @@ namespace o0.Project
|
|
|
//var ScreenLocateTexLightedMat = texture.Too0Mat();
|
|
//var ScreenLocateTexLightedMat = texture.Too0Mat();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// <param name="ScreenLocateTexture">用于算法检测线段的图片</param>
|
|
|
|
|
- /// <param name="ChoosableLineTex">输出备选线段</param>
|
|
|
|
|
- /// <param name="ScreenQuadTex">输出最终结果</param>
|
|
|
|
|
/// <param name="lineWidth">识别的最小线段长度</param>
|
|
/// <param name="lineWidth">识别的最小线段长度</param>
|
|
|
- /// <param name="debugImage">这个参数如果不为null,则执行debug操作</param>
|
|
|
|
|
|
|
+ /// <param name="debugImages">这个参数如果不为null且数量大于0,则执行debug操作</param>
|
|
|
void QuadrilateralFit(List<Texture2D> debugImages = null, float lineWidth = 10)
|
|
void QuadrilateralFit(List<Texture2D> debugImages = null, float lineWidth = 10)
|
|
|
{
|
|
{
|
|
|
// 屏幕黑白差值,存放多批次的图像用于识别, 该List数量不能等于 0
|
|
// 屏幕黑白差值,存放多批次的图像用于识别, 该List数量不能等于 0
|
|
@@ -653,14 +650,23 @@ namespace o0.Project
|
|
|
}
|
|
}
|
|
|
else // 获得屏幕差值
|
|
else // 获得屏幕差值
|
|
|
{
|
|
{
|
|
|
- PixelsMultipleBatches.Add(ScreenWhiteTexture.Select((i) => new UnityEngine.Color(i.x, i.y, i.z)).ToArray());
|
|
|
|
|
|
|
+ var maxWhite = 0f;
|
|
|
|
|
+ foreach (var i in ScreenWhiteTexture)
|
|
|
|
|
+ {
|
|
|
|
|
+ var m = i.x > i.y ? (i.x > i.z ? i.x : i.z) : (i.y > i.z ? i.y : i.z);
|
|
|
|
|
+ if (maxWhite < m)
|
|
|
|
|
+ maxWhite = m;
|
|
|
|
|
+ }
|
|
|
|
|
+ var scale = 1.0f / maxWhite; // 放大对比度
|
|
|
|
|
+
|
|
|
var differPixel = new UnityEngine.Color[Size.x * Size.y];
|
|
var differPixel = new UnityEngine.Color[Size.x * Size.y];
|
|
|
Parallel.For(0, Size.x * Size.y, i =>
|
|
Parallel.For(0, Size.x * Size.y, i =>
|
|
|
{
|
|
{
|
|
|
var pi = ScreenWhiteTexture[i] - ScreenBlackTexture[i];
|
|
var pi = ScreenWhiteTexture[i] - ScreenBlackTexture[i];
|
|
|
- differPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
|
|
|
|
|
|
|
+ differPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z) * scale;
|
|
|
});
|
|
});
|
|
|
PixelsMultipleBatches.Add(differPixel);
|
|
PixelsMultipleBatches.Add(differPixel);
|
|
|
|
|
+ PixelsMultipleBatches.Add(ScreenWhiteTexture.Select((i) => new UnityEngine.Color(i.x, i.y, i.z) * scale).ToArray());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1;
|
|
int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1;
|
|
@@ -671,20 +677,20 @@ namespace o0.Project
|
|
|
string log = $"[ScreenLocate Auto] Size: ({Size.x},{Size.y}), 卷积核Size: {conSize}, 最小线段长度: {minLength}";
|
|
string log = $"[ScreenLocate Auto] Size: ({Size.x},{Size.y}), 卷积核Size: {conSize}, 最小线段长度: {minLength}";
|
|
|
|
|
|
|
|
var allLines = new List<LineIdentified>();
|
|
var allLines = new List<LineIdentified>();
|
|
|
- Texture2D ScreenLocateTexture = null;
|
|
|
|
|
|
|
+ List<Texture2D> LocateTexTemp = new List<Texture2D>();
|
|
|
List<Matrix> ScreenLocateMatList = new List<Matrix>();
|
|
List<Matrix> ScreenLocateMatList = new List<Matrix>();
|
|
|
foreach (var batch in PixelsMultipleBatches.Index())
|
|
foreach (var batch in PixelsMultipleBatches.Index())
|
|
|
{
|
|
{
|
|
|
- ScreenLocateTexture = ToLocateTex(PixelsMultipleBatches[batch]);
|
|
|
|
|
- var ScreenLocateMat = ScreenLocateTexture.Too0Mat(); // 用于获取Lines的Matrix
|
|
|
|
|
- var lineCount = ZIMIdentifyQuadLSD(ref allLines, batch, ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize));
|
|
|
|
|
|
|
+ var locateTex = ToLocateTex(PixelsMultipleBatches[batch]);
|
|
|
|
|
+ LocateTexTemp.Add(locateTex);
|
|
|
|
|
+ var ScreenLocateMat = locateTex.Too0Mat(); // 用于获取Lines的Matrix
|
|
|
|
|
+ var lineCount = ZIMIdentifyQuadLSD(ref allLines, batch, ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize), minLength);
|
|
|
log += $"\r\n识别图片{batch}, 识别到的线段数量为: {lineCount}";
|
|
log += $"\r\n识别图片{batch}, 识别到的线段数量为: {lineCount}";
|
|
|
ScreenLocateMatList.Add(ScreenLocateMat);
|
|
ScreenLocateMatList.Add(ScreenLocateMat);
|
|
|
}
|
|
}
|
|
|
|
|
+ Texture2D ScreenLocateTexture = LocateTexTemp[0]; // for output
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // 过滤得到四边形的四条边
|
|
|
|
|
|
|
+ // 过滤得到四边形的四条边, ScreenLocateMatList[0]默认是屏幕的黑白色差
|
|
|
var quadLines = FilterLines(ScreenLocateMatList, allLines, GetAvgPoint(ScreenLocateMatList[0]),
|
|
var quadLines = FilterLines(ScreenLocateMatList, allLines, GetAvgPoint(ScreenLocateMatList[0]),
|
|
|
out Line[] oldLines, out List<Line> possibleLines,
|
|
out Line[] oldLines, out List<Line> possibleLines,
|
|
|
Screen, conSize, conSize, minLength);
|
|
Screen, conSize, conSize, minLength);
|
|
@@ -767,7 +773,7 @@ namespace o0.Project
|
|
|
if (ScreenLocate.Main.SaveToggle.isOn && ScreenLocate.Main.DebugOnZIMDemo)
|
|
if (ScreenLocate.Main.SaveToggle.isOn && ScreenLocate.Main.DebugOnZIMDemo)
|
|
|
{
|
|
{
|
|
|
var FileDirectory = $"Debug_屏幕定位/";
|
|
var FileDirectory = $"Debug_屏幕定位/";
|
|
|
- SaveImages(FileDirectory, log, ScreenLocateTexture, allLinesTex, ScreenQuadTex);
|
|
|
|
|
|
|
+ SaveImages(FileDirectory, log, ScreenLocateTexture, allLinesTex, ChoosableLineTex, ScreenQuadTex);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//times.Add(watch.ElapsedMilliseconds);
|
|
//times.Add(watch.ElapsedMilliseconds);
|
|
@@ -790,6 +796,11 @@ namespace o0.Project
|
|
|
ScreenLocate.DebugTexture(4, ScreenLocateTexture.Merge(ScreenQuadTex));
|
|
ScreenLocate.DebugTexture(4, ScreenLocateTexture.Merge(ScreenQuadTex));
|
|
|
ScreenLocate.DebugTexture(5, ChoosableLineTex);
|
|
ScreenLocate.DebugTexture(5, ChoosableLineTex);
|
|
|
}
|
|
}
|
|
|
|
|
+ foreach (var i in LocateTexTemp)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (i != ScreenLocateTexture) // ScreenLocateTexture 由 ScreenLocate.DebugTexture 释放
|
|
|
|
|
+ GameObject.Destroy(i);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Vector GetAvgPoint(Matrix screenLocateMat)
|
|
Vector GetAvgPoint(Matrix screenLocateMat)
|
|
@@ -822,7 +833,7 @@ namespace o0.Project
|
|
|
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 = 100)
|
|
|
{
|
|
{
|
|
|
- var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 20, LineCaptureSize: new Vector(0, 5));
|
|
|
|
|
|
|
+ var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 50, LineCaptureSize: new Vector(10, 6));
|
|
|
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)));
|
|
@@ -856,7 +867,7 @@ namespace o0.Project
|
|
|
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]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- float e = (float)Math.Sqrt(Math.Max(1, line.Line.Length / minLength / 3)); // 长度系数,筛选时梯度更大、长度更长的线段更优
|
|
|
|
|
|
|
+ float e = (float)Math.Pow(Math.Ceiling(line.Line.Length / minLength), 0.2f); // 长度系数,筛选时梯度更大、长度更长的线段更优
|
|
|
float d = (3 - distanceRatio) / 2; // 距离系数,距离越近,系数越大
|
|
float d = (3 - distanceRatio) / 2; // 距离系数,距离越近,系数越大
|
|
|
return e * d * Math.Abs(lg.Mean());
|
|
return e * d * Math.Abs(lg.Mean());
|
|
|
}
|
|
}
|
|
@@ -875,7 +886,7 @@ namespace o0.Project
|
|
|
var calibration = ScreenLocate.Main.ReDoLocateCalibrationRatio * Size.y;
|
|
var calibration = ScreenLocate.Main.ReDoLocateCalibrationRatio * Size.y;
|
|
|
oldLines = screen.QuadInCamera.GetLines();
|
|
oldLines = screen.QuadInCamera.GetLines();
|
|
|
|
|
|
|
|
- var pedals = oldLines.Select((i) => o0Extension.PointPedal(i, avgPoint)).ToArray(); // 当前定位的垂足,下、右、上、左
|
|
|
|
|
|
|
+ var pedals = oldLines.Select((i) => o0Extension.PointPedal(i, avgPoint, out _)).ToArray(); // 当前定位的垂足,下、右、上、左
|
|
|
|
|
|
|
|
foreach (var i in allLines)
|
|
foreach (var i in allLines)
|
|
|
{
|
|
{
|
|
@@ -883,7 +894,7 @@ namespace o0.Project
|
|
|
int index = -1;
|
|
int index = -1;
|
|
|
foreach (var j in pedals.Index())
|
|
foreach (var j in pedals.Index())
|
|
|
{
|
|
{
|
|
|
- var d = (o0Extension.PointPedal(i.Line, avgPoint) - pedals[j]).Length;
|
|
|
|
|
|
|
+ var d = (o0Extension.PointPedal(i.Line, avgPoint, out _) - pedals[j]).Length;
|
|
|
if (d < minDistance)
|
|
if (d < minDistance)
|
|
|
{
|
|
{
|
|
|
minDistance = d;
|
|
minDistance = d;
|
|
@@ -893,8 +904,13 @@ namespace o0.Project
|
|
|
//Debug.Log(minDistance +", -----------"+ calibration);
|
|
//Debug.Log(minDistance +", -----------"+ calibration);
|
|
|
if (minDistance < calibration) // 垂足的距离足够近
|
|
if (minDistance < calibration) // 垂足的距离足够近
|
|
|
{
|
|
{
|
|
|
- quadLines[index].Add((estimateGradient(i, minDistance / calibration), i.Line));
|
|
|
|
|
- possibleLines.Add(i.Line);
|
|
|
|
|
|
|
+ // 另外满足,新的线段的中点,到旧线段的垂足,要在旧线段内
|
|
|
|
|
+ var middleToOldLine = o0Extension.PointPedal(oldLines[index], (i.Line.A + i.Line.B) / 2, out bool inLineSegment);
|
|
|
|
|
+ if (inLineSegment)
|
|
|
|
|
+ {
|
|
|
|
|
+ quadLines[index].Add((estimateGradient(i, minDistance / calibration), i.Line));
|
|
|
|
|
+ possibleLines.Add(i.Line);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -958,7 +974,7 @@ namespace o0.Project
|
|
|
return result.ToList();
|
|
return result.ToList();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void SaveImages(string FileDirectory, string log, Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ScreenQuadTex)
|
|
|
|
|
|
|
+ void SaveImages(string FileDirectory, string log, Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ChoosableLineTex, Texture2D ScreenQuadTex)
|
|
|
{
|
|
{
|
|
|
if (!Directory.Exists(FileDirectory))
|
|
if (!Directory.Exists(FileDirectory))
|
|
|
Directory.CreateDirectory(FileDirectory);
|
|
Directory.CreateDirectory(FileDirectory);
|
|
@@ -973,12 +989,21 @@ namespace o0.Project
|
|
|
var pngData2 = allLinesTex.EncodeToPNG();
|
|
var pngData2 = allLinesTex.EncodeToPNG();
|
|
|
if (pngData2 != null)
|
|
if (pngData2 != null)
|
|
|
File.WriteAllBytes($"{FileDirectory}{time}C全部识别线段.png", pngData2);
|
|
File.WriteAllBytes($"{FileDirectory}{time}C全部识别线段.png", pngData2);
|
|
|
- var pngData3 = ScreenQuadTex.EncodeToPNG();
|
|
|
|
|
|
|
+ var pngData3 = ChoosableLineTex.EncodeToPNG();
|
|
|
if (pngData3 != null)
|
|
if (pngData3 != null)
|
|
|
- File.WriteAllBytes($"{FileDirectory}{time}D识别结果.png", pngData3);
|
|
|
|
|
|
|
+ File.WriteAllBytes($"{FileDirectory}{time}D备选线段.png", pngData3);
|
|
|
|
|
+ var pngData4 = ScreenQuadTex.EncodeToPNG();
|
|
|
|
|
+ if (pngData4 != null)
|
|
|
|
|
+ File.WriteAllBytes($"{FileDirectory}{time}E识别结果.png", pngData4);
|
|
|
|
|
+
|
|
|
|
|
|
|
|
Debug.Log($"<color=aqua>({time}) 屏幕识别图片保存至:程序根目录/{FileDirectory}</color>");
|
|
Debug.Log($"<color=aqua>({time}) 屏幕识别图片保存至:程序根目录/{FileDirectory}</color>");
|
|
|
- log += $"\r\n屏幕原图保存{pngData != null}, \r\n黑白色差保存{pngData1 != null}, \r\n全部识别线段保存{pngData2 != null}, \r\n识别结果保存{pngData3 != null}, ";
|
|
|
|
|
|
|
+ log +=
|
|
|
|
|
+ $"\r\n屏幕原图保存{pngData != null}, " +
|
|
|
|
|
+ $"\r\n黑白色差保存{pngData1 != null}, " +
|
|
|
|
|
+ $"\r\n全部识别线段保存{pngData2 != null}, " +
|
|
|
|
|
+ $"\r\n备选线段保存{pngData3 != null}, " +
|
|
|
|
|
+ $"\r\n识别结果保存{pngData4 != null}, ";
|
|
|
File.WriteAllText($"{FileDirectory}{time}屏幕自动定位_日志.log", log);
|
|
File.WriteAllText($"{FileDirectory}{time}屏幕自动定位_日志.log", log);
|
|
|
}
|
|
}
|
|
|
|
|
|