Example #1
0
        //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);
            }
        }
Example #2
0
        //共線或是相交
        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);
            }
        }