using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using Emgu.CV.Structure; using Emgu.CV; using Emgu.CV.OCR; namespace TestVideo { internal class Zone { [Flags] public enum ZoneType { Standings, Gaps, LastLapPace } private ZoneType _type; private Rectangle _zoneArea; private Bitmap _zoneData; private string _rawText; private string[] _cleanText; private string _name; private ZoneType Type { get => _type; set => _type = value; } public Rectangle ZoneArea { get => _zoneArea; private set => _zoneArea = value; } public Bitmap ZoneData { get => _zoneData; private set => _zoneData = value; } public string RawText { get => _rawText; private set => _rawText = value; } public string[] CleanText { get => _cleanText; private set => _cleanText = value; } public string Name { get => _name; private set => _name = value; } public Zone(Rectangle area, ZoneType type, string name) { ZoneArea = area; Type = type; Name = name; } public void Update(Bitmap data) { ZoneData = data; RawText = GetRawText(ZoneData); CleanText = GetCleanText(RawText); } //Original method : http://leonwoo-tech.blogspot.com/2018/06/tip-how-to-properly-setup-opencv-ocr-to.html private string GetRawText(Bitmap inputBmp) { string result = ""; string tesseractResult = Tesseract(inputBmp); string[] lettersData = tesseractResult.Split('\n'); using (Graphics g = Graphics.FromImage(inputBmp)) { foreach (string letterData in lettersData) { string[] data = letterData.Split(' '); //This data is in a format that we cant process if (data.Length != 6) break; string letter = data[0]; Point position = new Point(Convert.ToInt32(data[1]), Convert.ToInt32(data[2])); Size size = new Size(Convert.ToInt32(data[3]), Convert.ToInt32(data[4])); int unknownData = Convert.ToInt32(data[5]); //A neat post processing Idea would be to separate letters that have a unusually big difference in X or Y axis to try and recognise words //Use the data result += letter; g.DrawRectangle(new Pen(Brushes.Red, 5), new Rectangle(position, size)); } } return result; } private string[] GetCleanText(string rawText) { //TODO return new string[] { rawText }; } private string Tesseract(Bitmap inputBmp) { string result = ""; //To use this toImage you need : NuGet\Install-Package Emgu.CV.Bitmap -Version 4.5.5.4823 inputBmp = PrepareImage(inputBmp); ZoneData = inputBmp; Image emguImage = inputBmp.ToImage(); using (var image = emguImage) { using (Tesseract tesseractOcrProvider = new Tesseract(AppDomain.CurrentDomain.BaseDirectory + "\\Data", "eng", OcrEngineMode.Default)) { tesseractOcrProvider.SetImage(image); tesseractOcrProvider.Recognize(); result = tesseractOcrProvider.GetBoxText().TrimEnd(); } } return result; } private Bitmap PrepareImage(Bitmap inputImage) { for (int y = 0; y < inputImage.Height; y++) { for (int x = 0; x < inputImage.Width; x++) { //We transform the RGB image into a Grayscale one //Grayscale = 0.299R + 0.587G + 0.114B Color color = inputImage.GetPixel(x, y); int grayScaleValue = Convert.ToInt32(0.299 * (float)color.R + 0.587 * (float)color.G + 0.114 * (float)color.B); int finalValue = 0; //Then we make it boolean, either black or white if (grayScaleValue > 255 / 2) finalValue = 255; inputImage.SetPixel(x, y, Color.FromArgb(finalValue, finalValue, finalValue)); } } //inputImage.Save("C:/TEST/test.png",ImageFormat.Png); return inputImage; } } }