private static void SaveDebugImage(DirectBitmap db, CoordsData coordsData, int nr) { using (var bmp = db.Bitmap.Clone(new Rectangle(0, 0, db.Width, db.Height), db.Bitmap.PixelFormat)) { var setCoordsCount = coordsData.Coords.Count; var step = 255 / setCoordsCount; using (var g = Graphics.FromImage(bmp)) { using (var b = new SolidBrush(Color.Black)) for (int c = 0; c < setCoordsCount; c++) { b.Color = Color.FromArgb(255 - (c * step), c * step, 50); g.FillRectangle(b, new Rectangle(coordsData.Coords[c].X, coordsData.Coords[c].Y, 1, 1)); } const int factor = 5; using (var resizedBmp = new Bitmap(bmp.Width * factor, bmp.Height * factor)) using (var gr = Graphics.FromImage(resizedBmp)) { gr.DrawImage(bmp, new Rectangle(0, 0, bmp.Width * factor, bmp.Height * factor)); resizedBmp.Save(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "ASBFontTesting", "RegionGrowing", $"RG_{DateTime.Now:yyyy-MM-dd-HH-mm-ss-ffff}_{nr}.png")); } } } }
private static CoordsData VisitChar(int x, int y, bool[,] visited, DirectBitmap db, CoordsData data = null) { // TODO better region growing algorithm? if (data == null) { data = new CoordsData(x, x, y, y); } data.Add(x, y); for (int i = 0; i < OffsetX.Length; i++) { var nextX = OffsetX[i] + x; var nextY = OffsetY[i] + y; var isSafe = nextX > 0 && nextX < db.Width && nextY > 0 && nextY < db.Height && !visited[nextX, nextY]; if (!isSafe) { continue; } visited[nextX, nextY] = true; if (IsNotBlank(db, nextX, nextY)) { VisitChar(nextX, nextY, visited, db, data); } } return(data); }
private static void VisitVertical(CoordsData coordsData, bool[,] visited, DirectBitmap db) { for (int i = coordsData.MinX; i <= coordsData.MaxX; i++) { for (int j = 0; j < db.Height; j++) { if (!visited[i, j] && IsNotBlank(db, i, j)) { coordsData.Add(i, j); } visited[i, j] = true; } } }
/// <summary> /// Adds set pixels of all columns of the pattern that are not part of another pattern. /// </summary> private static void VisitVertical(CoordsData coordsData, bool[,] visited, bool[,] image) { var h = image.GetLength(1); for (int x = coordsData.MinX; x <= coordsData.MaxX; x++) { for (int y = 0; y < h; y++) { if (visited[x, y]) { continue; } if (image[x, y]) { VisitChar(x, y, visited, image, coordsData); } visited[x, y] = true; } } }
///// <summary> ///// Collect all neighboring pixels of a character (region growing with recursive calls). ///// </summary> //private static CoordsData VisitCharRecursively(int x, int y, bool[,] visited, bool[,] image, CoordsData data = null) //{ // if (data == null) // data = new CoordsData(x, x, y, y); // var w = image.GetLength(0); // var h = image.GetLength(1); // data.Add(x, y); // for (int i = 0; i < OffsetX.Length; i++) // { // var nextX = OffsetX[i] + x; // var nextY = OffsetY[i] + y; // var isSafe = nextX >= 0 && nextX < w && nextY >= 0 && nextY < h && !visited[nextX, nextY]; // if (!isSafe) // { // continue; // } // visited[nextX, nextY] = true; // if (image[nextX, nextY]) // { // VisitCharRecursively(nextX, nextY, visited, image, data); // } // } // // debug // //data.ToDebugConsole(); // return data; //} /// <summary> /// Collect all neighboring pixels of a character (region growing with a stack). /// </summary> private static CoordsData VisitChar(int x, int y, bool[,] visited, bool[,] image, CoordsData data = null) { if (data == null) { data = new CoordsData(x, x, y, y); } var w = image.GetLength(0); var h = image.GetLength(1); var stackToCheck = new Stack <(int x, int y)>(image.GetLength(1) * 2); stackToCheck.Push((-1, -1)); stackToCheck.Push((x, y)); do { var(cx, cy) = stackToCheck.Pop(); data.Add(cx, cy); visited[cx, cy] = true; for (int i = 0; i < OffsetX.Length; i++) { var nextX = OffsetX[i] + cx; var nextY = OffsetY[i] + cy; // add neighbors that are set if (nextX >= 0 && nextX < w && nextY >= 0 && nextY < h && !visited[nextX, nextY] && image[nextX, nextY]) { visited[nextX, nextY] = true; stackToCheck.Push((nextX, nextY)); } } }while (stackToCheck.Peek().x != -1); return(data); }