/** * Uses a breadth-first search in order to get the rectangle around a blob given a coordinate in the blob **/ private Rectangle expandBlob(Image image, Coordinate startingPoint) { // create a BinaryImage in order to store which points we have checked already bool[] bin = new bool[image.Pixels.Length]; for (int i = 0; i < bin.Length; i++) { bin [i] = false; } BinaryImage binaryMap = new BinaryImage(bin, image.Width, image.Height); Rectangle blob = new Rectangle(startingPoint.X, startingPoint.Y, startingPoint.X, startingPoint.Y); List <Coordinate> pointsToCheck = new List <Coordinate> (); // start by expanding in all directions from the starting point pointsToCheck = getUnseenWhiteAdjacentPixels(startingPoint, image, binaryMap); // keep expanding from every single point in the list until we can't expand any further while (pointsToCheck.Count > 0) { List <Coordinate> newPointsToCheck = new List <Coordinate> (); // check if this point can expand the rectangle and update it if so foreach (Coordinate pointToCheck in pointsToCheck) { if (pointToCheck.X < blob.TopLeftX) { blob.TopLeftX = pointToCheck.X; } else if (pointToCheck.X > blob.BottomRightX) { blob.BottomRightX = pointToCheck.X; } if (pointToCheck.Y > blob.TopLeftY) { blob.TopLeftY = pointToCheck.Y; } else if (pointToCheck.Y < blob.BottomRightY) { blob.BottomRightY = pointToCheck.Y; } // expand from this point List <Coordinate> adjacent = getUnseenWhiteAdjacentPixels(pointToCheck, image, binaryMap); newPointsToCheck.AddRange(adjacent); } pointsToCheck.Clear(); pointsToCheck = newPointsToCheck; } return(blob); }
/** * Apply the filter to a given BinaryImage. * All transformations will be done on a copy of the image and the original image will not be altered. **/ public BinaryImage Apply(BinaryImage image) { BinaryImage newImage = new BinaryImage(new bool[image.Pixels.Length], image.Width, image.Height); for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { bool pixel = image.getPixel(x, y); newImage.setPixel(x, y, pixel); if (!pixel) { continue; } for (int modX = halfStrokeWidth * (-1); modX < halfStrokeWidth; modX++) { int newX = x + modX; if (newX > 0 && newX < image.Width) { newImage.setPixel(newX, y, pixel); } } for (int modY = halfStrokeWidth * (-1); modY < halfStrokeWidth; modY++) { int newY = y + modY; if (newY > 0 && newY < image.Height) { newImage.setPixel(x, newY, pixel); } } } } return(newImage); }
private List <Coordinate> getUnseenWhiteAdjacentPixels(Coordinate coordinate, Image image, BinaryImage seenMap) { int[][] modifiers = { new int[] { 0, -1 }, // up new int[] { 1, -1 }, // up-right new int[] { 1, 0 }, // right new int[] { 1, 1 }, // down-right new int[] { 0, 1 }, // down new int[] { -1, 1 }, // down-left new int[] { -1, 0 }, // left new int[] { -1, -1 } // up-left }; List <Coordinate> adjacentCoordinates = new List <Coordinate> (); foreach (int[] modifier in modifiers) { Coordinate modCoord = new Coordinate(coordinate.X + modifier[0], coordinate.Y + modifier[1]); if (modCoord.X < 0 || modCoord.X > image.Width - 1) { continue; } if (modCoord.Y < 0 || modCoord.Y > image.Height - 1) { continue; } if (!adjacentCoordinates.Contains(modCoord) && !seenMap.getPixel(modCoord.X, modCoord.Y) && !isBlackPixel(modCoord, image)) { adjacentCoordinates.Add(modCoord); seenMap.setPixel(modCoord.X, modCoord.Y, true); } } return(adjacentCoordinates); }