예제 #1
0
        /// <summary>
        /// Applies blob Processing on the image and extracts blobs corresponding to the bubbles and return them as a blob array.
        /// <param name="bitmap">Pre Processed Image</param>
        /// </summary>
        public static List <Blob> ExtractBubbleCorrespondingBlobs(Bitmap bitmap, int minblobwidth, int minblobheight)
        {
            Bitmap   bm = new Bitmap(bitmap.Size.Width, bitmap.Size.Height);
            Graphics g  = Graphics.FromImage(bm);

            g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
            Pen redpen = new Pen(Color.Red, 3);

            AForge.Math.Geometry.SimpleShapeChecker detectshape = new AForge.Math.Geometry.SimpleShapeChecker();

            // lock the image
            BitmapData bitmapdata = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // Finding Blobs in the Bitmap image
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = minblobheight;
            blobCounter.MinWidth    = minblobwidth;

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

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

            List <Blob> bubblesblobs = new List <Blob>();

            try
            {
                foreach (Blob blob in blob_objects)
                {
                    //detect circles through aspect ratio
                    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
                    {
                        List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
                        detectshape.MinAcceptableDistortion = 0.5f;   //0.5f;
                        detectshape.RelativeDistortionLimit = 0.079f; //0.057f;

                        AForge.Point center;
                        float        radius;

                        //detect circles only
                        if (detectshape.IsCircle(edgePoints, out center, out radius))
                        {
                            //detect filled bubbles only
                            if ((blob.Fullness > 0.60) && ((double)blob.Image.Width / (double)bitmap.Size.Width > 0.014))
                            {
                                //g.DrawEllipse(redpen,
                                //    (int)(center.X - radius),
                                //    (int)(center.Y - radius),
                                //    (int)(radius * 2),
                                //    (int)(radius * 2));
                                bubblesblobs.Add(blob);
                            }
                        }
                    }
                }
                return(bubblesblobs);
            }
            catch (ArgumentException) { MessageBox.Show("Bubble Detection Failed"); }
            return(null);
        }
