static public void DeskewAsColumnOfBlocks(ref Bitmap bitmap, int blockMaxLength, int blockMinGap, Size structuringElementSize, int contourMaxCount, double angleMaxDeviation, Color marginColor)
        {
            (float H, float V)dpi = (H : bitmap.HorizontalResolution, V : bitmap.VerticalResolution);
            using (Image <Rgb, byte> image = bitmap.ToImage <Rgb, byte>())
            {
                bitmap.Dispose();
                Size margin    = getScaledBlockMargin();
                Rgb  marginRgb = new Rgb(marginColor);
                Image <Rgb, byte> deskewedImage = new Image <Rgb, byte>(image.Width + 2 * margin.Width, image.Height /*+ 2 * margin.Height*/, marginRgb);

                //int lastBlockBottomLeft = -1;
                //int lastBlockBottomRight = -1;
                Image <Gray, byte> image2 = image.Convert <Gray, byte>();
                CvInvoke.BitwiseNot(image2, image2);
                //CvInvoke.Blur(image2, image2, new Size(3, 3), new Point(0, 0));
                CvInvoke.GaussianBlur(image2, image2, new Size(25, 25), 5);//remove small spots
                CvInvoke.Threshold(image2, image2, 125, 255, ThresholdType.Otsu | ThresholdType.Binary);
                Mat se = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(5, 5), new Point(-1, -1));
                CvInvoke.Dilate(image2, image2, se, new Point(-1, -1), 1, BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);
                //CvInvoke.Erode(image2, image2, se, new Point(-1, -1), 5, BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);

                //CvInvoke.BitwiseNot(image2, image2);
                //return image2.ToBitmap();

                VectorOfVectorOfPoint cs = new VectorOfVectorOfPoint();
                Mat h = new Mat();
                CvInvoke.FindContours(image2, cs, h, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
                if (cs.Size < 1)
                {
                    return;
                }

                Array          hierarchy = h.GetData();
                List <Contour> contours  = new List <Contour>();
                for (int i = 0; i < cs.Size; i++)
                {
                    int p = (int)hierarchy.GetValue(0, i, Contour.HierarchyKey.Parent);
                    if (p < 1)
                    {
                        contours.Add(new Contour(hierarchy, i, cs[i]));
                    }
                }
                if (contours.Where(a => a.ParentId < 0).Count() < 2)//the only parent is the whole page frame
                {
                    contours.RemoveAll(a => a.ParentId < 0);
                }
                else
                {
                    contours.RemoveAll(a => a.ParentId >= 0);
                }

                contours = contours.OrderBy(a => a.BoundingRectangle.Bottom).ToList();
                for (int blockY = 0; blockY < image.Height;)
                {
                    int blockBottom = image.Height - 1;
                    Tuple <Contour, Contour> lastSpan = null;
                    for (; contours.Count > 0;)
                    {
                        Contour c = contours[0];
                        contours.RemoveAt(0);
                        if (contours.Count > 0)
                        {
                            Contour minTop = contours.Aggregate((a, b) => a.BoundingRectangle.Top < b.BoundingRectangle.Top ? a : b);
                            if (c.BoundingRectangle.Bottom + blockMinGap <= minTop.BoundingRectangle.Top)
                            {
                                lastSpan = new Tuple <Contour, Contour>(c, minTop);
                            }
                        }

                        if (c.BoundingRectangle.Bottom > blockY + blockMaxLength && lastSpan != null)
                        {
                            blockBottom = lastSpan.Item1.BoundingRectangle.Bottom + blockMinGap / 2;
                            break;
                        }
                    }

                    Rectangle         blockRectangle     = new Rectangle(0, blockY, image2.Width, blockBottom + 1 - blockY);
                    Image <Rgb, byte> blockImage         = image.Copy(blockRectangle);
                    Image <Rgb, byte> deskewedBlockImage = deskew(blockImage, structuringElementSize, contourMaxCount, angleMaxDeviation, margin, marginRgb);
                    //int blockTopLeft = findOffsetLeft(deskewedBlockImage, 10).X;
                    //int blockTopRight = findOffsetRight(deskewedBlockImage, 10).X;
                    //if (lastBlockBottomLeft < 0)
                    //    lastBlockBottomLeft = blockTopLeft;
                    //if (lastBlockBottomRight < 0)
                    //    lastBlockBottomRight = blockTopRight;
                    //deskewedBlockImage.ROI = new Rectangle(blockTopLeft, 0, blockTopRight - blockTopLeft, deskewedBlockImage.Height);
                    //deskewedImage.ROI = new Rectangle(lastBlockBottomLeft - ((blockTopRight - blockTopLeft) - (lastBlockBottomRight - lastBlockBottomLeft)) / 2, blockRectangle.Y, blockTopRight - blockTopLeft, deskewedBlockImage.Height);
                    deskewedBlockImage.ROI = new Rectangle(0, margin.Height, deskewedBlockImage.Width, deskewedBlockImage.Height - 2 * margin.Height);
                    deskewedImage.ROI      = new Rectangle(0, blockRectangle.Y, deskewedBlockImage.ROI.Width, deskewedBlockImage.ROI.Height);
                    deskewedBlockImage.CopyTo(deskewedImage);
                    deskewedImage.ROI = Rectangle.Empty;
                    //lastBlockBottomLeft = findOffsetLeft(deskewedBlockImage, -10).X;
                    //lastBlockBottomRight = findOffsetRight(deskewedBlockImage, -10).X;
                    // break;
                    blockY = blockBottom + 1;
                }
                deskewedImage.ROI = getCropped(deskewedImage, marginRgb);//crop
                bitmap            = deskewedImage?.ToBitmap();
            }
            bitmap.SetResolution(dpi.H, dpi.V);
        }
