コード例 #1
0
        /// <summary>
        /// Detect the square in the image using contours
        /// </summary>
        /// <param name="img">Image</param>
        /// <param name="modifiedImg">Modified image to be return</param>
        /// <param name="storage">Memory storage</param>
        /// <returns></returns>
        public static CvPoint[] DetectSquares(IplImage img)
        {
            // Debug
            //System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            //stopWatch.Start();

            using (CvMemStorage storage = new CvMemStorage())
            {
                // create empty sequence that will contain points -
                // 4 points per square (the square's vertices)
                CvSeq<CvPoint> squares = new CvSeq<CvPoint>(SeqType.Zero, CvSeq.SizeOf, storage);

                using (IplImage timg = img.Clone())
                using (IplImage gray = new IplImage(timg.Size, BitDepth.U8, 1))
                using (IplImage dstCanny = new IplImage(timg.Size, BitDepth.U8, 1))
                {
                    // Get gray scale
                    timg.CvtColor(gray, ColorConversion.BgrToGray);

                    // Canny
                    Cv.Canny(gray, dstCanny, 70, 300);

                    // dilate canny output to remove potential
                    // holes between edge segments
                    Cv.Dilate(dstCanny, dstCanny, null, 2);

                    // find contours and store them all as a list
                    CvSeq<CvPoint> contours;
                    dstCanny.FindContours(storage, out contours);

                    // Debug
                    //Cv.ShowImage("Edge", dstCanny);
                    //if (contours != null) Console.WriteLine(contours.Count());

                    // Test each contour
                    while (contours != null)
                    {
                        // Debug
                        //if (stopWatch.ElapsedMilliseconds > 100)
                        //{
                        //    Console.WriteLine("ROI detection is taking too long and is skipped.");
                        //}

                        // approximate contour with accuracy proportional
                        // to the contour perimeter
                        CvSeq<CvPoint> result = Cv.ApproxPoly(contours, CvContour.SizeOf, storage, ApproxPolyMethod.DP, contours.ContourPerimeter() * 0.02, false);

                        // square contours should have 4 vertices after approximation
                        // relatively large area (to filter out noisy contours)
                        // and be convex.
                        // Note: absolute value of an area is used because
                        // area may be positive or negative - in accordance with the
                        // contour orientation
                        if (result.Total == 4 &&
                            Math.Abs(result.ContourArea(CvSlice.WholeSeq)) > 250 &&
                            result.CheckContourConvexity())
                        {
                            double s = 0;

                            for (int i = 0; i < 5; i++)
                            {
                                // find minimum Angle between joint
                                // edges (maximum of cosine)
                                if (i >= 2)
                                {
                                    double t = Math.Abs(Angle(result[i].Value, result[i - 2].Value, result[i - 1].Value));
                                    s = s > t ? s : t;
                                }
                            }

                            // if cosines of all angles are small
                            // (all angles are ~90 degree) then write quandrange
                            // vertices to resultant sequence
                            if (s < 0.3)
                            {
                                //Console.WriteLine("ROI found!");  // Debug
                                for (int i = 0; i < 4; i++)
                                {
                                    //Console.WriteLine(result[i]);
                                    squares.Push(result[i].Value);
                                }
                            }
                        }

                        // Take the next contour
                        contours = contours.HNext;
                    }
                }
                //stopWatch.Stop();
                //Console.WriteLine("ROI Detection : {0} ms", stopWatch.ElapsedMilliseconds); // Debug
                return squares.ToArray();
            }
        }