From f0f78e81f9c803b7bd50bb08c1296c5604acd0ca Mon Sep 17 00:00:00 2001 From: maxluli Date: Wed, 19 Oct 2022 16:14:02 +0200 Subject: [PATCH] Just everything is better --- TestVideo/EnumExtensions.cs | 101 +++++++++++++++++ TestVideo/Extraction.cs | 156 +++++++++++++++++++++++++++ TestVideo/Form1.Designer.cs | 132 +++++++++++++++++++++-- TestVideo/Form1.cs | 210 +++++++++++++++--------------------- TestVideo/TestVideo.csproj | 3 + TestVideo/Zone.cs | 120 +++++++++++++++++++++ 6 files changed, 589 insertions(+), 133 deletions(-) create mode 100644 TestVideo/EnumExtensions.cs create mode 100644 TestVideo/Extraction.cs create mode 100644 TestVideo/Zone.cs diff --git a/TestVideo/EnumExtensions.cs b/TestVideo/EnumExtensions.cs new file mode 100644 index 0000000..5076047 --- /dev/null +++ b/TestVideo/EnumExtensions.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TestVideo +{ + public static class EnumExtensions + { + /// + /// Gets all items for an enum value. + /// + /// + /// The value. + /// + public static IEnumerable GetAllItems(this Enum value) + { + foreach (object item in Enum.GetValues(typeof(T))) + { + yield return (T)item; + } + } + + /// + /// Gets all items for an enum type. + /// + /// + /// The value. + /// + public static IEnumerable GetAllItems() where T : struct + { + foreach (object item in Enum.GetValues(typeof(T))) + { + yield return (T)item; + } + } + + /// + /// Gets all combined items from an enum value. + /// + /// + /// The value. + /// + /// + /// Displays ValueA and ValueB. + /// + /// EnumExample dummy = EnumExample.Combi; + /// foreach (var item in dummy.GetAllSelectedItems()) + /// { + /// Console.WriteLine(item); + /// } + /// + /// + public static IEnumerable GetAllSelectedItems(this Enum value) + { + int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture); + + foreach (object item in Enum.GetValues(typeof(T))) + { + int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture); + + if (itemAsInt == (valueAsInt & itemAsInt)) + { + yield return (T)item; + } + } + } + + /// + /// Determines whether the enum value contains a specific value. + /// + /// The value. + /// The request. + /// + /// true if value contains the specified value; otherwise, false. + /// + /// + /// + /// EnumExample dummy = EnumExample.Combi; + /// if (dummy.Contains(EnumExample.ValueA)) + /// { + /// Console.WriteLine("dummy contains EnumExample.ValueA"); + /// } + /// + /// + public static bool Contains(this Enum value, T request) + { + int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture); + int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture); + + if (requestAsInt == (valueAsInt & requestAsInt)) + { + return true; + } + + return false; + } + } +} diff --git a/TestVideo/Extraction.cs b/TestVideo/Extraction.cs new file mode 100644 index 0000000..6cd4758 --- /dev/null +++ b/TestVideo/Extraction.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace TestVideo +{ + internal class Extraction + { + private List _zones; + private Screen _currentScreen; + private Bitmap _screenPreview; + + public Screen CurrentScreen { get => _currentScreen; set => _currentScreen = value; } + public List Zones { get => _zones; private set => _zones = value; } + public Bitmap ScreenPreview { get => _screenPreview; set => _screenPreview = value; } + + public Extraction(Screen screen) + { + CurrentScreen = screen; + } + public Extraction(List zones) + { + Zones = zones; + } + + public void UpdateZones() + { + ScreenPreview = ScreenShot(); + DrawZones(); + foreach (Zone zone in Zones) + { + Bitmap bmpData = ScreenPreview.Clone(zone.ZoneArea, ScreenPreview.PixelFormat); + zone.Update(bmpData); + } + } + public void ChangeScreen(Screen newScreen) + { + if (newScreen != CurrentScreen) + CurrentScreen = newScreen; + + //This makes sure that if you go from a screen with smaller dimensions only the zones that are valid for it stays + List newZones = new List(); + foreach (Zone zone in newZones) + { + if (IsZoneInBounds(zone.ZoneArea)) + newZones.Add(zone); + } + Zones = newZones; + + ScreenPreview = ScreenShot(); + } + public List GetZonesNames() + { + List zoneNames = new List(); + foreach (Zone zone in Zones) + { + zoneNames.Add(zone.Name); + } + return zoneNames; + } + public void AddZone(Rectangle zoneArea,Zone.ZoneType type,string name) + { + if (!IsZoneInBounds(zoneArea)) + throw new ArgumentException("Rectangle is outside the screen"); + + Zones.Add(new Zone(zoneArea,type,name)); + } + public void RemoveZone(int idZone) + { + Zones.RemoveAt(idZone); + } + + public Rectangle GetZoneArea(int idZone) + { + return Zones[idZone].ZoneArea; + } + + public Bitmap GetZoneData(int idZone) + { + return Zones[idZone].ZoneData; + } + + public string GetZoneRawText(int idZone) + { + return Zones[idZone].RawText; + } + public string[] GetZonesCleanText(int idZone) + { + return Zones[idZone].CleanText; + } + private Bitmap ScreenShot() + { + Bitmap screenshot; + screenshot = new Bitmap(CurrentScreen.Bounds.Width, CurrentScreen.Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + // Create a graphics object from the bitmap + Graphics gfxScreenshot = Graphics.FromImage(screenshot); + // Take the screenshot from the upper left corner to the right bottom corner + gfxScreenshot.CopyFromScreen( + CurrentScreen.Bounds.X, + CurrentScreen.Bounds.Y, + 0, + 0, + CurrentScreen.Bounds.Size, + CopyPixelOperation.SourceCopy); + return screenshot; + } + public void DrawZones() + { + using (Graphics g = Graphics.FromImage(ScreenPreview)) + { + foreach (Zone zone in Zones) + { + g.DrawRectangle(new Pen(Color.Red,3),zone.ZoneArea); + } + } + } + private string SaveScreenshot(Bitmap image) + { + //This method is now quite old. If you plan to use it I would recommand rewriting it + string path = ""; + string directory = AppDomain.CurrentDomain.BaseDirectory + "Screens"; + path = directory + "\\Screenshot" + DateTime.Now.ToString("yyyy_MM_dd-hh_mm_ss") + ".png"; + if (Directory.Exists(directory)) + { + image.Save(path, ImageFormat.Png); + } + else + { + Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Screens"); + } + return path; + } + private bool IsZoneInBounds(Rectangle zoneArea) + { + bool result = true; + //Check that the position of the zone is possible + if (zoneArea.X < 0 || zoneArea.X >= CurrentScreen.Bounds.Width) + result = false; + if (zoneArea.Y < 0 || zoneArea.Y >= CurrentScreen.Bounds.Width) + result = false; + //Check that the zone does'nt go outside the bounds of the Screen + if (zoneArea.X + zoneArea.Width >= CurrentScreen.Bounds.Width) + result = false; + if (zoneArea.Y + zoneArea.Height >= CurrentScreen.Bounds.Height) + result = false; + + return result; + } + } +} diff --git a/TestVideo/Form1.Designer.cs b/TestVideo/Form1.Designer.cs index 3d5310b..600f646 100644 --- a/TestVideo/Form1.Designer.cs +++ b/TestVideo/Form1.Designer.cs @@ -35,6 +35,15 @@ this.tmrScreenshots = new System.Windows.Forms.Timer(this.components); this.lsbScreens = new System.Windows.Forms.ListBox(); this.tbxResult = new System.Windows.Forms.TextBox(); + this.lsbZones = new System.Windows.Forms.ListBox(); + this.btnCreateZone = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.lsbZoneTypes = new System.Windows.Forms.ListBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.pbxInput)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pbxOutput)).BeginInit(); this.SuspendLayout(); @@ -43,14 +52,15 @@ // this.pbxInput.Location = new System.Drawing.Point(12, 12); this.pbxInput.Name = "pbxInput"; - this.pbxInput.Size = new System.Drawing.Size(480, 270); + this.pbxInput.Size = new System.Drawing.Size(960, 540); this.pbxInput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.pbxInput.TabIndex = 0; this.pbxInput.TabStop = false; + this.pbxInput.Click += new System.EventHandler(this.pbxInput_Click); // // pbxOutput // - this.pbxOutput.Location = new System.Drawing.Point(12, 288); + this.pbxOutput.Location = new System.Drawing.Point(978, 12); this.pbxOutput.Name = "pbxOutput"; this.pbxOutput.Size = new System.Drawing.Size(480, 270); this.pbxOutput.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; @@ -59,11 +69,11 @@ // // btnStart // - this.btnStart.Location = new System.Drawing.Point(495, 245); + this.btnStart.Location = new System.Drawing.Point(818, 425); this.btnStart.Name = "btnStart"; - this.btnStart.Size = new System.Drawing.Size(157, 37); + this.btnStart.Size = new System.Drawing.Size(154, 37); this.btnStart.TabIndex = 2; - this.btnStart.Text = "Start"; + this.btnStart.Text = "Start recording"; this.btnStart.UseVisualStyleBackColor = true; this.btnStart.Click += new System.EventHandler(this.btnStart_Click); // @@ -76,32 +86,123 @@ // this.lsbScreens.FormattingEnabled = true; this.lsbScreens.ItemHeight = 16; - this.lsbScreens.Location = new System.Drawing.Point(498, 12); + this.lsbScreens.Location = new System.Drawing.Point(818, 468); this.lsbScreens.Name = "lsbScreens"; - this.lsbScreens.Size = new System.Drawing.Size(154, 228); + this.lsbScreens.Size = new System.Drawing.Size(154, 84); this.lsbScreens.TabIndex = 3; this.lsbScreens.SelectedIndexChanged += new System.EventHandler(this.lsbScreens_SelectedIndexChanged); // // tbxResult // - this.tbxResult.Location = new System.Drawing.Point(498, 288); + this.tbxResult.Location = new System.Drawing.Point(12, 581); this.tbxResult.Multiline = true; this.tbxResult.Name = "tbxResult"; this.tbxResult.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.tbxResult.Size = new System.Drawing.Size(147, 270); + this.tbxResult.Size = new System.Drawing.Size(480, 190); this.tbxResult.TabIndex = 4; // + // lsbZones + // + this.lsbZones.FormattingEnabled = true; + this.lsbZones.ItemHeight = 16; + this.lsbZones.Location = new System.Drawing.Point(978, 304); + this.lsbZones.Name = "lsbZones"; + this.lsbZones.Size = new System.Drawing.Size(225, 100); + this.lsbZones.TabIndex = 5; + this.lsbZones.SelectedIndexChanged += new System.EventHandler(this.lsbZones_SelectedIndexChanged); + // + // btnCreateZone + // + this.btnCreateZone.Location = new System.Drawing.Point(978, 410); + this.btnCreateZone.Name = "btnCreateZone"; + this.btnCreateZone.Size = new System.Drawing.Size(482, 37); + this.btnCreateZone.TabIndex = 6; + this.btnCreateZone.Text = "Create Zone"; + this.btnCreateZone.UseVisualStyleBackColor = true; + this.btnCreateZone.Click += new System.EventHandler(this.btnCreateZone_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(978, 453); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(482, 37); + this.button2.TabIndex = 7; + this.button2.Text = "Delete Zone"; + this.button2.UseVisualStyleBackColor = true; + // + // lsbZoneTypes + // + this.lsbZoneTypes.FormattingEnabled = true; + this.lsbZoneTypes.ItemHeight = 16; + this.lsbZoneTypes.Location = new System.Drawing.Point(1233, 304); + this.lsbZoneTypes.Name = "lsbZoneTypes"; + this.lsbZoneTypes.Size = new System.Drawing.Size(225, 100); + this.lsbZoneTypes.TabIndex = 8; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(978, 285); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(45, 16); + this.label1.TabIndex = 9; + this.label1.Text = "Zones"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(1230, 285); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(74, 16); + this.label2.TabIndex = 10; + this.label2.Text = "Zone types"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(12, 555); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(69, 16); + this.label3.TabIndex = 11; + this.label3.Text = "Raw result"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(492, 581); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.textBox1.Size = new System.Drawing.Size(480, 190); + this.textBox1.TabIndex = 12; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(489, 555); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(104, 16); + this.label4.TabIndex = 13; + this.label4.Text = "Computed result"; + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(657, 565); + this.ClientSize = new System.Drawing.Size(1472, 783); + this.Controls.Add(this.label4); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.lsbZoneTypes); + this.Controls.Add(this.button2); + this.Controls.Add(this.btnCreateZone); + this.Controls.Add(this.lsbZones); this.Controls.Add(this.tbxResult); this.Controls.Add(this.lsbScreens); this.Controls.Add(this.btnStart); this.Controls.Add(this.pbxOutput); this.Controls.Add(this.pbxInput); - this.Enabled = false; this.Name = "Form1"; this.Text = "Form1"; ((System.ComponentModel.ISupportInitialize)(this.pbxInput)).EndInit(); @@ -119,6 +220,15 @@ private System.Windows.Forms.Timer tmrScreenshots; private System.Windows.Forms.ListBox lsbScreens; private System.Windows.Forms.TextBox tbxResult; + private System.Windows.Forms.ListBox lsbZones; + private System.Windows.Forms.Button btnCreateZone; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ListBox lsbZoneTypes; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label4; } } diff --git a/TestVideo/Form1.cs b/TestVideo/Form1.cs index 9adb5e8..1b25412 100644 --- a/TestVideo/Form1.cs +++ b/TestVideo/Form1.cs @@ -18,15 +18,21 @@ namespace TestVideo public partial class Form1 : Form { public Screen[] screens; - Screen currentScreen; List screenNames; + Extraction extraction; + int currentZoneIndex; + + List zoneTypes; + bool creatingZone; + Point[] newZonePoints; - Image displayedImage = null; public Form1() { InitializeComponent(); screens = Screen.AllScreens; - currentScreen = screens[0]; + extraction = new Extraction(screens[0]); + currentZoneIndex = -1; + screenNames = new List(); foreach (Screen scr in screens) { @@ -34,150 +40,110 @@ namespace TestVideo } lsbScreens.DataSource = screenNames; - //TESTING TESSERACT - - //string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\Baneer.png"; - //string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\Test.png"; - //string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\Standings.png"; - //string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\Gaps.png"; - //string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\SectorTimes.png"; - string path = AppDomain.CurrentDomain.BaseDirectory + "Screens\\Standings2.png"; - - tbxResult.Text = DecodeTessereactResults(testTesseract((Bitmap)Image.FromFile(path)), Image.FromFile(path), pbxOutput); - } - private Bitmap PrepareImage(Bitmap inputImage) - { - for (int y = 0; y < inputImage.Height; y++) + zoneTypes = new List(); + foreach (object type in Enum.GetValues(typeof(Zone.ZoneType))) { - for (int x = 0; x < inputImage.Width; x++) - { - //We will apply a filter to put the image first in grayScale - //Then if the pixel is more white than black it will be fully white and same for black - - //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; - if (grayScaleValue > 255 / 2) - finalValue = 255; - inputImage.SetPixel(x, y, Color.FromArgb(finalValue, finalValue, finalValue)); - } + zoneTypes.Add((Zone.ZoneType)type); } - //inputImage.Save("C:/TEST/test.png",ImageFormat.Png); - return inputImage; - } - private string DecodeTessereactResults(string tesseractResult, Image inputImage, PictureBox resultPbx) - { - MessageBox.Show(tesseractResult); - string result = ""; - string[] lettersData = tesseractResult.Split('\n'); - using (Graphics g = Graphics.FromImage(inputImage)) - { - 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)); - } - } - - resultPbx.Image = inputImage; - - return result; + lsbZoneTypes.DataSource = zoneTypes; + + newZonePoints = new Point[2] {new Point(-1,-1), new Point(-1,-1)}; } + private void btnStart_Click(object sender, EventArgs e) { if (tmrScreenshots.Enabled) { tmrScreenshots.Enabled = false; - btnStart.Text = "Start"; + btnStart.Text = "Start recording"; } else { tmrScreenshots.Enabled = true; - btnStart.Text = "Stop"; + btnStart.Text = "Stop recording"; } } - private Bitmap ScreenShot() - { - Bitmap screenshot; - screenshot = new Bitmap(currentScreen.Bounds.Width, currentScreen.Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - // Create a graphics object from the bitmap - Graphics gfxScreenshot = Graphics.FromImage(screenshot); - // Take the screenshot from the upper left corner to the right bottom corner - gfxScreenshot.CopyFromScreen( - currentScreen.Bounds.X, - currentScreen.Bounds.Y, - 0, - 0, - currentScreen.Bounds.Size, - CopyPixelOperation.SourceCopy); - //testTesseract(screenshot); - //SaveScreenshot(screenshot); - MessageBox.Show(testTesseract(screenshot)); - return screenshot; - } - private string SaveScreenshot(Bitmap image) + public void RefreshUi() { - string path = ""; - string directory = AppDomain.CurrentDomain.BaseDirectory + "Screens"; - path = directory + "\\Screenshot" + DateTime.Now.ToString("yyyy_MM_dd-hh_mm_ss") + ".png"; - if (Directory.Exists(directory)) - { - image.Save(path, ImageFormat.Png); - } - else - { - Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Screens"); - } - return path; - } - //http://leonwoo-tech.blogspot.com/2018/06/tip-how-to-properly-setup-opencv-ocr-to.html - private string testTesseract(Bitmap inputBmp) - { - string result = ""; - //To use this toImage you need : NuGet\Install-Package Emgu.CV.Bitmap -Version 4.5.5.4823 - inputBmp = PrepareImage(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(); - } - } - //File.Delete(filePath); - return result; + lsbZones.DataSource = extraction.GetZonesNames(); + extraction.DrawZones(); + //extraction.UpdateZones(); + pbxInput.Image = extraction.ScreenPreview; } + + private void tmrScreenshots_Tick(object sender, EventArgs e) { - //pbxInput.Image.Dispose(); - Image img = ScreenShot(); - pbxInput.Image = img; + extraction.UpdateZones(); + pbxInput.Image = extraction.ScreenPreview; + if(currentZoneIndex != -1) + tbxResult.Text = extraction.GetZoneRawText(currentZoneIndex); + //This is to prevent Ram from exploding GC.Collect(); - //img.Dispose(); } private void lsbScreens_SelectedIndexChanged(object sender, EventArgs e) { - currentScreen = screens[lsbScreens.SelectedIndex]; + extraction.ChangeScreen(screens[lsbScreens.SelectedIndex]); + pbxInput.Image = extraction.ScreenPreview; } + private void pbxInput_Click(object sender, EventArgs e) + { + if (creatingZone) + { + //Convert coordinates to image coordinates + Rectangle screenSize = extraction.CurrentScreen.Bounds; + float xRatio = (float)screenSize.Width / (float)pbxInput.Width; + float yRatio = (float)screenSize.Height / (float)pbxInput.Height; + Point tmpPoint = pbxInput.PointToClient(MousePosition); + Point newPoint = new Point(Convert.ToInt32((float)tmpPoint.X * xRatio),Convert.ToInt32((float)tmpPoint.Y * yRatio)); + + if (newZonePoints[0] == new Point(-1,-1)) + { + //Its the first point + newZonePoints[0] = newPoint; + btnCreateZone.Text = "Creating Zone 1/2 points selected"; + } + else + { + //Its the second point + newZonePoints[1] = newPoint; + btnCreateZone.Text = "Create Zone"; + + Zone.ZoneType newZoneType = zoneTypes[lsbZoneTypes.SelectedIndex]; + Random rnd = new Random(); + Point p1 = newZonePoints[0]; + Point p2 = newZonePoints[1]; + Size newSize = new Size(Math.Max(p1.X,p2.X) - Math.Min(p1.X, p2.X),Math.Max(p1.Y,p2.Y) - Math.Min(p1.Y, p2.Y)); + extraction.AddZone(new Rectangle(newZonePoints[0],newSize),newZoneType,"Coucou"); + + newZonePoints = new Point[2] { new Point(-1, -1), new Point(-1, -1) }; + creatingZone = false; + RefreshUi(); + } + } + } + private void btnCreateZone_Click(object sender, EventArgs e) + { + creatingZone = !creatingZone; + if (creatingZone) + { + btnCreateZone.Text = "Creating Zone 0/2 points selected"; + } + else + { + btnCreateZone.Text = "Create Zone"; + } + } + + private void lsbZones_SelectedIndexChanged(object sender, EventArgs e) + { + if (extraction.GetZonesNames().Any() && lsbZones.SelectedIndex >= 0) + { + currentZoneIndex = lsbZones.SelectedIndex; + } + } } } diff --git a/TestVideo/TestVideo.csproj b/TestVideo/TestVideo.csproj index fe2c034..3947705 100644 --- a/TestVideo/TestVideo.csproj +++ b/TestVideo/TestVideo.csproj @@ -67,6 +67,8 @@ + + Form @@ -75,6 +77,7 @@ + Form1.cs diff --git a/TestVideo/Zone.cs b/TestVideo/Zone.cs new file mode 100644 index 0000000..7796571 --- /dev/null +++ b/TestVideo/Zone.cs @@ -0,0 +1,120 @@ +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); + 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; + } + } +}