diff --git a/OCR_Decode/OcrImage.cs b/OCR_Decode/OcrImage.cs index d81878b..44b85d9 100644 --- a/OCR_Decode/OcrImage.cs +++ b/OCR_Decode/OcrImage.cs @@ -14,9 +14,10 @@ namespace OCR_Decode //Just so you know public class OcrImage { - Bitmap InputImage; - Random rnd = new Random(); - int salt = 0; + //this is a hardcoded value based on the colors of the F1TV data channel background you can change it if sometime in the future the color changes + //Any color that has any of its R,G or B channel higher than the treshold will be considered as being usefull information + public static Color F1TV_BACKGROUND_TRESHOLD = Color.FromArgb(0x50,0x50,0x50); + Bitmap InputBitmap; public enum WindowType { LapTime, @@ -25,70 +26,116 @@ namespace OCR_Decode Gap, Tyre, } - public OcrImage(Bitmap inputImage) + //For debugging purposes + public bool DumpDebugImages; + Random rnd = new Random(); + int salt = 0; + + /// + /// Create a new Ocr image to help enhance the given bitmap for OCR + /// + /// The image you want to enhance + public OcrImage(Bitmap inputBitmap) { - InputImage = inputImage; + InputBitmap = inputBitmap; + //Before turning this on check that the DEBUG_DUMP_FOLDER constant has been changed in the Reader.cs file + DumpDebugImages = false; + + //To help debugging salt = rnd.Next(0, 10000); } + /// + /// Enhances the image depending on wich type of window the image comes from + /// + /// The type of the window. Depending on it different enhancing features will be applied + /// public Bitmap Enhance(WindowType type = WindowType.Text) { - Bitmap result = (Bitmap)InputImage.Clone(); + Bitmap outputBitmap = (Bitmap)InputBitmap.Clone(); switch (type) { case WindowType.LapTime: - //result.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeBefore_" + salt + ".png"); - result = Tresholding(result, 185); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "LapTime1_" + salt + ".png"); - result = Resize(result, 2); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "LapTime2_" + salt + ".png"); - result = Dilatation(result, 1); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "LapTime3_" + salt + ".png"); - result = Erode(result, 1); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeAfter_" + salt + ".png"); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeBefore_" + salt + ".png"); + + outputBitmap = Tresholding(outputBitmap, 185); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeFilter1_" + salt + ".png"); + + outputBitmap = Resize(outputBitmap, 2); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeFilter2_" + salt + ".png"); + + outputBitmap = Dilatation(outputBitmap, 1); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeFilter3_" + salt + ".png"); + + outputBitmap = Erode(outputBitmap, 1); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "LapTimeAfter_" + salt + ".png"); break; case WindowType.Text: - //result.Save(Reader.DEBUG_DUMP_FOLDER + "TextBefore_" + salt + ".png"); - result = InvertColors(result); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "Text01_" + salt + ".png"); - result = Tresholding(result, 165); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "Text02_" + salt + ".png"); - result = Resize(result, 2); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "Text03_" + salt + ".png"); - result = Dilatation(result, 1); - //result.Save(Reader.DEBUG_DUMP_FOLDER + "TextAfter_" + salt + ".png"); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TextBefore_" + salt + ".png"); + + outputBitmap = InvertColors(outputBitmap); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TextFilter1_" + salt + ".png"); + + outputBitmap = Tresholding(outputBitmap, 165); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TextFilter2_" + salt + ".png"); + + outputBitmap = Resize(outputBitmap, 2); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TextFilter3_" + salt + ".png"); + + outputBitmap = Dilatation(outputBitmap, 1); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TextAfter_" + salt + ".png"); break; case WindowType.Tyre: - result.Save(Reader.DEBUG_DUMP_FOLDER + "tyreBefore_" + salt + ".png"); - result = RemoveUseless(result); - result.Save(Reader.DEBUG_DUMP_FOLDER + "tyre01_" + salt + ".png"); - result = Resize(result, 4); - result.Save(Reader.DEBUG_DUMP_FOLDER + "tyre02_" + salt + ".png"); - result = Dilatation(result, 1); - result.Save(Reader.DEBUG_DUMP_FOLDER + "tyreAfter_" + salt + ".png"); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TyreBefore_" + salt + ".png"); + + outputBitmap = RemoveUseless(outputBitmap); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TyreFilter01_" + salt + ".png"); + + outputBitmap = Resize(outputBitmap, 4); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TyreFilter02_" + salt + ".png"); + + outputBitmap = Dilatation(outputBitmap, 1); + if (DumpDebugImages) + outputBitmap.Save(Reader.DEBUG_DUMP_FOLDER + "TyreAfter_" + salt + ".png"); break; default: - result = Tresholding(result, 165); - result = Resize(result, 4); - result = Erode(result, 1); + outputBitmap = Tresholding(outputBitmap, 165); + outputBitmap = Resize(outputBitmap, 4); + outputBitmap = Erode(outputBitmap, 1); break; } - //result = Dilatation(result, 1); - return result; + return outputBitmap; } - public static Bitmap Grayscale(Bitmap input) + /// + /// Method that convert a colored RGB bitmap into a GrayScale image + /// + /// The Bitmap you want to convert + /// + public static Bitmap Grayscale(Bitmap inputBitmap) { - Bitmap bmp = input; - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - for (int y = 0; y < bmp.Height; y++) + for (int y = 0; y < inputBitmap.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); - for (int x = 0; x < bmp.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -96,30 +143,35 @@ namespace OCR_Decode byte green = pixel[1]; byte red = pixel[2]; + //Those a specific values to correct the weights so its more pleasing to the human eye int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11); pixel[0] = pixel[1] = pixel[2] = (byte)gray; } } } - bmp.UnlockBits(bmpData); + inputBitmap.UnlockBits(bmpData); - return bmp; + return inputBitmap; } - public static Bitmap Tresholding(Bitmap input, int threshold) + /// + /// Method that binaries the input image up to a certain treshold given + /// + /// the bitmap you want to convert to binary colors + /// The floor at wich the color is considered as white or black + /// + public static Bitmap Tresholding(Bitmap inputBitmap, int threshold) { - Bitmap bmp = input; - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - int bmpHeight = bmp.Height; - int bmpWidth = bmp.Width; + int bmpHeight = inputBitmap.Height; + int bmpWidth = inputBitmap.Width; Parallel.For(0, bmpHeight, y => - //for (int y = 0; y < bmpHeight; y++) { byte* currentLine = ptr + (y * bmpData.Stride); for (int x = 0; x < bmpWidth; x++) @@ -129,7 +181,7 @@ namespace OCR_Decode byte blue = pixel[0]; byte green = pixel[1]; byte red = pixel[2]; - + //Those a specific values to correct the weights so its more pleasing to the human eye int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11); int value = gray < threshold ? 0 : 255; @@ -137,25 +189,28 @@ namespace OCR_Decode } }); } - bmp.UnlockBits(bmpData); + inputBitmap.UnlockBits(bmpData); - return bmp; + return inputBitmap; } - public static Bitmap RemoveBG(Bitmap input) + /// + /// Method that removes the pixels that are flagged as background + /// + /// The bitmap you want to remove the background from + /// + public static Bitmap RemoveBG(Bitmap inputBitmap) { - Color limitColor = Color.FromArgb(0x50, 0x50, 0x50); - Bitmap bmp = input; - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - for (int y = 0; y < bmp.Height; y++) + for (int y = 0; y < inputBitmap.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); - for (int x = 0; x < bmp.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -163,28 +218,29 @@ namespace OCR_Decode int G = pixel[1]; int R = pixel[2]; - if (R <= limitColor.R && G <= limitColor.G && B <= limitColor.B) + if (R <= F1TV_BACKGROUND_TRESHOLD.R && G <= F1TV_BACKGROUND_TRESHOLD.G && B <= F1TV_BACKGROUND_TRESHOLD.B) pixel[0] = pixel[1] = pixel[2] = 0; } } } - bmp.UnlockBits(bmpData); + inputBitmap.UnlockBits(bmpData); - return bmp; + return inputBitmap; } - public unsafe static Bitmap RemoveUseless(Bitmap bmp) + /// + /// Method that removes all the useless things from the image and returns hopefully only the numbers + /// + /// The bitmap you want to remove useless things from (Expects a cropped part of the TyreWindow) + /// + public unsafe static Bitmap RemoveUseless(Bitmap inputBitmap) { - Random rnd = new Random(); - int salt = rnd.Next(0,1000); - - //bmp.Save(Reader.DEBUG_DUMP_FOLDER + "RemovedBG_"+salt+".png"); - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; - Color limitColor = Color.FromArgb(0x50,0x50,0x50); + //Note you can use something else than a cropped tyre window but I would recommend checking the code first to see if it fits your intended use + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - for (int y = 0; y < bmp.Height; y++) + for (int y = 0; y < inputBitmap.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); @@ -192,7 +248,7 @@ namespace OCR_Decode bool fromBorder = true; - for (int x = 0; x < bmp.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -200,7 +256,7 @@ namespace OCR_Decode int G = pixel[1]; int R = pixel[2]; - if (fromBorder && B < limitColor.B && G < limitColor.G && R < limitColor.R) + if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R) { pixelsToRemove.Add(x); } @@ -214,7 +270,7 @@ namespace OCR_Decode } } fromBorder = true; - for (int x = bmp.Width - 1; x > 0; x--) + for (int x = inputBitmap.Width - 1; x > 0; x--) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -222,7 +278,7 @@ namespace OCR_Decode int G = pixel[1]; int R = pixel[2]; - if (fromBorder && B < limitColor.B && G < limitColor.G && R < limitColor.R) + if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R) { pixelsToRemove.Add(x); } @@ -246,12 +302,11 @@ namespace OCR_Decode } } - - //NOW REMOVING THE COLOR - for (int y = 0; y < bmp.Height; y++) + //Removing the color parts + for (int y = 0; y < inputBitmap.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); - for (int x = 0; x < bmp.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -259,9 +314,7 @@ namespace OCR_Decode int G = pixel[1]; int R = pixel[2]; - //We remove the background pixels - - if (R >= limitColor.R + 15 || G >= limitColor.G + 15 || B >= limitColor.B + 15) + if (R >= F1TV_BACKGROUND_TRESHOLD.R + 15 || G >= F1TV_BACKGROUND_TRESHOLD.G + 15 || B >= F1TV_BACKGROUND_TRESHOLD.B + 15) { pixel[0] = 0xFF; pixel[1] = 0xFF; @@ -270,16 +323,19 @@ namespace OCR_Decode } } - bmp.UnlockBits(bmpData); - - return bmp; + inputBitmap.UnlockBits(bmpData); + return inputBitmap; } - public static Color GetAvgColorFromBitmap(Bitmap bmp) + /// + /// Recovers the average colors from the Image. NOTE : It wont take in account colors that are lower than the background + /// + /// The bitmap you want to get the average color from + /// + public static Color GetAvgColorFromBitmap(Bitmap inputBitmap) { - Color limitColor = Color.FromArgb(0x50, 0x50, 0x50); - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; int totR = 0; int totG = 0; @@ -290,10 +346,9 @@ namespace OCR_Decode unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - int bmpHeight = bmp.Height; - int bmpWidth = bmp.Width; + int bmpHeight = inputBitmap.Height; + int bmpWidth = inputBitmap.Width; Parallel.For(0, bmpHeight, y => - //for (int y = 0; y < bmp.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); for (int x = 0; x < bmpWidth; x++) @@ -304,9 +359,7 @@ namespace OCR_Decode int G = pixel[1]; int R = pixel[2]; - //We remove the background pixels - - if (R >= limitColor.R || G >= limitColor.G || B >= limitColor.B) + if (R >= F1TV_BACKGROUND_TRESHOLD.R || G >= F1TV_BACKGROUND_TRESHOLD.G || B >= F1TV_BACKGROUND_TRESHOLD.B) { totPixels++; totB += pixel[0]; @@ -316,24 +369,28 @@ namespace OCR_Decode } }); } - bmp.UnlockBits(bmpData); + inputBitmap.UnlockBits(bmpData); return Color.FromArgb(255, Convert.ToInt32((float)totR / (float)totPixels), Convert.ToInt32((float)totG / (float)totPixels), Convert.ToInt32((float)totB / (float)totPixels)); } - public static Bitmap InvertColors(Bitmap input) + /// + /// This method simply inverts all the colors in a Bitmap + /// + /// the bitmap you want to invert the colors from + /// + public static Bitmap InvertColors(Bitmap inputBitmap) { - Bitmap bmp = input; - Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); - int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; + Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height); + BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat); + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8; unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); - for (int y = 0; y < bmp.Height; y++) + for (int y = 0; y < inputBitmap.Height; y++) { byte* currentLine = ptr + (y * bmpData.Stride); - for (int x = 0; x < bmp.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { byte* pixel = currentLine + (x * bytesPerPixel); @@ -343,47 +400,47 @@ namespace OCR_Decode } } } - bmp.UnlockBits(bmpData); + inputBitmap.UnlockBits(bmpData); - return bmp; + return inputBitmap; } - public static Bitmap ApplyGaussianBlur(Bitmap input, int radius) + /// + /// Methods that applies Bicubic interpolation to increase the size and resolution of an image + /// + /// The bitmap you want to resize + /// The factor of resizing you want to use. I recommend using even numbers + /// + public static Bitmap Resize(Bitmap inputBitmap, int resizeFactor) { - GaussianBlur filter = new GaussianBlur(radius); - Bitmap output = filter.Apply(input); - return output; - } - public static Bitmap Resize(Bitmap sourceBitmap, int amount) - { - // Create a new Bitmap object to hold the resized image - var resultBitmap = new Bitmap(sourceBitmap.Width * amount, sourceBitmap.Height * amount); + var resultBitmap = new Bitmap(inputBitmap.Width * resizeFactor, inputBitmap.Height * resizeFactor); - // Create a Graphics object to draw the resized image using (var graphics = Graphics.FromImage(resultBitmap)) { - // Set the interpolation mode to high-quality bicubic graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - - // Draw the resized image using the Graphics object - graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height)); + graphics.DrawImage(inputBitmap, new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height)); } return resultBitmap; } - public static Bitmap HighlightContours(Bitmap input) + /// + /// method that Highlights the countours of a Bitmap + /// + /// The bitmap you want to highlight the countours of + /// + public static Bitmap HighlightContours(Bitmap inputBitmap) { - Bitmap output = new Bitmap(input.Width, input.Height); + Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height); - Bitmap grayscale = Grayscale(input); + Bitmap grayscale = Grayscale(inputBitmap); Bitmap thresholded = Tresholding(grayscale, 128); Bitmap dilated = Dilatation(thresholded, 3); Bitmap eroded = Erode(dilated, 3); - for (int y = 0; y < input.Height; y++) + for (int y = 0; y < inputBitmap.Height; y++) { - for (int x = 0; x < input.Width; x++) + for (int x = 0; x < inputBitmap.Width; x++) { - Color pixel = input.GetPixel(x, y); + Color pixel = inputBitmap.GetPixel(x, y); Color dilatedPixel = dilated.GetPixel(x, y); Color erodedPixel = eroded.GetPixel(x, y); @@ -392,24 +449,30 @@ namespace OCR_Decode if (gray > threshold) { - output.SetPixel(x, y, Color.FromArgb(255, 255, 255)); + outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255)); } else if (gray <= threshold && erodedPixel.R == 0) { - output.SetPixel(x, y, Color.FromArgb(255, 0, 0)); + outputBitmap.SetPixel(x, y, Color.FromArgb(255, 0, 0)); } else { - output.SetPixel(x, y, Color.FromArgb(0, 0, 0)); + outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0)); } } } - return output; + return outputBitmap; } - public static Bitmap Erode(Bitmap input, int kernelSize) + /// + /// Method that that erodes the morphology of a bitmap + /// + /// The bitmap you want to erode + /// The amount of Erosion you want (be carefull its expensive on ressources) + /// + public static Bitmap Erode(Bitmap inputBitmap, int kernelSize) { - Bitmap output = new Bitmap(input.Width, input.Height); + Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height); int[,] kernel = new int[kernelSize, kernelSize]; @@ -421,9 +484,9 @@ namespace OCR_Decode } } - for (int y = kernelSize / 2; y < input.Height - kernelSize / 2; y++) + for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++) { - for (int x = kernelSize / 2; x < input.Width - kernelSize / 2; x++) + for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++) { bool flag = true; @@ -431,7 +494,7 @@ namespace OCR_Decode { for (int j = -kernelSize / 2; j <= kernelSize / 2; j++) { - Color pixel = input.GetPixel(x + i, y + j); + Color pixel = inputBitmap.GetPixel(x + i, y + j); int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11); if (gray >= 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1) @@ -449,21 +512,26 @@ namespace OCR_Decode if (flag) { - output.SetPixel(x, y, Color.FromArgb(255, 255, 255)); + outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255)); } else { - output.SetPixel(x, y, Color.FromArgb(0, 0, 0)); + outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0)); } } } - return output; + return outputBitmap; } - - public static Bitmap Dilatation(Bitmap input, int kernelSize) + /// + /// Method that that use dilatation of the morphology of a bitmap + /// + /// The bitmap you want to use dilatation on + /// The amount of dilatation you want (be carefull its expensive on ressources) + /// + public static Bitmap Dilatation(Bitmap inputBitmap, int kernelSize) { - Bitmap output = new Bitmap(input.Width, input.Height); + Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height); int[,] kernel = new int[kernelSize, kernelSize]; @@ -475,9 +543,9 @@ namespace OCR_Decode } } - for (int y = kernelSize / 2; y < input.Height - kernelSize / 2; y++) + for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++) { - for (int x = kernelSize / 2; x < input.Width - kernelSize / 2; x++) + for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++) { bool flag = false; @@ -485,7 +553,7 @@ namespace OCR_Decode { for (int j = -kernelSize / 2; j <= kernelSize / 2; j++) { - Color pixel = input.GetPixel(x + i, y + j); + Color pixel = inputBitmap.GetPixel(x + i, y + j); int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11); if (gray < 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1) @@ -503,16 +571,16 @@ namespace OCR_Decode if (flag) { - output.SetPixel(x, y, Color.FromArgb(0, 0, 0)); + outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0)); } else { - output.SetPixel(x, y, Color.FromArgb(255, 255, 255)); + outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255)); } } } - return output; + return outputBitmap; } }