Ejemplo n.º 1
0
        private HashSet <LineShape> FilterHorizontalLines(Image hlines, BoundedObjectGrid <CheckboxShape> checkboxGrid)
        {
            HashSet <LineShape> lines = new HashSet <LineShape>();

            int minThickLineWidth  = LineDetector.MinThickLineWidth.MulDiv(hlines.VerticalResolution, 200);
            int minThickLineLength = LineDetector.MinThickLineLength.MulDiv(hlines.HorizontalResolution, 200);
            int maxBoxSize         = this.MaxBoxSize.MulDiv(hlines.HorizontalResolution, 200);

            // find connected components and do preliminary filtering
            foreach (ConnectedComponent component in hlines.FindConnectedComponents(8))
            {
                Rectangle bounds   = component.Bounds;
                int       maxWidth = component.MaxHeight();

                bool isBad = false;

                if (bounds.Width.Between(minThickLineWidth, minThickLineLength - 1) &&
                    bounds.Height.Between(minThickLineWidth, minThickLineLength - 1) &&
                    maxWidth > minThickLineLength)
                {
                    // too thick for the length
                    isBad = true;
                }

                if (!isBad && bounds.Width <= maxBoxSize && checkboxGrid != null && checkboxGrid.EnumObjects(bounds).Any())
                {
                    // is part of the check box
                    isBad = true;
                }

                if (isBad)
                {
                    hlines.SetWhite(bounds);
                }
                else
                {
                    LineShape newline = new LineShape(bounds, maxWidth, LineTypes.Horizontal);
                    lines.Add(newline);
                }
            }

            // find line vectors
            AlignedObjectGrid <LineShape> grid = new AlignedObjectGrid <LineShape>(hlines.Bounds, 10, 20, RectangleLTRBComparer.Default);

            grid.AddRange(lines, true, true);

            int minLineLength = (this.MinHorizontalLineLength * hlines.HorizontalResolution).Round();
            int maxGap        = LineDetector.MaxLineGap.MulDiv(hlines.HorizontalResolution, 200);
            int tolerance     = 3.MulDiv(hlines.VerticalResolution, 200);

            HashSet <LineShape> newlines = new HashSet <LineShape>();

            foreach (LineShape line in lines)
            {
                if (line.VerticalAlignment == VerticalAlignment.None)
                {
                    IList <LineShape> alignedLines = grid.FindVerticalAlignment(
                        line,
                        VerticalAlignment.Center,
                        maxGap,
                        tolerance,
                        (result, bounds) => bounds.Width >= minLineLength && (result.Count >= 2 || result.Any(o => o.Bounds.Width >= minLineLength)));

                    if (alignedLines.Count > 0)
                    {
                        LineShape newline = new LineShape(
                            Rectangle.Union(alignedLines.Select(x => x.Bounds)),
                            alignedLines[0].Begin,
                            alignedLines[alignedLines.Count - 1].End,
                            alignedLines.Max(x => x.Width),
                            LineTypes.Horizontal);

                        newlines.Add(newline);
                    }
                }
            }

            // remove merged and short lines
            lines.RemoveWhere(x =>
            {
                // remove merged lines
                bool remove = x.VerticalAlignment != VerticalAlignment.None;

                // remove small not merged lines
                // also delete them from the image
                if (x.VerticalAlignment == VerticalAlignment.None && x.Bounds.Width < minLineLength)
                {
                    hlines.SetWhite(x.Bounds);
                    remove = true;
                }

                return(remove);
            });

            lines.UnionWith(newlines);

            return(lines);
        }
