Exemplo 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
            }
        }
Exemplo n.º 2
0
        private Bitmap ExtractPaperFromFlattened(Bitmap bitmap, Bitmap basicImage, int minBlobWidHei, int fillint, int contint, string OMRSheets)
        {
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // lock image

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

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = minBlobWidHei;
            blobCounter.MinWidth    = minBlobWidHei;

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

            Graphics g         = Graphics.FromImage(bitmap);
            Pen      yellowPen = new Pen(Color.Yellow, 2); // circles
            Pen      redPen    = new Pen(Color.Red, 2);    // quadrilateral
            Pen      brownPen  = new Pen(Color.Brown, 2);  // quadrilateral with known sub-type
            Pen      greenPen  = new Pen(Color.Green, 2);  // known triangle
            Pen      bluePen   = new Pen(Color.Blue, 2);   // triangle

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


            System.Drawing.Image compImg   = System.Drawing.Image.FromFile("lc.jpg");
            UnmanagedImage       compUMImg = UnmanagedImage.FromManagedImage((Bitmap)compImg);

            List <IntPoint> quad = new List <IntPoint>();

            showTimeStamp("Left edge Dection Started");
            try
            {
                //g.DrawRectangles(yellowPen, rects);
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > 0.0001 &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < 0.005 &&
                        blob.Rectangle.X < (bitmap.Width) / 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"); }
            showTimeStamp("Left edge Detection Ends");
            try
            {
                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);
            showTimeStamp("Right edge Dection Started");
            try
            {
                //g.DrawRectangles(yellowPen, rects);
                foreach (Blob blob in blobs2)
                {
                    if (
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) > 0.0001 &&
                        ((double)blob.Area) / ((double)bitmap.Width * bitmap.Height) < 0.004 &&
                        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"); }
            showTimeStamp("Right edge Dection Ends");
            try
            {
                if (quad[2].Y < quad[3].Y)
                {
                    IntPoint tp = quad[2];
                    quad[2] = quad[3];
                    quad[3] = tp;
                }
            }
            catch
            {
            }
            yellowPen.Dispose();
            redPen.Dispose();
            greenPen.Dispose();
            bluePen.Dispose();
            brownPen.Dispose();
            g.Dispose();

            //// put new image to clipboard
            //Clipboard.SetDataObject(bitmap);
            // and to picture box
            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();
                }
                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();
                }
            }
            if (quad.Count != 4)
            {
                if (contint <= 60)
                {
                    if (contint >= 0)
                    {
                        contint += 5;
                        contint *= -1;
                        return(ExtractOMRSheet(basicImage, fillint, contint, OMRSheets));
                    }
                    else
                    {
                        contint *= -1;
                        contint += 10;
                        return(ExtractOMRSheet(basicImage, fillint, contint, OMRSheets));
                    }
                }
                else
                {
                    MessageBox.Show("Extraction Failed.");
                    return(basicImage);
                }
            }
            else
            {
                IntPoint tp2 = quad[3];
                quad[3] = quad[1];
                quad[1] = tp2;
                QuadrilateralTransformation wrap = new QuadrilateralTransformation(quad);
                wrap.UseInterpolation = false;
                Rectangle sr = OMRSheetReader.GetSheetPropertyLocation(OMRSheets, OMREnums.OMRSheet.A550, OMREnums.OMRProperty.SheetSize);
                wrap.AutomaticSizeCalculaton = false;
                wrap.NewWidth  = sr.Width;
                wrap.NewHeight = sr.Height;
                wrap.Apply(basicImage).Save("LastImg.jpg", ImageFormat.Jpeg);
                System.Drawing.Image imgl = (System.Drawing.Image)wrap.Apply(basicImage);
                Graphics             gg   = Graphics.FromImage(imgl);
                Pen pr = new Pen(Brushes.Red, 2);

                //gg.DrawRectangle(pr, MyXML.OMRSheetReader.GetSheetProperty(OMRSheets, MyXML.OMREnums.OMRSheet.A550, MyXML.OMREnums.OMRProperty.tensBlock1));
                //gg.DrawRectangle(pr, MyXML.OMRSheetReader.GetSheetProperty(OMRSheets, MyXML.OMREnums.OMRSheet.A550, MyXML.OMREnums.OMRProperty.tensBlock2));
                //gg.DrawRectangle(pr, MyXML.OMRSheetReader.GetSheetProperty(OMRSheets, MyXML.OMREnums.OMRSheet.A550, MyXML.OMREnums.OMRProperty.tensBlock3));
                //gg.DrawRectangle(pr, MyXML.OMRSheetReader.GetSheetProperty(OMRSheets, MyXML.OMREnums.OMRSheet.A550, MyXML.OMREnums.OMRProperty.tensBlock4));

                pr.Dispose();
                gg.Dispose();
                return((Bitmap)imgl);
            }
        }
