public Rectangle[] FindPunctuation(Rectangle[] boxes)
 {
     Rectangle[] points = boxes.Where(box => box.Diameter().InRange(minPunctuationSize, maxCharSize-1)).ToArray();
     Rectangle[] chars = FindChars(boxes);
     var groupBy = chars.Group();
     return
         points
     //                .Where(p => !chars.IntersectsWith(p))
     //                .Where(p => chars.Any(ch => ch.MaxCoordDistanceTo(p) < ch.Diameter())) // significantly slow down. need optimization (for example with KD-Tree)
         .Where(p => groupBy.ContainsKey(p.Sector()) && !groupBy.IntersectsWith(p))
         .ToArray();
 }
        // Assumes no rectangles are overlapping beyond their edges
        public static bool IsSurroundedBy(this Point point, Rectangle[] usedSpace)
        {
            // Cannot surround a point with only one edge
            if (usedSpace.Length < 2) return false;

            var rectsSharingCorner = usedSpace.Where(r => r.GetCorners().Contains(point)).ToArray();
            var rectsSharingEdge = usedSpace.Where(r => r.SharesEdge(point))
                .Where(r => !rectsSharingCorner.Contains(r))
                .ToArray();

            // Four rects sharing a corner = surrounded
            if (rectsSharingCorner.Length == 4) return true;

            // Two rects sharing a corner = one rect needs to share an edge to be surrounded
            if (rectsSharingCorner.Length == 2 && rectsSharingEdge.Length == 1) return true;

            // No rects sharing a corner = two rects needs to share an edge to be surrounded
            if (rectsSharingCorner.Length == 0 && rectsSharingEdge.Length == 2) return true;

            //// One or three rects sharing a corner = at least one diagonal exposed
            //if (rectsSharingCorner.Length == 3) return false;
            //if (rectsSharingCorner.Length == 1) return false;
            return false;
        }
Exemple #3
0
        /// <summary>
        /// This method tries to order the blobs in rows.
        /// </summary>
        private Dictionary<int, List<Rectangle>> ReorderBlobs(Rectangle[] blobs)
        {
            Dictionary<int, List<Rectangle>> result = new Dictionary<int, List<Rectangle>>();
            if (blobs.Length < 1)
                return result;

            // Merge intersecting blobs (we filter some very small blobs first).
            List<Rectangle> mergedBlobs =
                MergeIntersectingBlobs(blobs.Where(r => r.Width * r.Height >= txtPreMergeFilter.Value).ToArray());

            // Filter for blobs that are larger than 50 "sq pixels" and order by Y.
            mergedBlobs =
                new List<Rectangle>(
                    mergedBlobs.Where(r => r.Height * r.Width >= txtPostMergeFilter.Value).OrderBy(r => r.Y));

            // Add the first row and blob.
            int currRowInd = 0;
            result.Add(currRowInd, new List<Rectangle>());
            result[currRowInd].Add(mergedBlobs[0]);

            // Now we loop thru all the blobs and try to guess where a new line begins.
            for (int i = 1; i < mergedBlobs.Count; i++)
            {
                // Since the blobs are ordered by Y, we consider a NEW line if the current blob's Y
                // is BELOW the previous blob lower quarter.
                // The assumption is that blobs on the same row will have more-or-less same Y, so if
                // the Y is below the previous blob lower quarter it's probably a new line.
                if (mergedBlobs[i].Y > mergedBlobs[i - 1].Y + 0.75 * mergedBlobs[i - 1].Height)
                {
                    // Add a new row to the dictionary
                    ++currRowInd;
                    result.Add(currRowInd, new List<Rectangle>());
                }

                // Add blob to the current row.
                result[currRowInd].Add(mergedBlobs[i]);
            }

            return result;
        }
 public Rectangle[] FindChars(Rectangle[] boxes)
 {
     return boxes.Where(box => box.Diameter().InRange(minCharSize, maxCharSize)).ToArray();
 }
Exemple #5
0
        /// <summary>
        /// This method looks for blobs that intersect and join them into one blob.
        /// </summary>
        private List<Rectangle> MergeIntersectingBlobs(Rectangle[] blobs)
        {
            // Loop thru all blobs.
            int i = 0;
            while (i < blobs.Length)
            {
                // Ignore empty blobs.
                if (blobs[i].IsEmpty)
                {
                    ++i;
                    continue;
                }

                // When we check for intersection we want to inflate the current blob, this is
                // for special cases where there are very close blobs that do not intersect and we DO want
                // them to intersect, for example the letters "i" or j" where the dot above the letter is a
                // different not intersecting blob, so by inflating the current blon we would hopefully
                // make them intersect.
                Rectangle tmp = blobs[i];
                tmp.Inflate((int)txtWidthMergeSense.Value, (int)txtHeightMergeSense.Value);

                // Go check the following blobs (it is order by X) and see if they are intersecting with
                // the current i'th blob.
                bool merged = false;
                for (int j = i + 1; j < blobs.Length; ++j)
                {
                    // Ignore empty blobs.
                    if (blobs[j].IsEmpty)
                    {
                        continue;
                    }

                    // If the j'th blob X is beyond the i'th blob area it means there are no more
                    // potential blobs that will intersect with the i'th blob, hence we can stop (because blobs are sorted on X).
                    if (blobs[j].X > tmp.X + tmp.Width)
                        break;

                    // Check if there is intersection.
                    if (tmp.IntersectsWith(blobs[j]))
                    {
                        // Replace the i'th blob with the union with j
                        // (Note we are using the i'th blob and not the inflated blob (tmp)).
                        blobs[i] = Rectangle.Union(blobs[i], blobs[j]);

                        // Set j'th blob to be empty so we will ignore it from now on.
                        blobs[j] = new Rectangle();

                        // Stop the current loop.
                        merged = true;
                        break;
                    }
                }

                // If we had a merge we don't move to the next Blob as the newly created
                // joined blob has to be checked for another newly potential intersections.
                if (!merged)
                    ++i;
            }

            // Create the result list with only non-empty rectangles.
            List<Rectangle> result = new List<Rectangle>(blobs.Where(r => !r.IsEmpty));
            return result;
        }