Ejemplo n.º 2
0
        private HashSet <LineShape> FilterVerticalLines(Image vlines, Image hlines, BoundedObjectGrid <CheckboxShape> checkboxGrid)
        {
            HashSet <LineShape> lines = new HashSet <LineShape>();

            int minThickLineWidth  = LineDetector.MinThickLineWidth.MulDiv(vlines.HorizontalResolution, 200);
            int minThickLineLength = LineDetector.MinThickLineLength.MulDiv(vlines.VerticalResolution, 200);
            int maxBoxSize         = this.MaxBoxSize.MulDiv(vlines.VerticalResolution, 200);

            // find connected components and do preliminary filtering
            foreach (ConnectedComponent component in vlines.FindConnectedComponents(8))
            {
                Rectangle bounds   = component.Bounds;
                int       maxWidth = component.MaxWidth();

                bool isBad = false;

                if (bounds.Width.Between(minThickLineWidth, minThickLineLength - 1) &&
                    bounds.Height.Between(minThickLineWidth, minThickLineLength - 1) &&
                    maxWidth > minThickLineLength)
                {
                    // too thick for the length
                    isBad = true;
                }

                if (!isBad && bounds.Height <= maxBoxSize && checkboxGrid != null && checkboxGrid.EnumObjects(bounds).Any())
                {
                    // is part of the check box
                    isBad = true;
                }

                if (isBad)
                {
                    vlines.SetWhite(bounds);
                }
                else
                {
                    Point     begin = new Point(component.GetLine(bounds.Y).Center, bounds.Y);
                    Point     end   = new Point(component.GetLine(bounds.Bottom - 1).Center, bounds.Bottom - 1);
                    LineShape line  = new LineShape(bounds, begin, end, maxWidth, LineTypes.Vertical);
                    lines.Add(line);
                }
            }

            // find line vectors
            AlignedObjectGrid <LineShape> grid = new AlignedObjectGrid <LineShape>(vlines.Bounds, 10, 20, RectangleTBLRComparer.Default);

            grid.AddRange(lines, true, true);

            int minLineLength = (this.MinVerticalLineLength * vlines.VerticalResolution).Round();
            int maxGap        = LineDetector.MaxLineGap.MulDiv(vlines.VerticalResolution, 200);
            int tolerance     = 6.MulDiv(vlines.HorizontalResolution, 200);

            HashSet <LineShape> newlines = new HashSet <LineShape>();

            foreach (LineShape line in lines)
            {
                if (line.HorizontalAlignment == HorizontalAlignment.None)
                {
                    IList <LineShape> alignedLines = grid.FindHorizontalAlignment(
                        line,
                        HorizontalAlignment.Center,
                        Math.Min(maxGap, line.Bounds.Height),
                        tolerance,
                        (result, bounds) => (bounds.Height >= minLineLength && (result.Count >= 3 || result.Any(o => o.Bounds.Height >= minLineLength))) || LineHasIntersectionsOnBothEnds(bounds));

                    if (alignedLines.Count > 0)
                    {
                        LineShape newline = new LineShape(
                            Rectangle.Union(alignedLines.Select(x => x.Bounds)),
                            alignedLines[0].Begin,
                            alignedLines[alignedLines.Count - 1].End,
                            alignedLines.Max(x => x.Width),
                            LineTypes.Vertical);

                        newlines.Add(newline);
                    }
                }
            }

            // remove merged and short lines
            lines.RemoveWhere(x =>
            {
                // remove merged lines
                bool remove = x.HorizontalAlignment != HorizontalAlignment.None;

                // remove small not merged lines
                // also delete them from the image
                if (x.HorizontalAlignment == HorizontalAlignment.None && x.Bounds.Height < minLineLength && !LineHasIntersectionsOnBothEnds(x.Bounds))
                {
                    vlines.SetWhite(x.Bounds);
                    remove = true;
                }

                return(remove);
            });

            lines.UnionWith(newlines);

            bool LineHasIntersectionsOnBothEnds(Rectangle bounds)
            {
                if (hlines != null)
                {
                    int boxheight = Math.Min(bounds.Width, bounds.Height);

                    Rectangle top = new Rectangle(bounds.X, bounds.Y, bounds.Width, boxheight);
                    top.Inflate(0, 2 * boxheight);
                    top.Intersect(hlines.Bounds);

                    Rectangle bottom = new Rectangle(bounds.X, bounds.Bottom - boxheight, bounds.Width, boxheight);
                    bottom.Inflate(0, 2 * boxheight);
                    bottom.Intersect(hlines.Bounds);

                    return(!hlines.IsAllWhite(top) && !hlines.IsAllWhite(bottom));
                }
                else
                {
                    return(false);
                }
            }

            return(lines);
        }