Exemplo n.º 3
0
        public void RunEdgeDetection(EdgeDetectionOptions options)
        {
            if (HasRunEdgeDetection)
            {
                return;
            }
            using (Bitmap newBitmap = LoadBitmap())
            {
                Rectangle rect = new Rectangle(0, 0, newBitmap.Width, newBitmap.Height);
                using (UnmanagedImage image = new UnmanagedImage(newBitmap.LockBits(rect, ImageLockMode.ReadWrite, newBitmap.PixelFormat)))
                {
                    using (UnmanagedImage grayImage = UnmanagedImage.Create(image.Width, image.Height, PixelFormat.Format8bppIndexed))
                    {
                        Grayscale.CommonAlgorithms.BT709.Apply(image, grayImage);

                        Threshold threshold = new Threshold(options.Threshold);

                        using (UnmanagedImage edgesImage = EDGE_DETECTOR.Apply(grayImage))
                        {
                            Threshold thresholdFilter = new Threshold(options.Threshold);
                            thresholdFilter.ApplyInPlace(edgesImage);

                            if (options.ShowEdgesImage)
                            {
                                ImageForm.ShowImage("Enhanced Edges Image", edgesImage);
                            }

                            BlobCounter blobCounter = new BlobCounter();
                            blobCounter.MinHeight    = MINIMUM_BLOB_SIZE;
                            blobCounter.MinWidth     = MINIMUM_BLOB_SIZE;
                            blobCounter.FilterBlobs  = true;
                            blobCounter.ObjectsOrder = ObjectsOrder.Size;

                            blobCounter.ProcessImage(edgesImage);
                            Blob[] blobs = blobCounter.GetObjectsInformation();

                            Corners.Clear();
                            foreach (Blob blob in blobs)
                            {
                                List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);
                                List <IntPoint> corners    = null;

                                if (SHAPE_CHECKER.IsQuadrilateral(edgePoints, out corners))
                                {
                                    List <IntPoint> leftEdgePoints, rightEdgePoints;
                                    blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdgePoints, out rightEdgePoints);

                                    Corners.Add(corners);

                                    if (options.ShowBlobImages)
                                    {
                                        QuadrilateralTransformation quadTransformation = new QuadrilateralTransformation(corners, 200, 200);
                                        using (UnmanagedImage quadImage = quadTransformation.Apply(image))
                                        {
                                            ImageForm.ShowImage("Quad Image", quadImage);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // New frame received by the player
        private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)
        {
            BitmapData imageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);

            try
            {
                UnmanagedImage unmanagedImg = new UnmanagedImage(imageData);

                int x = (int)(unmanagedImg.Width / 3.19); // 443
                int y = (int)(unmanagedImg.Height / 2.2); // 490
                int w = (int)(unmanagedImg.Width / 2.7);  // 553
                int h = (int)(unmanagedImg.Height / 4);   // 270
                int s = (int)(unmanagedImg.Width / 10.2); // 141

                // Crop the player scroll window.  Speeds up the next couple operations
                Crop           onePlayer = new Crop(new Rectangle(x, y, w, h));
                UnmanagedImage img       = onePlayer.Apply(unmanagedImg);

                // Use a quadrilateral transformation to make the scroller a big square.
                List <IntPoint> corners = new List <IntPoint>();
                corners.Add(new IntPoint(s, 0));
                corners.Add(new IntPoint(img.Width - s, 0));;
                corners.Add(new IntPoint(img.Width, img.Height));
                corners.Add(new IntPoint(0, img.Height));

                QuadrilateralTransformation filter =
                    new QuadrilateralTransformation(corners, img.Width, img.Height);
                img = filter.Apply(img);

                // Crop the bottom half since it appears to have the best imagery
                Crop bottom = new Crop(new Rectangle(0, img.Height / 2, img.Width, img.Height / 2));
                img = bottom.Apply(img);

                UnmanagedImage grayImg = UnmanagedImage.Create(img.Width, img.Height, PixelFormat.Format8bppIndexed);
                Grayscale.CommonAlgorithms.BT709.Apply(img, grayImg);

                OtsuThreshold threshold = new OtsuThreshold();
                threshold.ApplyInPlace(grayImg);

                // Divide the square into 5 peices.  One for each color.
                UnmanagedImage[] colorImg = new UnmanagedImage[5];
                for (int i = 0; i < 5; i++)
                {
                    int  colorWidth  = grayImg.Width / 5;
                    int  colorHeight = grayImg.Height;
                    Crop colorCrop   = new Crop(new Rectangle(colorWidth * i, 0, colorWidth, colorHeight));
                    colorImg[i] = colorCrop.Apply(grayImg);
                }


                greenCol.Image  = colorImg[GREEN].ToManagedImage();
                redCol.Image    = colorImg[RED].ToManagedImage();
                yellowCol.Image = colorImg[YELLOW].ToManagedImage();
                blueCol.Image   = colorImg[BLUE].ToManagedImage();
                orangeCol.Image = colorImg[ORANGE].ToManagedImage();


                VerticalIntensityStatistics[] hist = new VerticalIntensityStatistics[5];

                for (int i = 0; i < 5; i++)
                {
                    hist[i] = new VerticalIntensityStatistics(colorImg[i]);
                }

                findPucks(hist);

                greenHist.Values  = hist[GREEN].Gray.Values;
                redHist.Values    = hist[RED].Gray.Values;
                yellowHist.Values = hist[YELLOW].Gray.Values;
                blueHist.Values   = hist[BLUE].Gray.Values;
                orangeHist.Values = hist[ORANGE].Gray.Values;

                pictureBox1.Image = img.ToManagedImage();
            }
            finally
            {
                image.UnlockBits(imageData);
            }
        }
Exemplo n.º 5
0
        private void camview_MouseUp(object sender, MouseEventArgs e)
        {
            int select_width, select_height;

            if ((e.X == x1) || (e.Y == y1))
            {
                return;
            }

            if (!snap_ready)
            {
                if (sel_rect.Checked)
                {
                    x2 = e.X;
                    y2 = e.Y;

                    if (x2 <= 0)
                    {
                        x2 = 0;
                    }

                    if (x2 >= camview.Width - 1)
                    {
                        x2 = camview.Width - 1;
                    }

                    if (y2 <= 0)
                    {
                        y2 = 0;
                    }

                    if (y2 >= camview.Height - 1)
                    {
                        y2 = camview.Height - 1;
                    }


                    if (x1 < x2)
                    {
                        sx = x1;
                    }
                    else
                    {
                        sx = x2;
                    }

                    if (y1 < y2)
                    {
                        sy = y1;
                    }
                    else
                    {
                        sy = y2;
                    }

                    select_width  = (int)Math.Round((fx * (1 + Math.Abs(x1 - x2))), 0);
                    select_height = (int)Math.Round((fy * (1 + Math.Abs(y1 - y2))), 0);
                    sx            = Math.Round((sx * fx), 0);
                    sy            = Math.Round((sy * fy), 0);

                    sel_bmp = cam_bmp.Clone(new Rectangle((int)sx, (int)sy, select_width, select_height), cam_bmp.PixelFormat);

                    selection.Image = sel_bmp;
                    richText.Text   = "Ungarbling this gibberish...";
                    process_image();
                }
                else
                {
                    List <IntPoint> quad;
                    quad = new List <IntPoint>(4);
                    qt   = new QuadrilateralTransformation();
                    quad.Add(new IntPoint((int)(fx * corners[0].X), (int)(fy * corners[0].Y)));
                    quad.Add(new IntPoint((int)(fx * corners[1].X), (int)(fy * corners[1].Y)));
                    quad.Add(new IntPoint((int)(fx * corners[2].X), (int)(fy * corners[2].Y)));
                    quad.Add(new IntPoint((int)(fx * corners[3].X), (int)(fy * corners[3].Y)));
                    qt.SourceQuadrilateral = quad;
                    sel_bmp         = qt.Apply(cam_bmp);
                    selection.Image = sel_bmp;
                    corner_index    = -1;
                }
            }
        }
Exemplo n.º 6
0
        public double[] detectionGlyph(bool CalculTailleTerrain)
        {
            bool Trouve = false;

            double[] ratio = new double[2] {
                0, 0
            };
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
            BlobCounter        blobCounter  = new BlobCounter();

            blobCounter.MinHeight    = 23;
            blobCounter.MinWidth     = 23;
            blobCounter.FilterBlobs  = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            // 4 - find all stand alone blobs
            blobCounter.ProcessImage(imgContour);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            // 5 - check each blob
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List <IntPoint> corners    = null;

                // Test de la forme selectionnée
                if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                {
                    // Détection des points de coutour
                    List <IntPoint> leftEdgePoints, rightEdgePoints, topEdgePoints, bottomEdgePoints;

                    Line Horizontale = Line.FromPoints(new IntPoint(0, 0), new IntPoint(10, 0));
                    blobCounter.GetBlobsLeftAndRightEdges(blobs[i], out leftEdgePoints, out rightEdgePoints);
                    blobCounter.GetBlobsTopAndBottomEdges(blobs[i], out topEdgePoints, out bottomEdgePoints);

                    // calculate average difference between pixel values from outside of the
                    // shape and from inside
                    float diff = CalculateAverageEdgesBrightnessDifference(leftEdgePoints, rightEdgePoints, imgNB);
                    // check average difference, which tells how much outside is lighter than
                    // inside on the average
                    if (diff > 20)
                    {
                        // Transformation de l'image reçu en un carré pour la reconnaissance
                        QuadrilateralTransformation quadrilateralTransformation = new QuadrilateralTransformation(corners, 60, 60);
                        UnmanagedImage glyphImage = quadrilateralTransformation.Apply(imgNB);

                        // Filtre de contraste
                        OtsuThreshold otsuThresholdFilter = new OtsuThreshold();
                        otsuThresholdFilter.ApplyInPlace(glyphImage);
                        imgContour = glyphImage;
                        // Reconnaissance du Glyph
                        Glyph Gl = new Glyph(glyphImage, GlyphSize);

                        Gl.ReconnaissanceGlyph(corners, imgNB);

                        // Si le Glyph est valide
                        if (Gl.getIdentifiant() > 0)
                        {
                            if (AutAffichage[0])
                            {
                                // Coloration des contours des zones détectées
                                UnImgReel.SetPixels(leftEdgePoints, Color.Red);
                                UnImgReel.SetPixels(rightEdgePoints, Color.Red);
                                UnImgReel.SetPixels(topEdgePoints, Color.Red);
                                UnImgReel.SetPixels(bottomEdgePoints, Color.Red);
                            }

                            // Détection du milieu
                            Line     line         = Line.FromPoints(corners[0], corners[2]);
                            Line     line2        = Line.FromPoints(corners[1], corners[3]);
                            IntPoint intersection = (IntPoint)line.GetIntersectionWith(line2);
                            if (AutAffichage[1])
                            {
                                dessinePoint(intersection, UnImgReel, 4, Color.Yellow);
                            }

                            // Calcul de la rotation
                            Line   ComparasionAngle = Line.FromPoints(corners[0], corners[1]);
                            Double rotation         = (int)ComparasionAngle.GetAngleBetweenLines(Horizontale);
                            rotation   += 90 * Gl.getNbRotation();
                            Gl.rotation = 360 - rotation;
                            rotation   *= (Math.PI / 180.0);


                            // Calcul d'un point en bout de pince
                            float Taille = corners[0].DistanceTo(corners[1]);

                            float taille = (Taille / BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille) * BibliotequeGlyph.Biblioteque[Gl.getPosition()].DistancePince;
                            int   x      = -(int)(System.Math.Sin(rotation) * taille);
                            int   y      = -(int)(System.Math.Cos(rotation) * taille);
                            x          += (int)intersection.X;
                            y          += (int)intersection.Y;
                            Gl.Position = new int[2] {
                                x, y
                            };
                            if (AutAffichage[2])
                            {
                                dessinePoint(new IntPoint(x, y), UnImgReel, 4, Color.Cyan);
                            }
                            imgContour = Gl.getImage();
                            addGlyph(Gl);

                            if (CalculTailleTerrain == true && Trouve == false)
                            {
                                Trouve = true;
                                int tailleglyph = BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille;

                                // Pythagore pour detection taille
                                Rectangle       a     = blobs[i].Rectangle;
                                double          angle = -Gl.rotation + 180;
                                List <IntPoint> coins = new List <IntPoint>();
                                coins.Add(new IntPoint(100, 100));
                                coins.Add(new IntPoint(100, 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph, 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph, 100));
                                IntPoint Centre = new IntPoint((coins[2].X + coins[0].X) / 2, (coins[2].Y + coins[0].Y) / 2);
                                int      radius = (int)(0.5 * Math.Sqrt(coins[0].DistanceTo(coins[1]) * coins[0].DistanceTo(coins[1]) + coins[1].DistanceTo(coins[2]) * coins[1].DistanceTo(coins[2])));
                                double   alpha  = Math.Atan2(coins[0].DistanceTo(coins[1]), coins[1].DistanceTo(coins[2])) * (180 / Math.PI);

                                double ang = 0;
                                for (i = 0; i < 4; i++)
                                {
                                    IntPoint tmp = coins[i];
                                    switch (i)
                                    {
                                    case 0:
                                        ang = alpha - 180 + angle;
                                        break;

                                    case 1:
                                        ang = +angle - alpha;
                                        break;

                                    case 2:
                                        ang = +angle + alpha;
                                        break;

                                    case 3:
                                        ang = -alpha + 180 + angle;
                                        break;
                                    }
                                    ang  *= (Math.PI / 180);
                                    tmp.X = (int)(Centre.X + radius * Math.Cos(ang));
                                    tmp.Y = (int)(Centre.Y + radius * Math.Sin(ang));

                                    coins[i] = tmp;
                                }

                                Rectangle r = new Rectangle(min(coins[0].X, coins[1].X, coins[2].X, coins[3].X), min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y),
                                                            max(coins[0].X, coins[1].X, coins[2].X, coins[3].X) - min(coins[0].X, coins[1].X, coins[2].X, coins[3].X),
                                                            max(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y) - min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y));
                                ratio[0] = ((double)r.Width / (double)a.Width) * 1.48;
                                ratio[1] = ((double)r.Height / (double)a.Height) * 1.48;
                            }
                        }
                    }
                }
            }
            if (Trouve == false || ratio[0] == 0 || ratio[0] == 1 || ratio[1] == 0 || ratio[1] == 1)
            {
                return(null);
            }
            ratio[0] *= 0.7;
            ratio[1] *= 0.7;
            return(ratio);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Detects and recognizes cards from source image
        /// </summary>
        /// <param name="source">Source image to be scanned</param>
        /// <returns>Recognized Cards</returns>
        public CardCollection Recognize(Bitmap source)
        {
            var            height       = ((double)source.Height / (double)source.Width * 640d);
            ResizeBilinear ImageResizer = new ResizeBilinear(640, (int)height);

            source = ImageResizer.Apply(source);
            CardCollection collection = new CardCollection();     //Collection that will hold cards
            Bitmap         temp       = source.Clone() as Bitmap; //Clone image to keep original image

            FiltersSequence seq = new FiltersSequence();

            seq.Add(Grayscale.CommonAlgorithms.BT709); //First add  grayScaling filter
            seq.Add(new OtsuThreshold());              //Then add binarization(thresholding) filter
            temp = seq.Apply(source);                  // Apply filters on source image


            //Extract blobs from image whose size width and height larger than 150
            BlobCounter extractor = new BlobCounter();

            extractor.FilterBlobs = true;
            extractor.MinWidth    = extractor.MinHeight = 150;
            extractor.MaxWidth    = extractor.MaxHeight = 350;
            extractor.ProcessImage(temp);

            //Will be used transform(extract) cards on source image
            QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation();

            //Will be used resize(scaling) cards
            ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight);

            var Blobs = extractor.GetObjectsInformation();

            foreach (Blob blob in Blobs)
            {
                //Get Edge points of card
                List <IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob);
                //Calculate/Find corners of card on source image from edge points
                List <IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints);

                quadTransformer.SourceQuadrilateral     = corners; //Set corners for transforming card
                quadTransformer.AutomaticSizeCalculaton = true;

                Bitmap cardImg = quadTransformer.Apply(source);          //Extract(transform) card image

                if (cardImg.Width > cardImg.Height)                      //If card is positioned horizontally
                {
                    cardImg.RotateFlip(RotateFlipType.Rotate90FlipNone); //Rotate
                }
                cardImg = resizer.Apply(cardImg);                        //Normalize card size

                Card card = new Card(cardImg, corners.ToArray());        //Create Card Object
                char color;
                try
                {
                    color = ScanColor(card.GetTopLeftPart()); //Scan color
                }
                catch (Exception ex)
                {
                    continue;
                }
                bool faceCard = IsFaceCard(cardImg); //Determine type of card(face or not)

                if (!faceCard)
                {
                    card.Suit = ScanSuit(cardImg, color); //Scan Suit of non-face card
                    card.Rank = ScanRank(cardImg);        //Scan Rank of non-face card
                }
                else
                {
                    Bitmap topLeft = card.GetTopLeftPart();
                    seq.Clear();
                    seq.Add(Grayscale.CommonAlgorithms.BT709);
                    seq.Add(new BradleyLocalThresholding());
                    topLeft = seq.Apply(topLeft);
                    BlobsFiltering bFilter = new BlobsFiltering(5, 5, 150, 150);
                    bFilter.ApplyInPlace(topLeft); //Filter blobs that can not be a suit

                    // topLeft.Save("topleft.bmp", ImageFormat.Bmp);

                    card.Suit = ScanFaceSuit(topLeft, color); //Scan suit of face card
                    card.Rank = ScanFaceRank(topLeft);        //Scan rank of face card
                }
                collection.Add(card);                         //Add card to collection
            }
            return(collection);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Scans dominant color on image and returns it.
        /// Crops rank part on image and analyzes suit part on image
        /// </summary>
        /// <param name="bmp">Bitmap to be scanned</param>
        /// <returns>Returns 'B' for black , 'R' for red</returns>
        private char ScanColor(Bitmap bmp)
        {
            System.Diagnostics.Debug.Flush();
            System.Diagnostics.Debug.Print("I'm here");
            char color = 'B';
            //Crop rank part


            Crop crop = new Crop(new Rectangle(0, bmp.Height / 2, bmp.Width, bmp.Height / 2));

            bmp = crop.Apply(bmp);
            Bitmap temp = commonSeq.Apply(bmp); //Apply filters

            //Find suit blob on image
            BlobCounter counter = new BlobCounter();

            counter.ProcessImage(temp);
            Blob[] blobs = counter.GetObjectsInformation();

            if (blobs.Length > 0) //If blobs found
            {
                Blob max = blobs[0];
                //Find blob whose size is biggest
                foreach (Blob blob in blobs)
                {
                    if (blob.Rectangle.Height > max.Rectangle.Height)
                    {
                        max = blob;
                    }
                    else if (blob.Rectangle.Height == max.Rectangle.Height)
                    {
                        max = blob.Rectangle.Width > max.Rectangle.Width ? blob : max;
                    }
                }

                QuadrilateralTransformation trans = new QuadrilateralTransformation();
                trans.SourceQuadrilateral = PointsCloud.FindQuadrilateralCorners(counter.GetBlobsEdgePoints(max));
                bmp = trans.Apply(bmp); //Extract suit
            }
            //Lock Bits for processing
            BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                                ImageLockMode.ReadOnly, bmp.PixelFormat);
            int totalRed   = 0;
            int totalBlack = 0;

            unsafe
            {
                //Count red and black pixels
                try
                {
                    UnmanagedImage img = new UnmanagedImage(imageData);

                    int   height    = img.Height;
                    int   width     = img.Width;
                    int   pixelSize = (img.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                    byte *p         = (byte *)img.ImageData.ToPointer();

                    // for each line
                    for (int y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (int x = 0; x < width; x++, p += pixelSize)
                        {
                            int r = (int)p[RGB.R];                     //Red pixel value
                            int g = (int)p[RGB.G];                     //Green pixel value
                            int b = (int)p[RGB.B];                     //Blue pixel value

                            if (r > g + b)                             //If red component is bigger then total of green and blue component
                            {
                                totalRed++;                            //then its red
                            }
                            else if (r <= g + b && (r < 50 && g < 50)) //If all components less 70
                            {
                                totalBlack++;                          //then its black
                            }
                        }
                    }
                }
                finally
                {
                    bmp.UnlockBits(imageData); //Unlock
                }
            }



            if (totalRed > totalBlack) //If red is dominant
            {
                color = 'R';           //Set color as Red
            }
            return(color);
        }
Exemplo n.º 9
0
        private void detectQuads(Bitmap bitmap)
        {
            // Greyscale
            filteredBitmap = Grayscale.CommonAlgorithms.BT709.Apply(bitmap);

            // edge filter
            SobelEdgeDetector edgeFilter = new SobelEdgeDetector();

            edgeFilter.ApplyInPlace(filteredBitmap);

            // Threshhold filter
            Threshold threshholdFilter = new Threshold(190);

            threshholdFilter.ApplyInPlace(filteredBitmap);

            BitmapData bitmapData = filteredBitmap.LockBits(
                new Rectangle(0, 0, filteredBitmap.Width, filteredBitmap.Height),
                ImageLockMode.ReadWrite, filteredBitmap.PixelFormat);


            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight   = 125;
            blobCounter.MinWidth    = 125;

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

            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();

            Bitmap bm = new Bitmap(filteredBitmap.Width, filteredBitmap.Height, PixelFormat.Format24bppRgb);

            Graphics g = Graphics.FromImage(bm);

            g.DrawImage(filteredBitmap, 0, 0);

            Pen             pen           = new Pen(Color.Red, 5);
            List <IntPoint> cardPositions = new List <IntPoint>();


            // Loop through detected shapes
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List <IntPoint> corners;
                bool            sameCard = false;

                // is triangle or quadrilateral
                if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
                {
                    // get sub-type
                    PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);

                    // Only return 4 corner rectanges
                    if ((subType == PolygonSubType.Parallelogram || subType == PolygonSubType.Rectangle) && corners.Count == 4)
                    {
                        // Check if its sideways, if so rearrange the corners so it's veritcal
                        rearrangeCorners(corners);

                        // Prevent it from detecting the same card twice
                        foreach (IntPoint point in cardPositions)
                        {
                            if (corners[0].DistanceTo(point) < 40)
                            {
                                sameCard = true;
                            }
                        }

                        if (sameCard)
                        {
                            continue;
                        }

                        // Hack to prevent it from detecting smaller sections of the card instead of the whole card
                        if (GetArea(corners) < 20000)
                        {
                            continue;
                        }

                        cardPositions.Add(corners[0]);

                        g.DrawPolygon(pen, ToPointsArray(corners));

                        // Extract the card bitmap
                        QuadrilateralTransformation transformFilter = new QuadrilateralTransformation(corners, 211, 298);
                        cardBitmap = transformFilter.Apply(cameraBitmap);

                        List <IntPoint> artCorners = new List <IntPoint>();
                        artCorners.Add(new IntPoint(14, 35));
                        artCorners.Add(new IntPoint(193, 35));
                        artCorners.Add(new IntPoint(193, 168));
                        artCorners.Add(new IntPoint(14, 168));

                        // Extract the art bitmap
                        QuadrilateralTransformation cartArtFilter = new QuadrilateralTransformation(artCorners, 183, 133);
                        cardArtBitmap = cartArtFilter.Apply(cardBitmap);

                        MagicCard card = new MagicCard();
                        card.corners       = corners;
                        card.cardBitmap    = cardBitmap;
                        card.cardArtBitmap = cardArtBitmap;
                        card.area          = GetArea(corners);

                        magicCards.Add(card);
                    }
                }
            }

            pen.Dispose();
            g.Dispose();

            filteredBitmap = bm;
        }
Exemplo n.º 10
0
        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
            }
        }