private string readImage(int resolution, Bitmap source, bool onlyMaximalMatches, bool onlyNumbers, bool writingInWhite = true)
{
string result = "";
Bitmap[,] theAlphabet = alphabet;
if (onlyNumbers)
theAlphabet = reducedAlphabet;
Bitmap cleanedImage = removePixelsUnderThreshold(GetGreyScale(source, !writingInWhite), whiteThreshold);
AddBitmapToDebug(cleanedImage);
//source.Save("D:\\temp\\debug.png"); // TODO comment out
//cleanedImage.Save("D:\\temp\\debug_cleaned.png");// TODO comment out
for (int x = 0; x < cleanedImage.Width; x++)
{
bool foundLetter = false;
int letterStart = 0;
int letterEnd = 0;
// look for the start pixel of the letter
while (!(foundLetter == true || x >= cleanedImage.Width))
{
foundLetter = HasWhiteInVerticalLine(cleanedImage, x);
x++;
}
if (foundLetter)
{
letterStart = x - 1;
// look for the end of the letter
do
{
x++;
} while (HasWhiteInVerticalLine(cleanedImage, x) && x < cleanedImage.Width - 1);
letterEnd = x;
}
if (letterEnd > cleanedImage.Width)
letterEnd = cleanedImage.Width;
if (letterStart != letterEnd)
{
// found a letter, see if a match can be found
Rectangle letterR = letterRect(cleanedImage, letterStart, letterEnd);
if (letterR.Width > 0 && letterR.Height > 0)
{
Bitmap testImage = SubImage(cleanedImage, letterR.Left, letterR.Top, letterR.Width, letterR.Height);
//testImage.Save("D:\\temp\\debug_letterfound.png");// TODO comment out
Dictionary<int, float> matches = new Dictionary<int, float>();
float bestMatch = 0;
for (int l = 0; l < theAlphabet.GetLength(1); l++)
{
float match = 0;
if (theAlphabet[resolution, l] != null)
match = (float)(PercentageMatch(theAlphabet[resolution, l], testImage) * charWeighting[l]);
else
continue;
if (match > 0.5)
{
matches[l] = match;
if (bestMatch < match)
bestMatch = match;
}
}
if (matches.Count == 0)
continue;
Dictionary<int, float> goodMatches = new Dictionary<int, float>();
if (matches.Count == 1)
goodMatches = matches;
else
{
foreach (KeyValuePair<int, float> kv in matches)
if (kv.Value > 0.95 * bestMatch)
goodMatches[kv.Key] = kv.Value; // discard matches that are not at least 95% as good as the best match
}
//// debugging / TODO
//// save recognized image and two best matches with percentage
//Bitmap debugImg = new Bitmap(200, 50);
//using (Graphics g = Graphics.FromImage(debugImg))
//{
// g.FillRectangle(Brushes.DarkCyan, 0, 0, debugImg.Width, debugImg.Height);
// g.DrawImage(testImage, 1, 1, testImage.Width, testImage.Height);
// int i = testImage.Width + 25;
// Font font = new Font("Arial", 8);
// foreach (int l in goodMatches.Keys)
// {
// g.DrawImage(theAlphabet[resolution, l], i, 1, theAlphabet[resolution, l].Width, theAlphabet[resolution, l].Height);
// g.DrawString(Math.Round(goodMatches[l] * 100).ToString(), font, (bestMatch == goodMatches[l] ? Brushes.DarkGreen : Brushes.DarkRed), i, 35);
// i += theAlphabet[resolution, l].Width + 15;
// }
// debugImg.Save("D:\\temp\\debug_letter" + DateTime.Now.ToString("HHmmss\\-fffffff\\-") + x + ".png");
//}
//// end debugging
if (goodMatches.Count == 1)
result += (char)(goodMatches.Keys.ToArray()[0]);
else
{
if (onlyMaximalMatches)
{
foreach (int l in goodMatches.Keys)
{
if (goodMatches[l] == bestMatch)
{
result += (char)l;
break; // if there are multiple best matches take only the first
}
}
}
else
{
result += "[";
foreach (int l in goodMatches.Keys)
result += (char)l + goodMatches[l].ToString("{0.00}") + " ";
result += "]";
}
}
}
}
}
// replace half letters.
result = result.Replace((char)15 + "n", "n");
result = result.Replace((char)16 + "lK", "K");
return result;
}