//5.找尋直線 public static LinkedList <LineEquation> DetectHoughLine(Image <Gray, byte> source) { LinkedList <LineEquation> candidateLineEquations = new LinkedList <LineEquation>(); if (source != null) { //Hough transform for line detection LineSegment2D[][] lines = source.HoughLines( new Gray(125), //Canny algorithm low threshold new Gray(260), //Canny algorithm high threshold 1, //rho parameter Math.PI / 180.0, //theta parameter 100, //threshold 1, //min length for a line 20); //max allowed gap along the line foreach (var line in lines[0]) { //計算並取得線段的直線方程式 LineEquation eqation = LineEquation.GetLineEquation(line); candidateLineEquations.AddLast(eqation); } return(candidateLineEquations); } else { return(null); } }
//共線或是相交 public static bool CheckIntersectOrNot(LineEquation line1, LineEquation line2, out Point intersectP, ref LineSegment2D repaiedLine, Image <Bgr, byte> source) { intersectP = new Point(); //檢查共線(檢查向量 A,B,C三點,A->B 與B->C兩條向量會是比例關係 or A-B 與 A-C的斜率會依樣 or 向量叉積 A) //使用 x1(y2- y3) + x2(y3- y1) + x3(y1- y2) = 0 面積公式 http://math.tutorvista.com/geometry/collinear-points.html int x1 = line1.Line.P1.X; int y1 = line1.Line.P1.Y; int x2 = line1.Line.P2.X; int y2 = line1.Line.P2.Y; int x3 = line2.Line.P1.X; int y3 = line2.Line.P1.Y; int x4 = line2.Line.P2.X; int y4 = line2.Line.P2.Y; float v = (line1.A * line2.B) - line2.A * line1.B; //Console.WriteLine("line1 slope = " + line1.Slope + ", line 2 slope = " + line2.Slope); //Console.WriteLine("line1 P1 = " + line1.Line.P1 + ",line1 P2 = " + line1.Line.P2 + ", length = " + line1.Line.Length); //Console.WriteLine("line2 P1 = " + line2.Line.P1 + ",line2 P2 = " + line2.Line.P2 + ", length = " + line2.Line.Length); //不太可能會有共線,需要給一個Range //面積公式來看 1/2 * x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2) 如果小於1000可以是 //or 用A-B 與 A-C的斜率去看斜率誤差 約接近0表示共線高 //Console.WriteLine("面積公式1 = " + Math.Abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) + " y3 -y1 = " + Math.Abs(y3 - y1)); //Console.WriteLine("面積公式2 = " + Math.Abs(x1 * (y2 - y4) + x2 * (y4 - y1) + x4 * (y1 - y2)) + " y4 -y1 = " + Math.Abs(y4 - y1)); //float p1p2Slope = (y2 - y1) / (float)(x2 - x1); //float p1p3Slope = (y3 - y1) / (float)(x3 - x1); //Console.WriteLine("Slope p1 -> p2 = " +p1p2Slope+ ", Slope p1 -> p3 ="+ p1p3Slope + "差距值 = " + Math.Abs(Math.Abs(p1p2Slope) - Math.Abs(p1p3Slope))); //尋找兩端點 Point[] points = new Point[] { line1.Line.P1, line1.Line.P2, line2.Line.P1, line2.Line.P2 }; float area1 = Math.Abs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); float area2 = Math.Abs(x1 * (y2 - y4) + x2 * (y4 - y1) + x4 * (y1 - y2)); if (area1 <= 1000 && area2 <= 1000 && Math.Abs(y3 - y1) < 6 && Math.Abs(y4 - y1) < 6) // Math.Abs(y3 - y1) < 8 => y3 - y1表示距離 { //Console.WriteLine("共線" + "\n"); intersectP.X = -1; intersectP.Y = -1; repaiedLine = RepaiedHorizontalHoughLine(points); return(true); } else if (v != 0) { //代表兩條線段方程式不是平行,y3 - y1表示距離 //Console.Write("相交"); //Console.WriteLine("v = " + v); //兩條線相似 //Console.WriteLine("線段一原角度:" + line1.Angle + ",修正角度:" + line1.AdjustAngle + "\n線段原二角度:" + line2.Angle + ",修正角度" + line2.AdjustAngle); double angleDifference = Math.Abs(line1.AdjustAngle - line2.AdjustAngle); //Console.WriteLine("兩條線的角度差為:" + angleDifference); if (angleDifference < 15) { //Console.WriteLine("兩條線可能是可以銜接"); float delta_x = (line1.C * line2.B) - line2.C * line1.B; float delta_y = (line1.A * line2.C) - line2.A * line1.C; intersectP.X = Convert.ToInt32(delta_x / v); intersectP.Y = Convert.ToInt32(delta_y / v); if ((intersectP.X < 0 || intersectP.X > source.Width || intersectP.Y < 0 || intersectP.Y > source.Height)) { //Console.WriteLine("所以超出畫面"); intersectP.X = -1; intersectP.Y = -1; return(false); } else { //判斷角度有用原角度取絕對值(因為角度的方位比較特別) double line1_angle = Math.Abs(line1.Angle); double line2_angle = Math.Abs(line2.Angle); //接近平行線(角度都大於150),並且方向一致 if (line1_angle > 150 && line2_angle > 150 && line1.Direction == line2.Direction) { if (!CheckHorizontalIntersectionPoint(points, intersectP.X, intersectP.Y)) { return(false); } //Console.WriteLine("接近水平的線段,且交點有在兩線段內"); } else if (line1_angle <= 150 && line1_angle >= 120 && line2_angle <= 150 && line2_angle >= 120 && line1.Direction == line2.Direction) { //斜45度 if (!CheckVerticalIntersectionPoint(points, intersectP.X, intersectP.Y) && !CheckHorizontalIntersectionPoint(points, intersectP.X, intersectP.Y)) { return(false); } //Console.WriteLine("接近斜45度或135度的線段,且交點有在兩線段內"); } else if (line1_angle < 120 && line2_angle < 120 && line1.Direction == line2.Direction) //接近垂直 { if (!CheckVerticalIntersectionPoint(points, intersectP.X, intersectP.Y)) { return(false); } //Console.WriteLine("接近垂直的線段,且交點有在兩線段內"); } //Console.Write("\n"); repaiedLine = RepaiedHorizontalHoughLine(points); return(true); } } else { //Console.WriteLine("但是角度差異過大,研判不是\n"); intersectP.X = -1; intersectP.Y = -1; return(false); } //Console.WriteLine("intersect x = " + x + ",intersect y = " + y + "\n"); } else { intersectP.X = -1; intersectP.Y = -1; //Console.WriteLine("平行" + "\n"); return(false); } }