Added a good Name recognition algorythm
This commit is contained in:
@@ -15,12 +15,13 @@ namespace OCR_Decode
|
||||
{
|
||||
Name = "Name";
|
||||
}
|
||||
/*
|
||||
public override object DecodePng()
|
||||
{
|
||||
string result = "";
|
||||
|
||||
Bitmap rawData = WindowImage;
|
||||
rawData = Window.ConvertToBlackAndWhite(rawData,100);
|
||||
rawData = Window.ConvertToBlackAndWhite(rawData,150);
|
||||
|
||||
TesseractEngine engine = new TesseractEngine(TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(WindowImage));
|
||||
@@ -46,7 +47,113 @@ namespace OCR_Decode
|
||||
}
|
||||
rawData.Save(Reader.DEBUG_DUMP_FOLDER + result + "_Before" + ".png");
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
public override object DecodePng(List<string> DriverList)
|
||||
{
|
||||
string result = "";
|
||||
int[] recommendedTresholds = new int[] { 100, 125, 150, 175, 200 };
|
||||
|
||||
int index = 0;
|
||||
while (!IsADriver(DriverList, result))
|
||||
{
|
||||
if(index >= recommendedTresholds.Length -1)
|
||||
{
|
||||
//150 is usually the safest bet
|
||||
result = GetStringFromPng(150);
|
||||
//I put everything in uppercase to try to lower the chances of bad answers
|
||||
result = FindClosestMatch(DriverList.ConvertAll(d => d.ToUpper()), result.ToUpper());
|
||||
break;
|
||||
}
|
||||
result = GetStringFromPng(recommendedTresholds[index]);
|
||||
index++;
|
||||
}
|
||||
//rawData.Save(Reader.DEBUG_DUMP_FOLDER + result + "_Before" + ".png");
|
||||
return result;
|
||||
}
|
||||
private string GetStringFromPng(int BlackAndWhiteTresholh)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
Bitmap rawData = WindowImage;
|
||||
rawData = Window.ConvertToBlackAndWhite(rawData, 150);
|
||||
|
||||
TesseractEngine engine = new TesseractEngine(TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(WindowImage));
|
||||
|
||||
Page page = engine.Process(tessImage);
|
||||
Graphics g = Graphics.FromImage(rawData);
|
||||
// Get the iterator for the page layout
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
// Loop over the elements of the page layout
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
Rect boundingBox;
|
||||
// Get the bounding box for the current element
|
||||
if (iter.TryGetBoundingBox(PageIteratorLevel.Word, out boundingBox))
|
||||
{
|
||||
g.DrawRectangle(Pens.Red, new Rectangle(boundingBox.X1, boundingBox.Y1, boundingBox.Width, boundingBox.Height));
|
||||
}
|
||||
// Get the text for the current element
|
||||
result += iter.GetText(PageIteratorLevel.Word);
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//This method has been gnerated using ChatGPT
|
||||
public static string FindClosestMatch(List<string> array, string target)
|
||||
{
|
||||
var closestMatch = "";
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
foreach (var item in array)
|
||||
{
|
||||
var distance = LevenshteinDistance(item, target);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestMatch = item;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return closestMatch;
|
||||
}
|
||||
|
||||
public static int LevenshteinDistance(string s1, string s2)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s1))
|
||||
{
|
||||
return string.IsNullOrEmpty(s2) ? 0 : s2.Length;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(s2))
|
||||
{
|
||||
return string.IsNullOrEmpty(s1) ? 0 : s1.Length;
|
||||
}
|
||||
|
||||
var d = new int[s1.Length + 1, s2.Length + 1];
|
||||
for (var i = 0; i <= s1.Length; i++)
|
||||
{
|
||||
d[i, 0] = i;
|
||||
}
|
||||
|
||||
for (var j = 0; j <= s2.Length; j++)
|
||||
{
|
||||
d[0, j] = j;
|
||||
}
|
||||
|
||||
for (var i = 1; i <= s1.Length; i++)
|
||||
{
|
||||
for (var j = 1; j <= s2.Length; j++)
|
||||
{
|
||||
var cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
|
||||
d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
|
||||
}
|
||||
}
|
||||
|
||||
return d[s1.Length, s2.Length];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace OCR_Decode
|
||||
//Main Zone
|
||||
foreach (Zone z in MainZones[mainZoneId].Zones)
|
||||
{
|
||||
mainResults.Add(z.Decode());
|
||||
mainResults.Add(z.Decode(Drivers));
|
||||
}
|
||||
break;
|
||||
//Next there will be the title and laps added
|
||||
|
||||
@@ -38,6 +38,10 @@ namespace OCR_Decode
|
||||
{
|
||||
return " ";
|
||||
}
|
||||
public virtual Object DecodePng(List<string> drivers)
|
||||
{
|
||||
return " ";
|
||||
}
|
||||
public static byte[] ImageToByte(Image img)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
@@ -46,6 +50,17 @@ namespace OCR_Decode
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
public static bool IsADriver(List<string> drivers,string potentialDriver)
|
||||
{
|
||||
bool result = false;
|
||||
//I cant use drivers.Contains because it has missmatched cases and all
|
||||
foreach (string name in drivers)
|
||||
{
|
||||
if (name.ToUpper() == potentialDriver.ToUpper())
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static Bitmap ConvertToBlackAndWhite(Bitmap inputBmp, int Treshold = 165)
|
||||
{
|
||||
Bitmap result = new Bitmap(inputBmp.Width, inputBmp.Height);
|
||||
|
||||
+9
-2
@@ -62,12 +62,19 @@ namespace OCR_Decode
|
||||
{
|
||||
Windows.Add(window);
|
||||
}
|
||||
public virtual List<Object> Decode()
|
||||
public virtual List<Object> Decode(List<string> drivers)
|
||||
{
|
||||
List<Object> result = new List<Object>();
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
result.Add(w.DecodePng());
|
||||
if (w is DriverNameWindow)
|
||||
{
|
||||
result.Add((w as DriverNameWindow).DecodePng(drivers));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(w.DecodePng());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user