Ejemplo n.º 1
0
        /// <summary>
        /// Detects, wrapps and crops out OMR sheet from flattened camera/scanner image.
        /// Flattened image is got by using method,  private Bitmap flatten(Bitmap bmp, int fillint, int contint);
        /// </summary>
        /// <param name="bitmap">Bitmap image to process</param>
        /// <param name="basicImage">Backup image in case extraction fails</param>
        /// <param name="minBlobWidHei">Pre-configured variable, to be queried from XML reader</param>
        /// <param name="fillint">Pre-configured int, to be queried from XML reader</param>
        /// <param name="contint">Pre-configured int, to be queried from XML reader</param>
        /// <param name="OMRSheets">Sheets XML File Address</param>
        /// <param name="tb">Textbox to give in'process details on</param>
        /// <param name="panel1">Panel to draw in-process changes on.</param>
        /// <param name="giveFB">True when In- Process Feedback is required.</param>
        /// <param name="sheet">Type of sheet from OMREnums</param>
        /// <returns>Cropped OMR sheet (if detected) from camera/scanner image.</returns>
        private Bitmap ExtractPaperFromFlattened(Bitmap bitmap, Bitmap basicImage, int minBlobWidHei, int fillint, int contint, string OMRSheets, ref TextBox tb, ref Panel panel1, bool giveFB, XML.OMREnums.OMRSheet sheet)
        {
            // lock image, Bitmap itself takes much time to be processed
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // step 2 - locating objects
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = minBlobWidHei; // both these variables have to be given when calling the
            blobCounter.MinWidth    = minBlobWidHei; // method, the can also be queried from the XML reader using OMREnums

            blobCounter.ProcessImage(bitmapData);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            bitmap.UnlockBits(bitmapData);

            Graphics g         = Graphics.FromImage(bitmap);
            Pen      yellowPen = new Pen(Color.Yellow, 2); // create pen in case image extraction failes and we need to preview the

            //blobs that were detected

            Rectangle[] rects  = blobCounter.GetObjectsRectangles();
            Blob[]      blobs2 = blobCounter.GetObjects(bitmap, false);

            //Detection of paper lies within the presence of crossmark printed on the corneres of printed sheet.
            // First, detect left edge.
            System.Drawing.Image compImg = System.Drawing.Image.FromFile("lc.jpg");
            // lc.jpg = Mirrored image sample as located on the corner of printed sheet
            UnmanagedImage compUMImg = UnmanagedImage.FromManagedImage((Bitmap)compImg);
            // this helps filtering out much smaller and much larger blobs depending upon the size of image.
            // can be queried from XML Reader
            double minbr = XML.OMRSheetReader.getProcessVariableD(OMRSheets, sheet, XML.OMREnums.OMRImageProcessVariables.MinBlobRatio);
            double maxbr = XML.OMRSheetReader.getProcessVariableD(OMRSheets, sheet, XML.OMREnums.OMRImageProcessVariables.MaxBlobRatio);

            List <IntPoint> quad = new List <IntPoint>(); // Store sheet corner locations (if anyone is detected )

            if (giveFB)
            {
                showTimeStamp("Left edge detection started.", ref tb);
            }
            try
            {
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > minbr &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < maxbr &&
                        blob.Rectangle.X < (bitmap.Width) / 4)     // filters oout very small or very larg blobs
                    {
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > .6) // filters out blobs having insanely wrong aspect ratio
                        {
                            compUMImg = UnmanagedImage.FromManagedImage(ImageUtilities.ResizeImage(compImg, blob.Rectangle.Width, blob.Rectangle.Height));
                            if (isSame(blob.Image, compUMImg))
                            {
                                g.DrawRectangle(yellowPen, blob.Rectangle);
                                quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                            }
                        }
                    }
                }
            }
            catch (ArgumentException) { MessageBox.Show("No Blobs"); }
            if (giveFB)
            {
                showTimeStamp("Left edge detection finished.", ref tb);
            }
            try
            { // Sort out the list in right sequence, UpperLeft,LowerLeft,LowerRight,upperRight
                if (quad[0].Y > quad[1].Y)
                {
                    IntPoint tp = quad[0];
                    quad[0] = quad[1];
                    quad[1] = tp;
                }
            }
            catch
            {
            }
            compImg   = System.Drawing.Image.FromFile("rc.jpg");
            compUMImg = UnmanagedImage.FromManagedImage((Bitmap)compImg);
            if (giveFB)
            {
                showTimeStamp("Right edge detection started.", ref tb);         // jusst like left edge detection
            }
            try
            {
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > minbr &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < maxbr &&
                        blob.Rectangle.X > (bitmap.Width * 3) / 4)
                    {
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > .6)
                        {
                            compUMImg = UnmanagedImage.FromManagedImage(ImageUtilities.ResizeImage(compImg, blob.Rectangle.Width, blob.Rectangle.Height));
                            if (isSame(blob.Image, compUMImg))
                            {
                                g.DrawRectangle(yellowPen, blob.Rectangle);
                                quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                            }
                        }
                    }
                }
            }
            catch (ArgumentException) { MessageBox.Show("No Blobs"); }
            if (giveFB)
            {
                showTimeStamp("Right edge detection finished.", ref tb);
            }
            try
            {
                if (quad[2].Y < quad[3].Y)
                {
                    IntPoint tp = quad[2];
                    quad[2] = quad[3];
                    quad[3] = tp;
                }
            }
            catch
            {
            }

            yellowPen.Dispose();
            g.Dispose();
            //Again, filter out if wrong blobs pretended to our blobs.
            if (quad.Count == 4)
            {
                if (((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) < .75 ||
                    ((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) > 1.25)
                {
                    quad.Clear(); // clear if, both edges have insanely wrong lengths
                }
                else if (quad[0].X > bitmap.Width / 2 || quad[1].X > bitmap.Width / 2 || quad[2].X < bitmap.Width / 2 || quad[3].X < bitmap.Width / 2)
                {
                    quad.Clear(); // clear if, sides appear to be "wrong sided"
                }
            }
            if (quad.Count != 4)   // sheet not detected, reccurrsive call.
            {
                if (contint <= 60) //try altering the contrast correction on both sides of numberline
                {
                    if (contint >= 0)
                    {
                        contint += 5;
                        contint *= -1;
                        return(ExtractOMRSheet(basicImage, fillint, contint, OMRSheets, ref panel1, ref tb, giveFB, sheet));
                    }
                    else
                    {
                        contint *= -1;
                        contint += 10;
                        return(ExtractOMRSheet(basicImage, fillint, contint, OMRSheets, ref panel1, ref tb, giveFB, sheet));
                    }
                }
                else // contrast correction yeilded no result
                {
                    MessageBox.Show("Extraction Failed.");
                    return(basicImage);
                }
            }
            else // sheet found
            {
                IntPoint tp2 = quad[3];
                quad[3] = quad[1];
                quad[1] = tp2;
                //sort the edges for wrap operation
                QuadrilateralTransformation wrap = new QuadrilateralTransformation(quad);
                wrap.UseInterpolation = false; //perspective wrap only, no binary.
                Rectangle sr = XML.OMRSheetReader.GetSheetPropertyLocation(OMRSheets, sheet, XML.OMREnums.OMRProperty.SheetSize);
                wrap.AutomaticSizeCalculaton = false;
                wrap.NewWidth  = sr.Width;
                wrap.NewHeight = sr.Height;
                wrap.Apply(basicImage).Save("LastImg.jpg", ImageFormat.Jpeg); // creat file backup for future use.
                return(wrap.Apply(basicImage));                               // wrap
            }
        }
        public Bitmap ExtractPaperFromFlattened(Bitmap bitmap, Bitmap basicImage, int minBlobWidHei, int fillint, int contint)
        {
            // lock image, Bitmap itself takes much time to be processed
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);
            // step 2 - locating objects
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = minBlobWidHei; // both these variables have to be given when calling the
            blobCounter.MinWidth    = minBlobWidHei; // method, the can also be queried from the XML reader using OMREnums
            blobCounter.ProcessImage(bitmapData);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            bitmap.UnlockBits(bitmapData);
            Graphics g = Graphics.FromImage(bitmap);

//            Pen yellowPen = new Pen(Color.Yellow, 2);   // create pen in case image extraction failes and we need to preview the
            //blobs that were detected
            Rectangle[] rects  = blobCounter.GetObjectsRectangles();
            Blob[]      blobs2 = blobCounter.GetObjects(bitmap, false);
            //Detection of paper lies within the presence of crossmark printed on the corneres of printed sheet.
            // First, detect left edge.
            // lc.jpg = Mirrored image sample as located on the corner of printed sheet
            // this helps filtering out much smaller and much larger blobs depending upon the size of image.
            // can be queried from XML Reader
            List <IntPoint> quad = new List <IntPoint>(); // Store sheet corner locations (if anyone is detected )

            if (blobs2.GetLength(0) < 4 && contint == 0)
            {
                lExtractResult = ExtractResults.FAILED;
                return(basicImage);
            }
            try
            {
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > minbr &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < maxbr &&
                        blob.Rectangle.X < (bitmap.Width) / 4)     // filters oout very small or very larg blobs
                    {
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > .6) // filters out blobs having insanely wrong aspect ratio
                        {
                            cb1 = UnmanagedImage.FromManagedImage(ImageUtilities.ResizeImage(iMarkLeft, blob.Rectangle.Width, blob.Rectangle.Height));
                            if (isSame(blob.Image, cb1))
                            {
                                quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                            }
                        }
                    }
                }
            }
            catch (ArgumentException) { lExtractResult = ExtractResults.NOBLOB; }
            try
            { // Sort out the list in right sequence, UpperLeft,LowerLeft,LowerRight,upperRight
                if (quad[0].Y > quad[1].Y)
                {
                    IntPoint tp = quad[0];
                    quad[0] = quad[1];
                    quad[1] = tp;
                }
            }
            catch
            {
            }
            try
            {
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > minbr &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < maxbr &&
                        blob.Rectangle.X > (bitmap.Width * 3) / 4)
                    {
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > .6)
                        {
                            cb2 = UnmanagedImage.FromManagedImage(ImageUtilities.ResizeImage(iMarkRight, blob.Rectangle.Width, blob.Rectangle.Height));
                            if (isSame(blob.Image, cb2))
                            {
                                quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                            }
                        }
                    }
                }
            }
            catch (ArgumentException) { lExtractResult = ExtractResults.NOBLOB; }
            try
            {
                if (quad[2].Y < quad[3].Y)
                {
                    IntPoint tp = quad[2];
                    quad[2] = quad[3];
                    quad[3] = tp;
                }
            }
            catch
            {
            }
            g.Dispose();
            //Again, filter out if wrong blobs pretended to our blobs.
            if (quad.Count == 4)
            {
                if (((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) < .75 ||
                    ((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) > 1.25)
                {
                    quad.Clear(); // clear if, both edges have insanely wrong lengths
                }
                else if (quad[0].X > bitmap.Width / 2 || quad[1].X > bitmap.Width / 2 || quad[2].X < bitmap.Width / 2 || quad[3].X < bitmap.Width / 2)
                {
                    quad.Clear(); // clear if, sides appear to be "wrong sided"
                }
            }
            if (quad.Count != 4)   // sheet not detected, reccurrsive call.
            {
                if (contint <= 60) //try altering the contrast correction on both sides of numberline
                {
                    if (contint >= 0)
                    {
                        contint += 5;
                        contint *= -1;
                        return(ExtractOMRSheet(basicImage, fillint, contint));
                    }
                    else
                    {
                        contint *= -1;
                        contint += 10;
                        return(ExtractOMRSheet(basicImage, fillint, contint));
                    }
                }
                else // contrast correction yeilded no result
                {
                    lExtractResult = ExtractResults.FAILED;
                    return(basicImage);
                }
            }
            else // sheet found
            {
                IntPoint tp2 = quad[3];
                quad[3] = quad[1];
                quad[1] = tp2;

                if (!CheckSheetAR(quad))
                {
                    lExtractResult = ExtractResults.INVALIDAR;
                    return(basicImage);
                }

                //sort the edges for wrap operation
                QuadrilateralTransformation wrap = new QuadrilateralTransformation(quad);
                wrap.UseInterpolation        = false; //perspective wrap only, no binary.
                wrap.AutomaticSizeCalculaton = false;
                wrap.NewWidth  = tSheetSize.Width;
                wrap.NewHeight = tSheetSize.Height;
                lExtractResult = ExtractResults.OK;
                //wrap.Apply(basicImage);//.Save("LastImg.jpg", ImageFormat.Jpeg); // creat file backup for future use.
                return(wrap.Apply(basicImage)); // wrap
            }
        }