Exemple #2
0
        static public void DeskewAsColumnOfBlocks(ref Bitmap bitmap, int blockMaxHeight, int minBlockSpan)
        {
            using (Image <Rgb, byte> image = bitmap.ToImage <Rgb, byte>())
            {
                bitmap.Dispose();

                //return image.ToBitmap();
                Image <Rgb, byte>  deskewedimage = new Image <Rgb, byte>(image.Size);
                Image <Gray, byte> image2        = image.Convert <Gray, byte>();
                CvInvoke.BitwiseNot(image2, image2);
                //CvInvoke.Blur(image2, image2, new Size(3, 3), new Point(0, 0));
                CvInvoke.GaussianBlur(image2, image2, new Size(25, 25), 5);//remove small spots
                CvInvoke.Threshold(image2, image2, 125, 255, ThresholdType.Otsu | ThresholdType.Binary);
                Mat se = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(5, 5), new Point(-1, -1));
                CvInvoke.Dilate(image2, image2, se, new Point(-1, -1), 1, BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);
                //CvInvoke.Erode(image2, image2, se, new Point(-1, -1), 5, BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);

                //CvInvoke.BitwiseNot(image2, image2);
                //return image2.ToBitmap();

                VectorOfVectorOfPoint cs = new VectorOfVectorOfPoint();
                Mat h = new Mat();
                CvInvoke.FindContours(image2, cs, h, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
                if (cs.Size < 1)
                {
                    return;
                }

                Array          hierarchy = h.GetData();
                List <Contour> contours  = new List <Contour>();
                for (int i = 0; i < cs.Size; i++)
                {
                    int p = (int)hierarchy.GetValue(0, i, Contour.HierarchyKey.Parent);
                    if (p < 1)
                    {
                        contours.Add(new Contour(hierarchy, i, cs[i]));
                    }
                }
                if (contours.Where(a => a.ParentId < 0).Count() < 2)//the only parent is the whole page frame
                {
                    contours.RemoveAll(a => a.ParentId < 0);
                }
                else
                {
                    contours.RemoveAll(a => a.ParentId >= 0);
                }

                contours = contours.OrderBy(a => a.BoundingRectangle.Bottom).ToList();
                for (int blockY = 0; blockY < image.Height;)
                {
                    int blockBottom = image.Height - 1;
                    Tuple <Contour, Contour> lastSpan = null;
                    for (; contours.Count > 0;)
                    {
                        Contour c = contours[0];
                        contours.RemoveAt(0);
                        if (contours.Count > 0)
                        {
                            Contour minTop = contours.Aggregate((a, b) => a.BoundingRectangle.Top < b.BoundingRectangle.Top ? a : b);
                            if (c.BoundingRectangle.Bottom + minBlockSpan <= minTop.BoundingRectangle.Top)
                            {
                                lastSpan = new Tuple <Contour, Contour>(c, minTop);
                            }
                        }

                        if (c.BoundingRectangle.Bottom > blockY + blockMaxHeight && lastSpan != null)
                        {
                            blockBottom = lastSpan.Item1.BoundingRectangle.Bottom + minBlockSpan / 2;
                            break;
                        }
                    }

                    Rectangle         blockRectangle = new Rectangle(0, blockY, image2.Width, blockBottom + 1 - blockY);
                    Image <Rgb, byte> blockImage     = image.Copy(blockRectangle);
                    blockImage        = deskew(blockImage);
                    deskewedimage.ROI = blockRectangle;
                    blockImage.CopyTo(deskewedimage);
                    deskewedimage.ROI = Rectangle.Empty;
                    // break;
                    blockY = blockBottom + 1;
                }
                bitmap = deskewedimage?.ToBitmap();
            }
        }