public void SaveSoftMask(string input, string outputPath) { using (var rgbImage = Image.Load(input)) { using (var output = new Image <Rgba32>(rgbImage.Width, rgbImage.Height)) { var cache = new ImageCache(rgbImage); for (int x = 0; x < rgbImage.Width; x++) { for (int y = 0; y < rgbImage.Height; y++) { output[x, y] = new Rgba32(cache[x, y], cache[x, y], cache[x, y]); } } output.Save(outputPath); } } }
internal static TargetMask FindCharacterMask(Point firstPixel, ImageCache image, CoordinateList blacklistedPoints, int minX, int maxX, int minY, int maxY) { var points = FindCharacterPixelPoints(firstPixel, image, blacklistedPoints, minX, maxX, minY, maxY); var minPointX = points.Min(p => p.X); var mask = new bool[points.Max(p => p.X) - points.Min(p => p.X) + 1, maxY - minY]; var softMask = new float[points.Max(p => p.X) - points.Min(p => p.X) + 1, maxY - minY]; var pixelCount = 0; float softPixelCount = 0; foreach (var p in points) { mask[p.X - minPointX, p.Y - minY] = true; softMask[p.X - minPointX, p.Y - minY] = image[p.X, p.Y]; softPixelCount += image[p.X, p.Y]; pixelCount++; } return(new TargetMask(mask, points.Max(p => p.X), minPointX, points.Max(p => p.X) - minPointX + 1, pixelCount, softPixelCount, softMask)); }
internal static List <Point> FindCharacterPixelPoints(Point firstPixel, ImageCache image, CoordinateList blacklistedPoints, int minX, int maxX, int minY, int maxY) { var characterPoints = new CoordinateList(); AddConnectedPoints(characterPoints, firstPixel, image, blacklistedPoints, minX, maxX, minY, maxY); var midX = (int)characterPoints.Average(p => p.X); //Scan down from the initial midpoint for gap characters //Account for gaps such as in i or j for (int y = characterPoints.Where(p => p.X == midX).Max(p => p.Y) + 1; y < maxY; y++) { AddConnectedPoints(characterPoints, new Point(midX, y), image, blacklistedPoints, minX, maxX, minY, maxY); } //Scan up from new midpoint for gap characters that have a bit sticking out the front. Account for gaps like in ; midX = (int)characterPoints.Average(p => p.X); var highestY = characterPoints.Min(p => p.X == midX ? p.Y : maxY); for (int i = highestY; i >= minY; i--) { AddConnectedPoints(characterPoints, new Point(midX, i), image, blacklistedPoints, minX, maxX, minY, maxY); } //Account for crazy gaps such as in % var foundNewPixels = false; do { foundNewPixels = false; var maxCharX = characterPoints.Max(p => p.X); for (int y = characterPoints.Where(p => p.X == maxCharX).Min(p => p.Y) + 1; y < minY + ((maxY - minY) * 0.75f); y++) { var origCount = characterPoints.Count; AddConnectedPoints(characterPoints, new Point(maxCharX, y), image, blacklistedPoints, minX, maxX, minY, maxY); if (characterPoints.Count > origCount) { foundNewPixels = true; } } } while (foundNewPixels); return(new List <Point>(characterPoints)); }
private static void AddConnectedPoints(CoordinateList existingPoints, Point firstPixel, ImageCache image, CoordinateList blacklistedPoints, int minX, int maxX, int minY, int maxY) { if (image[firstPixel.X, firstPixel.Y] <= 0 && firstPixel.X >= minX && firstPixel.X < maxX && firstPixel.Y >= minY && firstPixel.Y < maxY) { return; } var q = new Queue <Point>(); if (!existingPoints.Exists(firstPixel)) { existingPoints.Add(firstPixel); q.Enqueue(firstPixel); } while (q.Count > 0) { var n = q.Dequeue(); if (n.X + 1 <= maxX && image[n.X + 1, n.Y] > 0 && !existingPoints.Exists(n.X + 1, n.Y) && (blacklistedPoints == null || !blacklistedPoints.Exists(n.X + 1, n.Y))) { var np = new Point(n.X + 1, n.Y); existingPoints.Add(np); q.Enqueue(np); } if (n.X - 1 >= minX && image[n.X - 1, n.Y] > 0 && !existingPoints.Exists(n.X - 1, n.Y) && (blacklistedPoints == null || !blacklistedPoints.Exists(n.X - 1, n.Y))) { var np = new Point(n.X - 1, n.Y); existingPoints.Add(np); q.Enqueue(np); } if (n.Y - 1 >= minY && image[n.X, n.Y - 1] > 0 && !existingPoints.Exists(n.X, n.Y - 1) && (blacklistedPoints == null || !blacklistedPoints.Exists(n.X, n.Y - 1))) { var np = new Point(n.X, n.Y - 1); existingPoints.Add(np); q.Enqueue(np); } if (n.Y + 1 < maxY && image[n.X, n.Y + 1] > 0 && !existingPoints.Exists(n.X, n.Y + 1) && (blacklistedPoints == null || !blacklistedPoints.Exists(n.X, n.Y + 1))) { var np = new Point(n.X, n.Y + 1); existingPoints.Add(np); q.Enqueue(np); } } }
private List <TrainingSampleCharacter> TrainOnLine(char[] referenceCharacters, int xOffset, Rectangle chatRect, ImageCache image, int lineHeight, int lineOffset) { var startX = xOffset; var endX = xOffset; List <Point> targetCharacterPixels = null; var refIndex = 0; var results = new List <TrainingSampleCharacter>(); for (int x = xOffset; x < chatRect.Right; x++) { //Advance until next pixel var firstPixel = Point.Empty; for (int i = endX; i < chatRect.Right; i++) { var pixelFound = false; for (int y = lineOffset; y < lineOffset + lineHeight; y++) { if (image[i, y] > 0.3f) { x = i; pixelFound = true; firstPixel = new Point(i, y); break; } } if (pixelFound) { break; } } //Make sure we didn't escape if (x >= chatRect.Right || firstPixel == Point.Empty) { break; } startX = chatRect.Right; //targetCharacterPixels = OCRHelpers.FindCharacterPixelPoints(firstPixel, image, null, chatRect.Left, chatRect.Right, lineOffset, lineOffset + lineHeight); //var minX = targetCharacterPixels.Min(p => p.X); //var minY = targetCharacterPixels.Min(p => p.Y); //using (var image2 = new Image<Rgba32>(targetCharacterPixels.Max(p => p.X) - targetCharacterPixels.Min(p => p.X) + 1, targetCharacterPixels.Max(p => p.Y) - targetCharacterPixels.Min(p => p.Y) + 1)) //{ // for (int x2 = 0; x2 < image2.Width; x2++) // { // for (int y2 = 0; y2 < image2.Height; y2++) // { // var p = targetCharacterPixels.FirstOrDefault(p2 => p2.X == x2 + minX && p2.Y == y2 + minY); // if (p != null) // image2[x2, y2] = new Rgba32(image[p.X, p.Y], image[p.X, p.Y], image[p.X, p.Y]); // else // image2[x2, y2] = Rgba32.Black; // } // } // image2.Save("debug_target.png"); //} var target = OCRHelpers.FindCharacterMask(firstPixel, image, null, chatRect.Left, chatRect.Right, lineOffset, lineOffset + lineHeight); var mask = new float[target.Width, lineHeight]; for (int x2 = 0; x2 < target.Width; x2++) { for (int y2 = 0; y2 < lineHeight; y2++) { mask[x2, y2] = Math.Max(0, image[target.MinX + x2, y2 + lineOffset]); } } startX = Math.Min(startX, target.MinX); endX = Math.Max(endX, target.MaxX + 1); results.Add(new TrainingSampleCharacter() { Mask = mask, Width = endX - startX, Character = referenceCharacters[refIndex++] }); x = endX; } if (referenceCharacters.Length > refIndex) { throw new Exception("Length missmatch on training line"); } return(results); }