Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How find document on scanned image? OpenCV

May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example image description

How find document on scanned image? OpenCV

May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example example, i need crop this red rectangle from picture image description

How find document on scanned image? OpenCV

May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example, i need crop this red rectangle from picture image description ` static CvPoint[] FindSquare(IplImage img, CvMemStorage storage) { const int N = 15;//11

        CvSize sz = new CvSize(img.Width & -2, img.Height & -2);
        IplImage timg = img.Clone(); // make a copy of input image
        //Draw frame in begin of image for best square finding near edge of big image
        timg.DrawRect(0, 0, timg.Width, timg.Height, CvColor.Black, 2);
        IplImage gray = new IplImage(sz, BitDepth.U8, 1);
        IplImage pyr = new IplImage(sz.Width / 2, sz.Height / 2, BitDepth.U8, 3);
        // 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);
        // select the maximum ROI in the image
        // with the width and height divisible by 2
        timg.ROI = new CvRect(0, 0, sz.Width, sz.Height);

        // down-Scale and upscale the image to filter out the noise
        Cv.PyrDown(timg, pyr, CvFilter.Gaussian5x5);
        Cv.PyrUp(pyr, timg, CvFilter.Gaussian5x5);
        IplImage tgray = new IplImage(sz, BitDepth.U8, 1);

            // extract the c-th color plane
            timg.COI = 1;
            Cv.Copy(timg, tgray, null);

            // try several threshold levels
            for (int l = 1; l < N; l++)
            {
                // hack: use Canny instead of zero threshold level.
                // Canny helps to catch squares with gradient shading   
                if (l == 0)
                {
                    // apply Canny. Take the upper threshold from slider
                    // and set the lower to 0 (which forces edges merging) 
                    Cv.Canny(tgray, gray, 0, Thresh, ApertureSize.Size5);
                    // dilate canny output to remove potential
                    // holes between edge segments 
                    Cv.Dilate(gray, gray, null, 1);
                }
                else
                {
                    // apply threshold if l!=0:
                    //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0                        
                    Cv.Threshold(tgray, gray, (l + 1) * 255.0 / N, 255, ThresholdType.Binary);
                }

                // find contours and store them all as a list
                CvSeq<CvPoint> contours;
                Cv.FindContours(gray, storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxSimple, new CvPoint(0, 0));
                // test each contour
                while (contours != null)
                {
                    // 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)) > 1000 && 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)
                        {
                            for (int i = 0; i < 4; i++)
                            {
                                //My squares. Then sort counturs of squares by area
                                squares.Push(result[i].Value);                                 
                            }
                        }                           

                    }

                    // take the next contour
                    contours = contours.HNext;
                }
        }`