o0IdentifyLineLSD.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using o0.Geometry;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using UnityEngine;
  8. using UnityEngine.UI;
  9. using o0.Geometry2D.Float;
  10. namespace o0.Project
  11. {
  12. public static partial class Extension
  13. {
  14. public static (Vector, float) lineSegGradient(Matrix mat, Matrix dir, float gradient, Vector start, Vector end, bool reverseXY)
  15. {
  16. int startX, endX;
  17. if (start.x < end.x)
  18. {
  19. startX = Mathf.RoundToInt(start.x) + 1;
  20. endX = Mathf.RoundToInt(end.x) + 1;
  21. }
  22. else
  23. {
  24. startX = Mathf.RoundToInt(start.x) - 1;
  25. endX = Mathf.RoundToInt(end.x) - 1;
  26. }
  27. if(startX == endX)
  28. return (new Vector(start.x, start.y), 0);
  29. var xDiff = end.x - start.x;
  30. var xToYRate = (float)(end.y - start.y) / xDiff;
  31. Func<float, float> xToYFunc = (x) => (x - start.x) * xToYRate + start.y;
  32. var B1 = Mathf.RoundToInt(start.x);
  33. var B1V = mat[B1, Mathf.RoundToInt(start.y)];
  34. var Sum1 = B1V;
  35. foreach (var x in startX.Range(endX))
  36. {
  37. var y = xToYFunc(x);
  38. var y1 = Mathf.FloorToInt(y);
  39. var y2 = Mathf.CeilToInt(y);
  40. var y0 = y1 - 1;
  41. var y3 = y2 + 1;
  42. int C0I, C3I;
  43. int C1I, C2I;
  44. if (reverseXY)
  45. {
  46. C0I = mat.Index(y0, x);
  47. C1I = mat.Index(y1, x);
  48. C2I = mat.Index(y2, x);
  49. C3I = mat.Index(y3, x);
  50. }
  51. else
  52. {
  53. C0I = mat.Index(x, y0);
  54. C1I = mat.Index(x, y1);
  55. C2I = mat.Index(x, y2);
  56. C3I = mat.Index(x, y3);
  57. }
  58. var C0A = dir.Element[C0I];
  59. var C1A = dir.Element[C1I];
  60. var C2A = dir.Element[C2I];
  61. var C3A = dir.Element[C3I];
  62. //var CV = (y2 - y) * mat.Element[C1I] + (y - y1) * mat.Element[C2I];
  63. var CV = o0.Max(mat.Element[C0I], mat.Element[C1I], mat.Element[C2I], mat.Element[C3I]);
  64. //var avaAngle2 = 22.5;
  65. var avaAngle = 90;
  66. var halfAvaAngle = avaAngle/2;
  67. //var avaAngle2 = 33.75;
  68. if (!(MathF.Abs(C0A - gradient) <= halfAvaAngle || MathF.Abs(C0A - 360 - gradient) <= halfAvaAngle || MathF.Abs(C0A + 360 - gradient) <= halfAvaAngle
  69. || MathF.Abs(C1A - gradient) <= halfAvaAngle || MathF.Abs(C1A - 360 - gradient) <= halfAvaAngle || MathF.Abs(C1A + 360 - gradient) <= halfAvaAngle
  70. || MathF.Abs(C2A - gradient) <= halfAvaAngle || MathF.Abs(C2A - 360 - gradient) <= halfAvaAngle || MathF.Abs(C2A + 360 - gradient) <= halfAvaAngle
  71. || MathF.Abs(C3A - gradient) <= halfAvaAngle || MathF.Abs(C3A - 360 - gradient) <= halfAvaAngle || MathF.Abs(C3A + 360 - gradient) <= halfAvaAngle))
  72. {
  73. break;
  74. }
  75. B1 = x;
  76. Sum1 += CV;
  77. }
  78. return (new Vector(B1, xToYFunc(B1)), Sum1);
  79. }
  80. public static (Line, float) lineSegGradient(Matrix mat, Matrix dir, float gradient, Vector start)
  81. {
  82. var lineDir = (gradient + 90) % 180;//需要检测的线的角度
  83. var line = mat.MaskLine(start, lineDir);
  84. var range = (6, 2);
  85. if (lineDir < 45 || lineDir > 135)
  86. {
  87. //var (p1, sum1) = lineSegGradient(mat, dir, gradient, start, line.A, false);
  88. //var (p2, sum2) = lineSegGradient(mat, dir, gradient, start, line.B, false);
  89. var (p1, sum1) = ZIMLineSegGradient(mat, dir, gradient, start, line.A, range, false);
  90. var (p2, sum2) = ZIMLineSegGradient(mat, dir, gradient, start, line.B, range, false);
  91. return (new Line(p1, p2), sum1 + sum2);
  92. }
  93. else
  94. {
  95. var startR = new Vector(start.y, start.x);
  96. //var (p1, sum1) = lineSegGradient(mat, dir, gradient, startR, new Vector(line.A.y, line.A.x), true);
  97. //var (p2, sum2) = lineSegGradient(mat, dir, gradient, startR, new Vector(line.B.y, line.B.x), true);
  98. var (p1, sum1) = ZIMLineSegGradient(mat, dir, gradient, startR, new Vector(line.A.y, line.A.x), range, true);
  99. var (p2, sum2) = ZIMLineSegGradient(mat, dir, gradient, startR, new Vector(line.B.y, line.B.x), range, true);
  100. return (new Line(new Vector(p1.y, p1.x), new Vector(p2.y, p2.x)), sum1 + sum2);
  101. }
  102. }/**/
  103. ///////////////////线 线梯度和 线梯度方向0-180/////////返回的线以梯度和最高值到最低值排列
  104. static public List<(Line, float, float)> IdentifyLineLSD(this Matrix mat, float minLength = 100)
  105. {
  106. var (edge, edgeDir) = mat.IdentifyEdge();
  107. return edge.IdentifyLineLSD(edgeDir, minLength);
  108. }
  109. ///////////////////线 线梯度和 线梯度方向0-180/////////返回的线以梯度和最高值到最低值排列
  110. static public List<(Line, float, float)> IdentifyLineLSD(this Matrix gradientValueMat, Matrix gradientDirMat, float minLength = 100,
  111. int maxReturnCount = int.MaxValue)
  112. {
  113. var matBuffer = gradientValueMat;
  114. //var (mat, gradientMat) = tex.IdentifyEdge();
  115. //var lineMinLength = 50;
  116. var avaAngle = 60;
  117. var halfAvaAngle = avaAngle / 2;
  118. var returnLines = new List<(Line, float, float)> ();
  119. // while (mat.Element[maxIndex] != default)
  120. int count = 0;
  121. /*
  122. var minIndex = matBuffer.Element.MinIndex(matBuffer.Width * matBuffer.Height / 2);
  123. foreach (var i in minIndex)
  124. matBuffer.Element[i] = 0;/**/
  125. var maxIndex = matBuffer.Element.MaxIndex();
  126. var maxPos = matBuffer.Position(maxIndex);
  127. var maxVector = new Vector(maxPos.Item1, maxPos.Item2);
  128. while (matBuffer.Element[maxIndex] != 0 && count <= maxReturnCount)
  129. {
  130. count++;
  131. var gradient = gradientDirMat.Element[maxIndex];//梯度
  132. var lines = new List<(Line, float, float, float)>(avaAngle);
  133. Parallel.For((int)Math.Floor(gradient - halfAvaAngle), (int)Math.Ceiling(gradient + halfAvaAngle) + 1, gradientI =>//需要检测的梯度
  134. {
  135. //var gradientF = (float)gradientI / scale;
  136. if (gradientI < 0)
  137. gradientI += 360;
  138. else if (gradientI > 360)
  139. gradientI -= 360;
  140. var dir = (gradientI + 90) % 180;//需要检测的线的角度
  141. //var (line, sum) = lineSegGradient(matBuffer, gradientDirMat, gradientF, maxVector);
  142. var (line, sum) = lineSegGradient(gradientValueMat, gradientDirMat, gradientI, maxVector);
  143. if (line.A != line.B)
  144. lock (matBuffer)
  145. {
  146. lines.Add((line, line.Length, sum, gradientI));
  147. //drawLineMap.DrawLine(line, sum);
  148. }
  149. });
  150. var (line , lineLength, sum, gradientI) = lines.Max((a, b) => a.Item3.CompareTo(b.Item3));
  151. if(lineLength != 0)
  152. {
  153. matBuffer.DrawLine(line, (x, y) => 0, Vector.One * minLength);
  154. }
  155. if (lineLength > minLength)
  156. returnLines.Add((line, sum, gradientI));
  157. else
  158. matBuffer.Element[maxIndex] = 0;
  159. maxIndex = matBuffer.Element.MaxIndex();
  160. maxPos = matBuffer.Position(maxIndex);
  161. maxVector = new Vector(maxPos.Item1, maxPos.Item2);
  162. }/**/
  163. returnLines.Sort((a, b) => b.Item2.CompareTo(a.Item2));
  164. return returnLines;
  165. /*
  166. var drawLineMap = new MatrixF2D(matBuffer.Width, matBuffer.Height);
  167. var returnMaxLines = returnLines.Sub(0,10);
  168. foreach (var (line, sum, gradient) in returnMaxLines)
  169. {
  170. drawLineMap.DrawLine(line, (x, y) => 1, new Vector(0, 10));
  171. //drawLineMap.DrawLine(line, (x, y) => sum / line.Length, new Vector(0, 10));
  172. Debug.Log(line);
  173. }
  174. Debug.Log(returnLines.Count);
  175. return drawLineMap;/**/
  176. }
  177. }
  178. }