/** * Extracts a horizontal or vertical shape of the original Shape. * The area of the new, smaller flat shape will be smaller thatn the areaLimit. * sizeLimit specifies the width of the flat, extracted shape. */ public static Shape reduceShapeHVAreaLimit(Shape originalShape, Point? firstPoint, int sizeLimit, bool horizontal, int areaLimit) { int px, py, nx, ny; int[] neighx = { -1, 0, 1, -1, 1, -1, 0, 1 }, neighy = { -1, -1, 1, 0, 0, 1, 1, 1 }; Shape reducedShape = new Shape(); Queue<Point?> queue = new Queue<Point?>(); if (originalShape == null) { return null; } if (!originalShape.contains(firstPoint)) { return null; } queue.Enqueue(firstPoint); while (true) { Point? head = queue.Dequeue(); reducedShape.Add(head); int reducedArea = reducedShape.Area; Point? shapeCenter = reducedShape.getCenter(); px = head.Value.X; py = head.Value.Y; for (int i = 0; i < 8; i++) { nx = px + neighx[i]; ny = py + neighy[i]; Point? neighbour = new Point(nx, ny); if ((originalShape.contains(neighbour)) && (!reducedShape.contains(neighbour)) && (!queue.Contains(neighbour)) && (queue.Count() + reducedArea < areaLimit) && (((horizontal) && (Math.Abs(nx - shapeCenter.Value.X) < sizeLimit)) || ((!horizontal) && (Math.Abs(ny - shapeCenter.Value.Y) < sizeLimit))) ) { queue.Enqueue(neighbour); } } if ((reducedArea > areaLimit) || (queue.Count == 0)) { break; } } return reducedShape; }
public static Shape reduceShapeToAreaAndRatio(Shape originalShape, Point? firstPoint, double ratioLimit, int areaLowerLimit, int areaHigherLimit) { int[] neighx = { -1, 0, 1, -1, 1, -1, 0, 1 }; int[] neighy = { -1, -1, 1, 0, 0, 1, 1, 1 }; if (ratioLimit <= 0) { return null; } double ratioLimitInv = 1 / ratioLimit; int px = 0, py = 0, nx, ny; Point? head, neighbour; Shape reducedShape = new Shape(); int reducedArea = 0; double reducedRatio = 1.0; Queue<Point?> queue = new Queue<Point?>(); if (originalShape == null) { return null; } if (!originalShape.contains(firstPoint)) { return null; } queue.Enqueue(firstPoint); while (true) { head = queue.Dequeue(); reducedShape.Add(head); reducedRatio = reducedShape.getAspectRatio(); reducedArea = reducedShape.Set.Count; py = head.Value.Y; for (int i = 0; i < 8; i++) { nx = px + neighx[i]; ny = py + neighy[i]; neighbour = new Point(nx, ny); if ((originalShape.contains(neighbour)) && (!reducedShape.contains(neighbour)) && (!queue.Contains(neighbour)) && (reducedArea + queue.Count < areaHigherLimit)) { queue.Enqueue(neighbour); } } /* * Stop condition. It's weird but it's faster */ if (!(queue.Count > 0)) { break; } else { if (reducedArea < areaLowerLimit) { continue; } else if (reducedArea > areaHigherLimit) { break; } else { if ((ratioLimitInv < reducedRatio) && (reducedRatio < ratioLimit)) { continue; } else { break; } } } } if ((reducedShape.Set.Count < areaLowerLimit) || ((ratioLimitInv < reducedRatio) && (reducedRatio < ratioLimit))) { return null; } return reducedShape; }
/** * Finds a contiguos shape in the boolean image by doing breadth first search. * It also deletes the found pixels from the source image, cutting the shape out from the original. */ public static Shape breadthShapeExtendAndCut(bool[,] source, Point? firstPoint) { int i; int height = source.GetLength(0), width = source.Length / source.GetLength(0); int px, py, nx, ny; Point? head, neighbour; Queue<Point?> queue; int[] neighx = { -1, 0, 1, -1, 1, -1, 0, 1 }, neighy = { -1, -1, 1, 0, 0, 1, 1, 1 }; Shape shape = new Shape(); queue = new Queue<Point?>(); queue.Enqueue(firstPoint); while (queue.Count > 0) { head = queue.Dequeue(); shape.Add(head); px = head.Value.X; py = head.Value.Y; source[py, px] = false; for (i = 0; i < 8; i++) { nx = px + neighx[i]; ny = py + neighy[i]; neighbour = new Point(nx, ny); if ((nx >= 0) && (nx < width) && (ny >= 0) && (ny < height) && (source[ny, nx]) && (!shape.contains(neighbour)) && (!queue.Contains(neighbour))) { queue.Enqueue(neighbour); source[ny, nx] = false; } } } return shape; }