Added a lot to the doc and modified the pdf generation

This commit is contained in:
2023-06-02 13:41:12 +02:00
parent bef8b9d635
commit a368e02453
113 changed files with 54217 additions and 17276 deletions
+148 -14
View File
@@ -1,8 +1,8 @@
/// Author : Maxime Rohmer
/// Date : 08/05/2023
/// Date : 30/05/2023
/// File : OcrImage.cs
/// Brief : Class containing all the methods used to enhance images for OCR
/// Version : 0.1
/// Version : Alpha 1.0
using System;
using System.Collections.Generic;
@@ -11,7 +11,7 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace Test_Merge
namespace TrackTrends
{
public class OcrImage
{
@@ -44,28 +44,57 @@ namespace Test_Merge
public Bitmap Enhance(WindowType type = WindowType.Text)
{
Bitmap outputBitmap = (Bitmap)InputBitmap.Clone();
//Note : If you plan to activate all the comments that I used to debug the OCR I would advise to make sure that the debug folder exists
switch (type)
{
case WindowType.LapTime:
outputBitmap = Tresholding(outputBitmap, 185);
case WindowType.Gap:
//outputBitmap.Save(Window.GAPTOLEADER_DEBUG_FOLDER + @"\raw_" + id + ".png");
outputBitmap = Tresholding(outputBitmap, 165);
//outputBitmap.Save(Window.GAPTOLEADER_DEBUG_FOLDER + @"\treshold_" + id + ".png");
outputBitmap = Resize(outputBitmap, 2);
//outputBitmap.Save(Window.GAPTOLEADER_DEBUG_FOLDER + @"\resize_" + id + ".png");
outputBitmap = Dilatation(outputBitmap, 1);
outputBitmap = Erode(outputBitmap, 1);
//outputBitmap.Save(Window.GAPTOLEADER_DEBUG_FOLDER + @"\Final_dilatation_" + id + ".png");
break;
case WindowType.Sector:
//outputBitmap.Save(Window.SECTOR1_DEBUG_FOLDER + @"\raw_" + id + ".png");
outputBitmap = VanishOxyAction(outputBitmap);
//outputBitmap.Save(Window.SECTOR1_DEBUG_FOLDER + @"\vanish_" + id + ".png");
outputBitmap = Tresholding(outputBitmap, 150);
//outputBitmap.Save(Window.SECTOR1_DEBUG_FOLDER + @"\Final_treshold_" + id + ".png");
break;
case WindowType.LapTime:
//outputBitmap.Save(Window.LAPTIME_DEBUG_FOLDER + @"\raw_" + id + ".png");
outputBitmap = Tresholding(outputBitmap,185);
//outputBitmap.Save(Window.LAPTIME_DEBUG_FOLDER + @"\Treshold_" + id + ".png");
outputBitmap = SobelEdgeDetection(outputBitmap);
//outputBitmap.Save(Window.LAPTIME_DEBUG_FOLDER + @"\SobelDetection_" + id + ".png");
break;
case WindowType.Text:
outputBitmap = InvertColors(outputBitmap);
//outputBitmap.Save(Window.STRING_DEBUG_FOLDER + @"\raw_" + id + ".png");
outputBitmap = Tresholding(outputBitmap, 165);
outputBitmap = Resize(outputBitmap, 2);
outputBitmap = Dilatation(outputBitmap, 1);
//outputBitmap.Save(Window.STRING_DEBUG_FOLDER + @"\Final_treshold_" + id + ".png");
break;
case WindowType.Tyre:
//outputBitmap.Save(Window.TYRE_DEBUG_FOLDER + @"\raw_" + id + ".png");
outputBitmap = RemoveUseless(outputBitmap);
outputBitmap = Resize(outputBitmap, 4);
//outputBitmap.Save(Window.TYRE_DEBUG_FOLDER + @"\uselessRemoved_" + id + ".png");
outputBitmap = Dilatation(outputBitmap, 1);
//outputBitmap.Save(Window.TYRE_DEBUG_FOLDER + @"\Final_dilatation_" + id + ".png");
break;
default:
outputBitmap = Tresholding(outputBitmap, 165);
outputBitmap = Resize(outputBitmap, 4);
outputBitmap = Resize(outputBitmap, 2);
outputBitmap = Erode(outputBitmap, 1);
break;
}
@@ -99,7 +128,112 @@ namespace Test_Merge
//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;
//This is not a proper treshold method but it is helping the sobel edge detection
if(gray <= F1TV_BACKGROUND_TRESHOLD.R)
{
pixel[0] = pixel[1] = pixel[2] = 0;
}
else
{
pixel[0] = pixel[1] = pixel[2] = (byte)gray;
}
}
}
}
inputBitmap.UnlockBits(bmpData);
return inputBitmap;
}
/// <summary>
/// Method that uses the Sobel Edge detection to outline the edges of the characters to help with the OCR
/// </summary>
/// <param name="grayscaleImage">The image with the sobel edge detection used</param>
/// <returns></returns>
private Bitmap SobelEdgeDetection(Bitmap grayscaleImage)
{
// Create a new bitmap for the edges
Bitmap edgesImage = new Bitmap(grayscaleImage.Width, grayscaleImage.Height);
// Define the Sobel operators
// Its just a matrix that we will use on the all image
int[,] sobelX = { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };
int[,] sobelY = { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } };
// Apply the Sobel operators and normalize the gradients
// NOTE: I dont know how easy or hard it would be to make this paralel but it could be a good idea to do so if possible.
for (int y = 1; y < grayscaleImage.Height - 1; y++)
{
for (int x = 1; x < grayscaleImage.Width - 1; x++)
{
int gradientX = CalculateGradient(grayscaleImage, sobelX, x, y);
int gradientY = CalculateGradient(grayscaleImage, sobelY, x, y);
int gradient = (int)Math.Sqrt(gradientX * gradientX + gradientY * gradientY);
// Normalize the gradient value
// In some rare cases the value can exceed 255 so we limit it with the Math.Min method
gradient = Math.Min(255, Math.Max(0, gradient));
edgesImage.SetPixel(x, y, Color.FromArgb(gradient, gradient, gradient));
}
}
return edgesImage;
}
/// <summary>
/// Method that's here to be used by the sobel edge detection method (Chat GPT has been used for parts of this method)
/// </summary>
/// <param name="grayscaleImage">The input image with the grayscale processing already done</param>
/// <param name="sobelOperator">The matrix to apply</param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>Returns the processed gradient</returns>
private int CalculateGradient(Bitmap grayscaleImage, int[,] sobelOperator, int x, int y)
{
int gradient = 0;
for (int j = -1; j <= 1; j++)
{
for (int i = -1; i <= 1; i++)
{
int pixelX = grayscaleImage.GetPixel(x + i, y + j).R;
gradient += sobelOperator[j + 1, i + 1] * pixelX;
}
}
return gradient;
}
/// <summary>
/// Method that is used to whiten an image. Ignore the funny name. Its used to prevent colored text to trouble the OCR when it uses grayscaling
/// </summary>
/// <param name="inputBitmap">The bitmap to vanish</param>
/// <returns></returns>
public static Bitmap VanishOxyAction(Bitmap inputBitmap)
{
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
{
//Note : MAKE THIS PARALELL OMG WY DID I LEFT IT LIKE THAT
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
for (int y = 0; y < inputBitmap.Height; y++)
{
byte* currentLine = ptr + (y * bmpData.Stride);
for (int x = 0; x < inputBitmap.Width; x++)
{
byte* pixel = currentLine + (x * bytesPerPixel);
int blue = (int)pixel[0];
int green = (int)pixel[1];
int red = (int)pixel[2];
int max = Math.Max(Math.Max(blue, green), red);
if (max > 255 / 3)
max = 255;
pixel[0] = pixel[1] = pixel[2] = (byte)max;
}
}
}
@@ -267,7 +401,7 @@ namespace Test_Merge
int G = pixel[1];
int R = pixel[2];
if (R >= F1TV_BACKGROUND_TRESHOLD.R + 15 || G >= F1TV_BACKGROUND_TRESHOLD.G + 15 || B >= F1TV_BACKGROUND_TRESHOLD.B + 15)
if (R >= F1TV_BACKGROUND_TRESHOLD.R +25|| G >= F1TV_BACKGROUND_TRESHOLD.G +25|| B >= F1TV_BACKGROUND_TRESHOLD.B +25)
{
pixel[0] = 0xFF;
pixel[1] = 0xFF;
@@ -324,7 +458,7 @@ namespace Test_Merge
}
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));
return Color.FromArgb(255,Math.Min(Convert.ToInt32((float)totR / (float)totPixels),255), Math.Min(Convert.ToInt32((float)totG / (float)totPixels),255), Math.Min(Convert.ToInt32((float)totB / (float)totPixels),255));
}
/// <summary>
/// This method simply inverts all the colors in a Bitmap