|
|
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|
|
using System.IO;
|
|
|
using System.Threading.Tasks;
|
|
|
using UnityEngine;
|
|
|
+using UnityStandardAssets.ImageEffects;
|
|
|
using ZIM;
|
|
|
using ZIM.Unity;
|
|
|
|
|
|
@@ -114,19 +115,12 @@ namespace o0.Project
|
|
|
|
|
|
void DebugImage(Texture2D image)
|
|
|
{
|
|
|
- QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex, 5, image);
|
|
|
- ScreenLocate.DebugTexture(1, LocateTex);
|
|
|
- ScreenLocate.DebugTexture(2, DrawLineTex);
|
|
|
-
|
|
|
+ QuadrilateralFit(out Texture2D LocateLightedRedTex,out Texture2D ChoosableLineTex, out Texture2D ScreenQuadTex, 5, image);
|
|
|
+ ScreenLocate.DebugTexture(1, LocateLightedRedTex);
|
|
|
+ ScreenLocate.DebugTexture(2, ScreenQuadTex);
|
|
|
// 融合线段和原图
|
|
|
- var pixel0 = image.GetPixels();
|
|
|
- var pixel1 = DrawLineTex.GetPixels();
|
|
|
- for (int i = 0; i < pixel0.Length; i++)
|
|
|
- pixel0[i] += pixel1[i];
|
|
|
- var texAdd = new Texture2D(image.width, image.height);
|
|
|
- texAdd.SetPixels(pixel0);
|
|
|
- texAdd.Apply();
|
|
|
- ScreenLocate.DebugTexture(3, texAdd);
|
|
|
+ ScreenLocate.DebugTexture(3, image.Merge(ScreenQuadTex));
|
|
|
+ ScreenLocate.DebugTexture(4, ChoosableLineTex);
|
|
|
|
|
|
//var watch = new System.Diagnostics.Stopwatch();
|
|
|
//watch.Start();
|
|
|
@@ -141,13 +135,13 @@ namespace o0.Project
|
|
|
new QuadrilateralInCamera(quad, image.Size().o0Vector()));
|
|
|
|
|
|
// 透视变换
|
|
|
- var srcWidth = LocateTex.width;
|
|
|
+ var srcWidth = LocateLightedRedTex.width;
|
|
|
var transformWidth = (int)((quad.B.x - quad.A.x + quad.D.x - quad.C.x) / 2);
|
|
|
var transformHeight = (int)((quad.C.y - quad.A.y + quad.D.y - quad.B.y) / 2);
|
|
|
var transformTex = new Texture2D(transformWidth, transformHeight);
|
|
|
var pt = new ZIMPerspectiveTransform(new OrdinalQuadrilateral(new Vector(0, 0), new Vector(transformWidth, 0), new Vector(0, transformHeight), new Vector(transformWidth, transformHeight)), quad);
|
|
|
var dstPixel = new UnityEngine.Color[transformWidth * transformHeight];
|
|
|
- var srcPixel = LocateTex.GetPixels();
|
|
|
+ var srcPixel = LocateLightedRedTex.GetPixels();
|
|
|
Parallel.For(0, transformWidth, (x) =>
|
|
|
{
|
|
|
for (int y = 0; y < transformHeight; y++)
|
|
|
@@ -266,26 +260,29 @@ namespace o0.Project
|
|
|
}
|
|
|
else if (locateIndex >= 4 && locateIndex < locateArea.Count - 1)
|
|
|
{
|
|
|
- QuadrilateralFit(out _, out _);
|
|
|
+ QuadrilateralFit(out _, out _, out _);
|
|
|
ScreenWhiteTexture = null;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex);
|
|
|
+ QuadrilateralFit(out Texture2D LocateLightedRedTex,out Texture2D ChoosableLineTex, out Texture2D ScreenQuadTex);
|
|
|
if (ScreenLocate.Main.DebugOnEditorWin)
|
|
|
{
|
|
|
- ScreenLocate.DebugTexture(1, LocateTex);
|
|
|
- ScreenLocate.DebugTexture(2, DrawLineTex);
|
|
|
+ ScreenLocate.DebugTexture(1, LocateLightedRedTex);
|
|
|
+ ScreenLocate.DebugTexture(2, ScreenQuadTex);
|
|
|
+ // 融合线段和原图
|
|
|
+ ScreenLocate.DebugTexture(3, LocateLightedRedTex.Merge(ScreenQuadTex));
|
|
|
+ ScreenLocate.DebugTexture(4, ChoosableLineTex);
|
|
|
}
|
|
|
|
|
|
if (quadTemp.Count != LocateAreaData[0].Length)
|
|
|
{
|
|
|
- Debug.Log($"拟合四边形失败, quadTemp.Count: {quadTemp.Count}");
|
|
|
+ Debug.Log($"<color=#FFA07A>[ScreenIdentification] 拟合四边形失败, quadTemp.Count: {quadTemp.Count}</color>");
|
|
|
}
|
|
|
else if (quadTemp.Count == 1)
|
|
|
{
|
|
|
Screen.QuadInCamera = new QuadrilateralInCamera(quadTemp[0], new Vector(Size.x, Size.y));
|
|
|
- //Debug.Log($"拟合四边形成功, quadTemp.Count: {quadTemp.Count}");
|
|
|
+ Debug.Log($"<color=#ADD8E6>[ScreenIdentification] 拟合成功,Quad: {Screen.QuadInCamera.QuadString}</color>");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -324,7 +321,7 @@ namespace o0.Project
|
|
|
}
|
|
|
}
|
|
|
Screen.QuadInCamera = new QuadrilateralInCamera(predicts, new Vector(Size.x, Size.y));
|
|
|
- Debug.Log($"[ScreenIdentification拟合结果] RSquared: {rs}, Quad: {Screen.QuadInCamera.QuadString}");
|
|
|
+ Debug.Log($"<color=#ADD8E6>[ScreenIdentification] 拟合成功,RSquared: {rs}, Quad: {Screen.QuadInCamera.QuadString}</color>");
|
|
|
//if (rs < 0.8) Screen.Quad = null;
|
|
|
}
|
|
|
|
|
|
@@ -602,9 +599,8 @@ namespace o0.Project
|
|
|
return sum;
|
|
|
}
|
|
|
|
|
|
- void QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex, float lineWidth = 10, Texture2D debugImage = null)
|
|
|
+ void QuadrilateralFit(out Texture2D LocateLightedRedTex,out Texture2D ChoosableLineTex, out Texture2D ScreenQuadTex, float lineWidth = 10, Texture2D debugImage = null)
|
|
|
{
|
|
|
- QuadrilateralInCamera screen = null;
|
|
|
UnityEngine.Color[] differPixel = new UnityEngine.Color[Size.x * Size.y];
|
|
|
|
|
|
//读取数据
|
|
|
@@ -634,7 +630,7 @@ namespace o0.Project
|
|
|
var ScreenLocateTexG = ScreenLocateTexLighted.ToRGB(ColorChannel.Green);
|
|
|
var ScreenLocateTexB = ScreenLocateTexLighted.ToRGB(ColorChannel.Blue);
|
|
|
|
|
|
- LocateTex = ScreenLocateTexR;
|
|
|
+ LocateLightedRedTex = ScreenLocateTexR;
|
|
|
//ScreenLocate.DebugTexture(2, ScreenLocateTexR);
|
|
|
//ScreenLocate.DebugTexture(4, ScreenLocateTexG);
|
|
|
//ScreenLocate.DebugTexture(5, ScreenLocateTexB);
|
|
|
@@ -650,77 +646,80 @@ namespace o0.Project
|
|
|
//var ScreenLocateTexLightedMat = texture.Too0Mat();
|
|
|
|
|
|
//var (edge, edgeDir) = ScreenLocateTexLightedMat.IdentifyEdge();
|
|
|
- int conSize = 15;
|
|
|
+ int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1;
|
|
|
+ Debug.Log($"[ScreenIdentification] Size: ({Size.x},{Size.y}), 卷积核Size: " + conSize);
|
|
|
var (edge, edgeDir) = ScreenLocateTexLightedMat.zimIdentifyEdgeGradientAny(conSize);
|
|
|
- ScreenLocate.DebugTexture(5, edgeDir.ToTex());
|
|
|
- ScreenLocate.DebugTexture(4, edge.ToTex());
|
|
|
|
|
|
- var drawLineMap = new Matrix(ScreenLocateTexLightedMat.Size, Tiling: true);
|
|
|
- var minLength = locateIndex == -1 ? 50 : 50 * areaPercent;
|
|
|
- var quadLines = ScreenLocateTexLightedMat.ZIMIdentifyQuadLSD(edge, edgeDir, out List<Line> lightLines, conSize, minLength);
|
|
|
+ var minLength = locateIndex == -1 ? 25 : 25 * areaPercent;
|
|
|
+ var quadLines = ScreenLocateTexLightedMat.ZIMIdentifyQuadLSD(edge, edgeDir, out Line[] oldLines, out List<Line> lightLines, Screen, conSize, conSize, minLength);
|
|
|
|
|
|
- int lineCount = 0;
|
|
|
- // LSD计算得到的矩阵尺寸较小(因为卷积),这里必须进行位移
|
|
|
- var offset = new Vector((conSize - 1) / 2, (conSize - 1) / 2);
|
|
|
- for (int i = 0; i < quadLines.Count; i++)
|
|
|
+ // 将识别到的边画出来,并判断能否拼成屏幕,能拼成则设置ScreenMap
|
|
|
+ // 线段顺序: 下、右、上、左
|
|
|
+ List<Line> LineIdentified = new List<Line>();
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
{
|
|
|
if (quadLines[i] != null)
|
|
|
- {
|
|
|
- quadLines[i] += offset;
|
|
|
- drawLineMap.DrawLine(quadLines[i], (x, y) => 1, new Geometry2D.Float.Vector(0, lineWidth));
|
|
|
- lineCount++;
|
|
|
- }
|
|
|
+ LineIdentified.Add(quadLines[i]);
|
|
|
+ else if (oldLines != null)
|
|
|
+ LineIdentified.Add(oldLines[i]);
|
|
|
}
|
|
|
- //foreach (var l in lightLines)
|
|
|
- //{
|
|
|
- // if (l != null)
|
|
|
- // {
|
|
|
- // if (quadLines.Contains(l))
|
|
|
- // {
|
|
|
- // drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
|
|
|
- // lineCount++;
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 2));
|
|
|
- // }
|
|
|
- // }
|
|
|
- //}
|
|
|
- if (lineCount == 4)
|
|
|
+
|
|
|
+ var drawScreenMap = new Matrix(ScreenLocateTexLightedMat.Size, Tiling: true);
|
|
|
+ foreach (var l in LineIdentified)
|
|
|
+ drawScreenMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, lineWidth));
|
|
|
+ ScreenQuadTex = drawScreenMap.ToTex(); // out ScreenQuadTex
|
|
|
+
|
|
|
+ QuadrilateralInCamera screenQuad = null;
|
|
|
+ if (LineIdentified.Count == 4)
|
|
|
{
|
|
|
- var a = quadLines[0].Intersect(quadLines[3], false).Value;
|
|
|
- var b = quadLines[0].Intersect(quadLines[1], false).Value;
|
|
|
- var c = quadLines[2].Intersect(quadLines[3], false).Value;
|
|
|
- var d = quadLines[1].Intersect(quadLines[2], false).Value;
|
|
|
- screen = new QuadrilateralInCamera(a, b, c, d, new Vector(Size.x, Size.y));
|
|
|
- if (!screen.IsQuadComplete())
|
|
|
- screen = null;
|
|
|
+ var a = LineIdentified[0].Intersect(LineIdentified[3], false).Value;
|
|
|
+ var b = LineIdentified[0].Intersect(LineIdentified[1], false).Value;
|
|
|
+ var c = LineIdentified[2].Intersect(LineIdentified[3], false).Value;
|
|
|
+ var d = LineIdentified[1].Intersect(LineIdentified[2], false).Value;
|
|
|
+ screenQuad = new QuadrilateralInCamera(a, b, c, d, new Vector(Size.x, Size.y));
|
|
|
+ if (!screenQuad.IsQuadComplete())
|
|
|
+ screenQuad = null;
|
|
|
+ }
|
|
|
+ if (screenQuad == null && Screen.QuadInCamera != null) // 如果可能,回退到上一个screen
|
|
|
+ {
|
|
|
+ Debug.Log("<color=#ADD8E6>[ScreenIdentification] 本次识别失败,回退到上次的识别结果</color>");
|
|
|
+ quadTemp.Add(Screen.QuadInCamera.Quad);
|
|
|
+ }
|
|
|
+ else if (screenQuad != null)
|
|
|
+ {
|
|
|
+ Debug.Log("<color=#ADD8E6>[ScreenIdentification] 识别到四边形</color>");
|
|
|
+ quadTemp.Add(screenQuad.Quad);
|
|
|
}
|
|
|
- if (screen != null)
|
|
|
- quadTemp.Add(screen.Quad);
|
|
|
-
|
|
|
- //var lines = edge.IdentifyLineLSD(edgeDir, 100);
|
|
|
- ////var lines = ScreenLocateTexLightedMat.IdentifyLineLSD();
|
|
|
|
|
|
- //var drawLineMap = new MatrixF2D(edge..Size.x, edge.Size.y);
|
|
|
- //var returnMaxLines = lines.Sub(0, 10);
|
|
|
- //foreach (var (line, sum, gradient) in returnMaxLines)
|
|
|
- // drawLineMap.DrawLine(line, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
|
|
|
+ // 还需要输出一张识别结果图,包含干扰线段
|
|
|
+ var LSDLineMap = new Matrix(ScreenLocateTexLightedMat.Size, Tiling: true);
|
|
|
+ foreach (var l in lightLines)
|
|
|
+ {
|
|
|
+ if (l != null && !quadLines.Contains(l))
|
|
|
+ LSDLineMap.DrawLine(l, (x, y) => 3, new Geometry2D.Float.Vector(0, 2), true); // 其他的备选线段
|
|
|
+ }
|
|
|
+ foreach (var l in quadLines)
|
|
|
+ {
|
|
|
+ if (l != null)
|
|
|
+ LSDLineMap.DrawLine(l, (x, y) => 2, new Geometry2D.Float.Vector(0, 4)); // 这次识别到的线段
|
|
|
+ }
|
|
|
+ if (oldLines != null)
|
|
|
+ {
|
|
|
+ foreach (var l in oldLines)
|
|
|
+ LSDLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 2), true); // 旧的屏幕线段(例如上次手动识别的)
|
|
|
+ }
|
|
|
+ ChoosableLineTex = LSDLineMap.ToTexRGBA(floatValueToColor);
|
|
|
|
|
|
- DrawLineTex = drawLineMap.ToTex();
|
|
|
- //ScreenLocate.DebugTexture(3, drawLineMap.ToTex());
|
|
|
- //var FileSavePath = Application.persistentDataPath + "/ScreenLocateTexture.bin";
|
|
|
- bool Save = ScreenLocate.Main.SaveToggle.isOn;
|
|
|
- string time;
|
|
|
- if (Save)
|
|
|
+ // 是否将图片保存到本地
|
|
|
+ if (ScreenLocate.Main.SaveToggle.isOn)
|
|
|
{
|
|
|
- time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
|
|
+ var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
|
|
var FileSavePath = $"{time}屏幕定位数据.bin";
|
|
|
FileSavePath.FileWriteByte(ScreenWhiteTexture);
|
|
|
|
|
|
var bytes = ScreenLocateTexLighted.EncodeToPNG();
|
|
|
File.WriteAllBytes($"{time}屏幕.png", bytes);
|
|
|
- bytes = DrawLineTex.EncodeToPNG();
|
|
|
+ bytes = ScreenQuadTex.EncodeToPNG();
|
|
|
File.WriteAllBytes($"{time}屏幕边框识别.png", bytes);
|
|
|
Debug.Log("ScreenLocateTexture Saved To: " + FileSavePath);
|
|
|
}
|
|
|
@@ -728,14 +727,7 @@ namespace o0.Project
|
|
|
//times.Add(watch.ElapsedMilliseconds);
|
|
|
//UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));
|
|
|
|
|
|
- //ScreenLocate.DebugTexture(5, edge.IdentifyLine(edgeDir).ToTex());
|
|
|
- //ScreenLocate.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientX().ToTex());
|
|
|
- //ScreenLocate.DebugTexture(5, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientY().ToTex());
|
|
|
-
|
|
|
- //var convolutionLighted2 = ScreenLocateTexLighted.Too0Mat().IdentifyEdgeVariance().ToTex();
|
|
|
-
|
|
|
- // opecncv处理
|
|
|
- // zim
|
|
|
+ // opecncv处理, zim
|
|
|
{
|
|
|
//var cvLines = edge.cvHoughLinesP();
|
|
|
//ScreenLocate.DebugTexture(5, cvLines);
|
|
|
@@ -747,5 +739,20 @@ namespace o0.Project
|
|
|
|
|
|
UnityEngine.Object.Destroy(ScreenLocateTex);
|
|
|
}
|
|
|
+
|
|
|
+ private UnityEngine.Color floatValueToColor(float i)
|
|
|
+ {
|
|
|
+ switch (i)
|
|
|
+ {
|
|
|
+ case 1:
|
|
|
+ return UnityEngine.Color.green;
|
|
|
+ case 2:
|
|
|
+ return UnityEngine.Color.red;
|
|
|
+ case 3:
|
|
|
+ return UnityEngine.Color.yellow;
|
|
|
+ default:
|
|
|
+ return UnityEngine.Color.black;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|