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(); } }
public Match(Contour templateContour, Contour pageContour) { TemplateContour = templateContour; PageContour = pageContour; }