Just everything is better

This commit is contained in:
2022-10-19 16:14:02 +02:00
parent 8a05e7b54b
commit f0f78e81f9
6 changed files with 589 additions and 133 deletions

101
TestVideo/EnumExtensions.cs Normal file
View File

@@ -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
{
/// <summary>
/// Gets all items for an enum value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static IEnumerable<T> GetAllItems<T>(this Enum value)
{
foreach (object item in Enum.GetValues(typeof(T)))
{
yield return (T)item;
}
}
/// <summary>
/// Gets all items for an enum type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static IEnumerable<T> GetAllItems<T>() where T : struct
{
foreach (object item in Enum.GetValues(typeof(T)))
{
yield return (T)item;
}
}
/// <summary>
/// Gets all combined items from an enum value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
/// <example>
/// Displays ValueA and ValueB.
/// <code>
/// EnumExample dummy = EnumExample.Combi;
/// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
/// {
/// Console.WriteLine(item);
/// }
/// </code>
/// </example>
public static IEnumerable<T> GetAllSelectedItems<T>(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;
}
}
}
/// <summary>
/// Determines whether the enum value contains a specific value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="request">The request.</param>
/// <returns>
/// <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
/// </returns>
/// <example>
/// <code>
/// EnumExample dummy = EnumExample.Combi;
/// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
/// {
/// Console.WriteLine("dummy contains EnumExample.ValueA");
/// }
/// </code>
/// </example>
public static bool Contains<T>(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;
}
}
}

156
TestVideo/Extraction.cs Normal file
View File

@@ -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<Zone> _zones;
private Screen _currentScreen;
private Bitmap _screenPreview;
public Screen CurrentScreen { get => _currentScreen; set => _currentScreen = value; }
public List<Zone> Zones { get => _zones; private set => _zones = value; }
public Bitmap ScreenPreview { get => _screenPreview; set => _screenPreview = value; }
public Extraction(Screen screen)
{
CurrentScreen = screen;
}
public Extraction(List<Zone> 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<Zone> newZones = new List<Zone>();
foreach (Zone zone in newZones)
{
if (IsZoneInBounds(zone.ZoneArea))
newZones.Add(zone);
}
Zones = newZones;
ScreenPreview = ScreenShot();
}
public List<string> GetZonesNames()
{
List<string> zoneNames = new List<string>();
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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -18,15 +18,21 @@ namespace TestVideo
public partial class Form1 : Form
{
public Screen[] screens;
Screen currentScreen;
List<string> screenNames;
Extraction extraction;
int currentZoneIndex;
List<Zone.ZoneType> 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<string>();
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<Zone.ZoneType>();
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<Bgr, byte> emguImage = inputBmp.ToImage<Bgr, byte>();
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;
}
}
}
}

View File

@@ -67,6 +67,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="EnumExtensions.cs" />
<Compile Include="Extraction.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
@@ -75,6 +77,7 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Zone.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>

120
TestVideo/Zone.cs Normal file
View File

@@ -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<Bgr, byte> emguImage = inputBmp.ToImage<Bgr, byte>();
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;
}
}
}