예제 #2
0
        public static Bitmap ExtractPaperFromFlattened(Bitmap bitmap, Bitmap originalimage, int minblobwidth, int minblobheight, bool applyrotation)
        {
            Bitmap   bm = new Bitmap(bitmap.Size.Width, bitmap.Size.Height);
            Graphics g  = Graphics.FromImage(bm);

            g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
            Pen redpen = new Pen(Color.Red, 2);

            AForge.Math.Geometry.SimpleShapeChecker detectshape = new AForge.Math.Geometry.SimpleShapeChecker();

            if (applyrotation)
            {
                //rotate the image in case it is not properly oriented
                // lock the image
                BitmapData bitmapdata_rot = bitmap.LockBits(
                    new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    ImageLockMode.ReadWrite, bitmap.PixelFormat);

                BlobCounter blobCounter_rot = new BlobCounter();

                blobCounter_rot.FilterBlobs = true;
                blobCounter_rot.MinHeight   = minblobheight;
                blobCounter_rot.MinWidth    = minblobwidth;

                blobCounter_rot.ProcessImage(bitmapdata_rot);
                bitmap.UnlockBits(bitmapdata_rot);

                Blob[] blob_objects_rot = blobCounter_rot.GetObjects(bitmap, false);

                try
                {
                    foreach (Blob blob in blob_objects_rot)
                    {
                        List <IntPoint> edgePoints = blobCounter_rot.GetBlobsEdgePoints(blob);

                        //detect rotated paper based on left edge rectangular mark
                        List <IntPoint> cornerPoints;
                        if (detectshape.IsQuadrilateral(edgePoints, out cornerPoints))
                        {
                            if (detectshape.CheckPolygonSubType(cornerPoints) == AForge.Math.Geometry.PolygonSubType.Rectangle)
                            {
                                if ((blob.Fullness > 0.7) && (((double)blob.Image.Width / (double)bitmap.Size.Width > 0.025) && ((double)blob.Image.Width / (double)bitmap.Size.Width < 0.037)) && (((double)blob.Image.Height / (double)bitmap.Size.Height > 0.005) && ((double)blob.Image.Height / (double)bitmap.Size.Height < 0.013)))
                                {
                                    // A------p------B      Suppose these are the Coordinates of the Rectangle (image)
                                    // |  2   |  1   |      A,B,C,D are vertices and 1,2,3,4 are quadrants
                                    // s------O------q      p,q,r,s midpoints
                                    // |  3   |  4   |      O is the center of the rectangle
                                    // D------r------C      let the blob be denoted by BL

                                    System.Drawing.Point cent_O = new System.Drawing.Point(bitmap.Size.Width / 2, bitmap.Size.Height / 2);

                                    GraphicsUnit         units = GraphicsUnit.Point;
                                    System.Drawing.Point pnt_A = new System.Drawing.Point((int)bitmap.GetBounds(ref units).X, (int)bitmap.GetBounds(ref units).Y);
                                    System.Drawing.Point pnt_B = new System.Drawing.Point(bitmap.Size.Width, (int)bitmap.GetBounds(ref units).Y);
                                    System.Drawing.Point pnt_C = new System.Drawing.Point(bitmap.Size.Width, bitmap.Size.Height);
                                    System.Drawing.Point pnt_D = new System.Drawing.Point((int)bitmap.GetBounds(ref units).X, bitmap.Size.Height);

                                    System.Drawing.Point midpnt_P = new System.Drawing.Point((pnt_A.X + pnt_B.X) / 2, (pnt_A.Y + pnt_B.Y) / 2);
                                    System.Drawing.Point midpnt_Q = new System.Drawing.Point((pnt_B.X + pnt_C.X) / 2, (pnt_B.Y + pnt_C.Y) / 2);
                                    System.Drawing.Point midpnt_R = new System.Drawing.Point((pnt_C.X + pnt_D.X) / 2, (pnt_C.Y + pnt_D.Y) / 2);
                                    System.Drawing.Point midpnt_S = new System.Drawing.Point((pnt_A.X + pnt_D.X) / 2, (pnt_A.Y + pnt_D.Y) / 2);

                                    System.Drawing.Point blob_CENGRAV = new System.Drawing.Point((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y);

                                    if (ImageProcessor.IsPointInsideRegion(bitmap, pnt_A, midpnt_P, cent_O, midpnt_S, blob_CENGRAV))
                                    {
                                        //do nothing...image is properly oriented
                                        break; //terminate the loop
                                    }
                                    else if (ImageProcessor.IsPointInsideRegion(bitmap, midpnt_P, pnt_B, midpnt_Q, cent_O, blob_CENGRAV))
                                    {
                                        //blob is present in quadrant 1
                                        //rotate image by three CW
                                        bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                                        originalimage.RotateFlip(RotateFlipType.Rotate270FlipNone);
                                        break;
                                    }
                                    else if (ImageProcessor.IsPointInsideRegion(bitmap, cent_O, midpnt_Q, pnt_C, midpnt_R, blob_CENGRAV))
                                    {
                                        //blob is present in quadrant 4
                                        //rotate image by two CW
                                        bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                                        originalimage.RotateFlip(RotateFlipType.Rotate180FlipNone);
                                        break;
                                    }
                                    else if (ImageProcessor.IsPointInsideRegion(bitmap, cent_O, midpnt_R, pnt_D, midpnt_S, blob_CENGRAV))
                                    {
                                        //blob is present in quadrant 3
                                        //rotate image by one CW
                                        bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                                        originalimage.RotateFlip(RotateFlipType.Rotate90FlipNone);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (ArgumentException) { MessageBox.Show("Bilinear Rotational Transformation Failed"); }
            }
            //After applying rotational process, extract the blobs once again to find the circular edge markers

            // lock the image
            BitmapData bitmapdata = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // Finding Blobs in the Bitmap image
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = minblobheight;
            blobCounter.MinWidth    = minblobwidth;

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

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

            // Paper Detection happens through the detection of the edge-markers placed on all four
            // edges of the OMR sheet

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

            try
            {
                foreach (Blob blob in blob_objects)
                {
                    //detect edge circles
                    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
                    {
                        List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);

                        //detect circles only
                        if (detectshape.IsCircle(edgePoints))
                        {
                            //detect filled circles only
                            //the ratio of width(blob)/width(bitmap) should be in range of 0.031 - 0.042
                            if ((blob.Fullness > 0.7) && (((double)blob.Image.Width / (double)bitmap.Width) > 0.031) && (((double)blob.Image.Width / (double)bitmap.Width) < 0.042))
                            {
                                //g.DrawRectangle(redpen, blob.Rectangle);
                                quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                            }
                        }
                    }
                }

                // filter out if wrong blobs pretend to be our blobs.
                if (quad.Count == 4)
                {
                    if (!((quad[0].DistanceTo(quad[1]) / quad[0].DistanceTo(quad[2]) > 0.5) &&
                          (quad[0].DistanceTo(quad[1]) / quad[0].DistanceTo(quad[2]) < 1.5)))
                    {
                        quad.Clear();
                    }
                    else
                    {
                        //rearrange the edge coordinates, if not in proper manner
                        while ((quad[0].X > quad[1].X) || (quad[1].Y > quad[3].Y) || (quad[2].X > quad[3].X) || (quad[0].Y > quad[2].Y))
                        {
                            if (quad[0].X > quad[1].X)
                            {
                                IntPoint tmp = quad[0];
                                quad[0] = quad[1];
                                quad[1] = tmp;
                            }

                            if (quad[1].Y > quad[3].Y)
                            {
                                IntPoint tmp = quad[1];
                                quad[1] = quad[3];
                                quad[3] = tmp;
                            }

                            if (quad[2].X > quad[3].X)
                            {
                                IntPoint tmp = quad[3];
                                quad[3] = quad[2];
                                quad[2] = tmp;
                            }

                            if (quad[0].Y > quad[2].Y)
                            {
                                IntPoint tmp = quad[0];
                                quad[0] = quad[2];
                                quad[2] = tmp;
                            }
                        }
                    }
                }

                if (quad.Count != 4)
                {
                    //call recursively as the sheet is not detected properly
                    //todo: try altering the blob height and width, threshold etc, when program does not find edge markers
                }
                else
                {
                    //rearrange the edges coordinates

                    //  0----1
                    //  |    |
                    //  2----3

                    //interchange 2 and 3
                    IntPoint tp2 = quad[3];
                    quad[3] = quad[2];
                    quad[2] = tp2;

                    //sort the edges for wrap operation
                    QuadrilateralTransformation wrap = new QuadrilateralTransformation(quad, 2100, 2970);
                    wrap.UseInterpolation        = false;
                    wrap.AutomaticSizeCalculaton = true;
                    Bitmap wrappedoriginal = wrap.Apply(originalimage);
                    return(wrappedoriginal);
                }
            }
            catch (ArgumentException) { MessageBox.Show("No Blobs Found"); }
            return(null);
        }