コード例 #1
0
ファイル: Ocr.cs プロジェクト: GettroLadalle/RegulatedNoise
        public void PerformOcr(List<Tuple<int, int>> textRowLocations)
        {
            int DarkPixels;
            var engine = new TesseractEngine(@"./tessdata", Form1.RegulatedNoiseSettings.TraineddataFile, EngineMode.Default);
            engine.DefaultPageSegMode = PageSegMode.SingleLine;

            string Stationname_OCR;
            string StationameAnalysisBase;

            // delete the old brainerous images - otherwise Brainerous will process older but not relevant images too
            if (Directory.Exists(@".\Brainerous\images"))
                foreach (string file in Directory.GetFiles(@".\\Brainerous\\images", "*.*"))
                    File.Delete(file);
            else
                Directory.CreateDirectory("./Brainerous/images");

            float level;
            var text = AnalyseFrameUsingTesseract(_bTrimmedHeader, engine, out level);
            Stationname_OCR = StripPunctuationFromScannedText(text);// (text + " {" + page.GetMeanConfidence() + "}\r\n");

            // debug: SystemAtTimeOfScreenshot = "BD+65 1846"
            string[] StationsInSystem = _callingForm.myMilkyway.getStationNames(SystemAtTimeOfScreenshot);

            if(_callingForm.tbCurrentStationinfoFromLogs.Text.Equals("scanning...", StringComparison.InvariantCultureIgnoreCase))
                StationameAnalysisBase = Stationname_OCR;
            else
                StationameAnalysisBase = _callingForm.tbCurrentStationinfoFromLogs.Text;

            string headerResult_temp = StationsInSystem.FirstOrDefault(x => x.Equals(StationameAnalysisBase, StringComparison.InvariantCultureIgnoreCase));

            if(headerResult_temp == null)
            { 
                // station not found in database
                var matchesInStationReferenceList = StationsInSystem.OrderBy(x => _levenshtein.LD2(Stationname_OCR, x)).ToList();

                if(matchesInStationReferenceList.Count > 0)
                {
                    var ld = _levenshtein.LD2(Stationname_OCR, matchesInStationReferenceList[0].ToUpper());
                
                    // this depends on the length of the word - this factor works really good
                    double LevenshteinLimit = Math.Round((matchesInStationReferenceList[0].Length * 1.0), 0);

                    if (ld <= LevenshteinLimit)
                        Stationname_OCR = matchesInStationReferenceList[0];
                }
            }
            else
            {
                Stationname_OCR = headerResult_temp;
            }
            
            // show station on GUI

            _callingForm.DisplayResults(Stationname_OCR);
            
            var commodityColumnText         = new string[textRowLocations.Count(), 8]; 
            var originalBitmaps             = new Bitmap[textRowLocations.Count(),8];
            var originalBitmapConfidences   = new float[textRowLocations.Count(), 8];
            var rowIds                      = new string[textRowLocations.Count()];
            var rowCtr                      = 0;
			
            var bitmapCtr = 0;

            foreach (var row in textRowLocations)
            {
                int startRow = row.Item1 - 3;
                int heightRow = row.Item2 - row.Item1 + 6;

                if (startRow < 0) 
                    startRow = 0;

                if (heightRow + startRow > _bTrimmed_4_OCR.Height) 
                    heightRow = _bTrimmed_4_OCR.Height - startRow;

                // We'll use this later to identify the right correction image
                rowIds[rowCtr] = Guid.NewGuid().ToString();
                using (Bitmap b = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(0, startRow, _bTrimmed_4_OCR.Width, heightRow)))
                {
                    b.Save(".//OCR Correction Images//" + rowIds[rowCtr] + ".png");
                }

                
                int columnCounter = 0;
                while (columnCounter < 8)
                {
                    int left, width;
                    switch(columnCounter)
                    {
                        case 0:
                            // commodity
                            left = 0; width = _calibrationPoints[3].X - _calibrationPoints[2].X;
                            break;
                        case 1:
                            // sell
                            left = _calibrationPoints[3].X - _calibrationPoints[2].X; width = _calibrationPoints[4].X - _calibrationPoints[3].X;
                            break;
                        case 2:
                            //buy
                            left = _calibrationPoints[4].X - _calibrationPoints[2].X; width = _calibrationPoints[5].X - _calibrationPoints[4].X;
                            break;
                        case 3:
                            // freight
                            left = _calibrationPoints[5].X - _calibrationPoints[2].X; width = _calibrationPoints[6].X - _calibrationPoints[5].X;
                            break;
                        case 4:
                            // demand
                            left = _calibrationPoints[6].X - _calibrationPoints[2].X; width = _calibrationPoints[7].X - _calibrationPoints[6].X;
                            break;
                        case 5:
                            // demand level
                            left = _calibrationPoints[7].X - _calibrationPoints[2].X; width = _calibrationPoints[8].X - _calibrationPoints[7].X;
                            break;
                        case 6:
                            // supply 
                            left = _calibrationPoints[8].X - _calibrationPoints[2].X; width = _calibrationPoints[9].X - _calibrationPoints[8].X;
                            break;
                        case 7:
                            // supply level
                            left = _calibrationPoints[9].X - _calibrationPoints[2].X; width = _calibrationPoints[10].X - _calibrationPoints[9].X;
                            break;
                        default:
                            left = 0; width = _calibrationPoints[3].X - _calibrationPoints[2].X;
                            break;
                    }
                    var fudgeFactor = 0;// _bOriginal.Height * 6 / 1440;
                    left = left + fudgeFactor;
                    width = width - fudgeFactor;

                    DarkPixels = 0;

                    if (_callingForm.cbCheckAOne.Checked)
                    {
                        if (PixelTest == null)
                            PixelTest = new EBPixeltest();

                        if (columnCounter == 3)
                        {
                            var brainerousOut = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow));

                            // check how much dark pixels are on the bitmap
                            for (int i = 0; i < brainerousOut.Height; i++)
                                for (int j = 0; j < brainerousOut.Width; j++)
                                    if (brainerousOut.GetPixel(j, i).GetBrightness() < Form1.RegulatedNoiseSettings.EBPixelThreshold)
                                        DarkPixels++;

                            PixelTest.addPicture(brainerousOut, DarkPixels);
                        }
                    }
                    else
                    {
                        //  RNGraphics.Crop a little bit more form the left border because sometimes if theres 
                        // the line of the table it was recognized as "1" or "7"
                        left += 10;
                        width -= 10;

                        if (columnCounter != 0 && columnCounter != 5 && columnCounter != 7)
                        {   //If it's a numeric column write it out for Brainerous to process later
                            var brainerousOut = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow));

                            if (Form1.RegulatedNoiseSettings.EBPixelAmount > 0)
                            {
                                // check how much dark pixels are on the bitmap -> we process only bitmaps 
                                // with something on it (minimum one digit supposed, a "1" hat about 25 pixels in default 1920x1200)
                                for (int i = 0; i < brainerousOut.Height; i++)
                                    for (int j = 0; j < brainerousOut.Width; j++)
                                        if (brainerousOut.GetPixel(j, i).GetBrightness() < Form1.RegulatedNoiseSettings.EBPixelThreshold)
                                            DarkPixels++;
                            }

                            if (DarkPixels >= Form1.RegulatedNoiseSettings.EBPixelAmount)
                                brainerousOut.Save("./Brainerous/images/" + bitmapCtr + ".png");

                            bitmapCtr++;
                        }
                        else
                        {   // It's a text column, we'll use Tesseract

                            // Prepare some different versions of the bitmap, we will take the best result
                            var c = new Bitmap[7];
                            c[0] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow)));
                            c[1] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left + 1, startRow, width, heightRow)));
                            c[2] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left - 1, startRow, width, heightRow)));
                            c[3] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow - 1, width, heightRow)));
                            c[4] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left + 1, startRow - 1, width, heightRow)));
                            c[5] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left - 1, startRow - 1, width, heightRow)));
                            c[6] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow + 2, width, heightRow - 2)));

                           
                            var t = new string[c.Length];
                            var cf = new float[c.Length];


                            for (int i = 0; i < c.Length; i++)
                            {
                                t[i] = AnalyseFrameUsingTesseract((Bitmap)(c[i].Clone()), engine, out cf[i]);
                            }

                            int result = 0;
                            float confidence = cf[0];

                            for (int i = 1; i < c.Length; i++)
                            {
                                if (confidence < cf[i])
                                { result = i; confidence = cf[i]; }
                            }

                            originalBitmaps[rowCtr, columnCounter] = (Bitmap)(c[result].Clone());

                            switch (columnCounter)
                            {
                                //bodges for number columns
                                case 1:
                                case 2:
                                case 3:
                                    t[result] = t[result].Replace(" ", "").Replace("O", "0").Replace("I", "1").Replace("'", "");
                                    t[result] = System.Text.RegularExpressions.Regex.Replace(t[result], @"[a-zA-Z\s]+", string.Empty); // remove any alphas that remain
                                    break;
                                case 5:
                                case 7:
                                    var darkpixels = 0;
                                    for (int i = 0; i < c[result].Height; i++)
                                        for (int j = 0; j < c[result].Width; j++)
                                            if (c[result].GetPixel(j, i).GetBrightness() < Form1.RegulatedNoiseSettings.EBPixelThreshold)
                                                darkpixels++;

                                    var ratio = (float) c[result].Height*c[result].Width/darkpixels;
                                    if (darkpixels < 100)
                                    {
                                        //0
                                    }
                                    else if (ratio < 2)
                                    {
                                        //3
                                        t[result] = "HIGH";
                                        cf[result] = 1;
                                    }
                                    else if (ratio < 2.6)
                                    {
                                        //2
                                        t[result] = "MED";
                                        cf[result] = 1;
                                    }
                                    else
                                    {
                                        //1
                                        t[result] = "LOW";
                                        cf[result] = 1;
                                    }
                                    break;
                            }
                            if ((columnCounter == 5 && t[result].Contains("ENTER")) ||
                                (columnCounter == 6 && (t[result].Contains("NGAR") || t[result].Contains("SURFACE"))))
                            {
                                t[result] = "";
                                cf[result] = 1;
                            }
                            commodityColumnText[rowCtr, columnCounter] += t[result];
                            originalBitmapConfidences[rowCtr, columnCounter] = cf[result];
                        }
                    }

                    columnCounter++;
                }
                rowCtr++;
            }

            if (_callingForm.cbCheckAOne.Checked)
            {
                PixelTest.StartModal(_callingForm);

            }
            else
            {
                if (textRowLocations.Count > 0)
                {
                    // Call out to Brainerous to process the numeric bitmaps we saved earlier
                    var outputFromBrainerous = "";
                    var pr = new Process();
                    pr.StartInfo.UseShellExecute = false;
                    pr.StartInfo.CreateNoWindow = true;
                    pr.StartInfo.RedirectStandardOutput = true;
                    pr.StartInfo.FileName = "./Brainerous/nn_training.exe";
                    pr.StartInfo.WorkingDirectory = "./Brainerous/";
                    pr.Start();
                    outputFromBrainerous = pr.StandardOutput.ReadToEnd();

                    while (outputFromBrainerous.Contains("Failed to pad successfully"))
                    {
                        var o2 = outputFromBrainerous.IndexOf("Failed to ");
                        var o3 = outputFromBrainerous.Substring(0, o2);
                        var o4 = outputFromBrainerous.Substring(o2).IndexOf("./images", StringComparison.InvariantCultureIgnoreCase);

                        // I had a string with "Failed to pad successfully" and only some trash behind but no "./images"
                        // so "o4" was "-1" and this results in strange behaviour
                        if (o4 > 0)
                        {
                            var o5 = outputFromBrainerous.Substring(o2 + o4);
                            outputFromBrainerous = o3 + "\r\n" + o5;
                        }
                        else
                        {
                            outputFromBrainerous = o3;
                        }
                    }

                    pr.WaitForExit();

                    List<string> splitOutput = ((string[])outputFromBrainerous.Replace("\r", "").Split('\n')).ToList();

                    for (var i = 0; i < (textRowLocations.Count * 10); i += 2)
                    {
                        string Filename = (i / 2).ToString() + ".png";
                        if ((splitOutput.Count <= i) || (splitOutput[i].Length < 14) || (splitOutput[i].Substring(9) != Filename))
                        {
                            splitOutput.Insert(i, "./images/" + Filename);
                            splitOutput.Insert(i + 1, "");
                        }
                    }


                    // Load the result from Brainerous into the OCR output
                    for (var i = 0; i < textRowLocations.Count; i++)
                    {
                        commodityColumnText[i, 1] = splitOutput[i * 10 + 1];
                        originalBitmaps[i, 1] = null;
                        originalBitmapConfidences[i, 1] = 1;
                        commodityColumnText[i, 2] = splitOutput[i * 10 + 3];
                        originalBitmaps[i, 2] = null;
                        originalBitmapConfidences[i, 2] = 1;
                        commodityColumnText[i, 3] = splitOutput[i * 10 + 5];
                        originalBitmaps[i, 3] = null;
                        originalBitmapConfidences[i, 3] = 1;
                        commodityColumnText[i, 4] = splitOutput[i * 10 + 7];
                        originalBitmaps[i, 4] = null;
                        originalBitmapConfidences[i, 4] = 1;
                        commodityColumnText[i, 6] = splitOutput[i * 10 + 9];
                        originalBitmaps[i, 6] = null;
                        originalBitmapConfidences[i, 6] = 1;

                    }
                }
            }

            _bOriginal.Dispose();
            _bOriginalClone.Dispose();
            engine.Dispose();

            if (_callingForm.cbCheckAOne.Checked)
            {
                _callingForm.setCheckbox(_callingForm.cbCheckAOne, false);
                Form1.InstanceObject.clearOcrOutput();
            }
            else
            {
                // Send the results for this screenshot back to the Form
                _callingForm.DisplayCommodityResults(commodityColumnText, originalBitmaps, originalBitmapConfidences, rowIds, CurrentScreenshot);
            }

            // ...and if we've got any buffered screenshots waiting to be processed, process the next one
            if (ScreenshotBuffer.Count > 0)
            {               
                var screenshot = ScreenshotBuffer[0];
                ScreenshotBuffer.Remove(screenshot);
                ProcessNewScreenshot(screenshot);
            }

            Working = false;

            Debug.WriteLine("set to " + Working);
        }
コード例 #2
0
ファイル: Ocr.cs プロジェクト: nernst/RegulatedNoise
        public void PerformOcr(List <Tuple <int, int> > textRowLocations)
        {
            int DarkPixels;
            var engine = new TesseractEngine(@"./tessdata", Form1.RegulatedNoiseSettings.TraineddataFile, EngineMode.Default);

            engine.DefaultPageSegMode = PageSegMode.SingleLine;

            string Stationname_OCR;
            string StationameAnalysisBase;

            // delete the old brainerous images - otherwise Brainerous will process older but not relevant images too
            if (Directory.Exists(@".\Brainerous\images"))
            {
                foreach (string file in Directory.GetFiles(@".\\Brainerous\\images", "*.*"))
                {
                    File.Delete(file);
                }
            }
            else
            {
                Directory.CreateDirectory("./Brainerous/images");
            }

            float level;
            var   text = AnalyseFrameUsingTesseract(_bTrimmedHeader, engine, out level);

            Stationname_OCR = StripPunctuationFromScannedText(text);// (text + " {" + page.GetMeanConfidence() + "}\r\n");

            // debug: SystemAtTimeOfScreenshot = "BD+65 1846"
            string[] StationsInSystem = _callingForm.myMilkyway.getStationNames(SystemAtTimeOfScreenshot);

            if (_callingForm.tbCurrentStationinfoFromLogs.Text.Equals("scanning...", StringComparison.InvariantCultureIgnoreCase))
            {
                StationameAnalysisBase = Stationname_OCR;
            }
            else
            {
                StationameAnalysisBase = _callingForm.tbCurrentStationinfoFromLogs.Text;
            }

            string headerResult_temp = StationsInSystem.FirstOrDefault(x => x.Equals(StationameAnalysisBase, StringComparison.InvariantCultureIgnoreCase));

            if (headerResult_temp == null)
            {
                // station not found in database
                var matchesInStationReferenceList = StationsInSystem.OrderBy(x => _levenshtein.LD2(Stationname_OCR, x)).ToList();

                if (matchesInStationReferenceList.Count > 0)
                {
                    var ld = _levenshtein.LD2(Stationname_OCR, matchesInStationReferenceList[0].ToUpper());

                    // this depends on the length of the word - this factor works really good
                    double LevenshteinLimit = Math.Round((matchesInStationReferenceList[0].Length * 1.0), 0);

                    if (ld <= LevenshteinLimit)
                    {
                        Stationname_OCR = matchesInStationReferenceList[0];
                    }
                }
            }
            else
            {
                Stationname_OCR = headerResult_temp;
            }

            // show station on GUI

            _callingForm.DisplayResults(Stationname_OCR);

            var commodityColumnText       = new string[textRowLocations.Count(), 8];
            var originalBitmaps           = new Bitmap[textRowLocations.Count(), 8];
            var originalBitmapConfidences = new float[textRowLocations.Count(), 8];
            var rowIds = new string[textRowLocations.Count()];
            var rowCtr = 0;

            var bitmapCtr = 0;

            foreach (var row in textRowLocations)
            {
                int startRow  = row.Item1 - 3;
                int heightRow = row.Item2 - row.Item1 + 6;

                if (startRow < 0)
                {
                    startRow = 0;
                }

                if (heightRow + startRow > _bTrimmed_4_OCR.Height)
                {
                    heightRow = _bTrimmed_4_OCR.Height - startRow;
                }

                // We'll use this later to identify the right correction image
                rowIds[rowCtr] = Guid.NewGuid().ToString();
                using (Bitmap b = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(0, startRow, _bTrimmed_4_OCR.Width, heightRow)))
                {
                    b.Save(".//OCR Correction Images//" + rowIds[rowCtr] + ".png");
                }

                int columnCounter = 0;
                while (columnCounter < 8)
                {
                    int left, width;
                    switch (columnCounter)
                    {
                    case 0:
                        // commodity
                        left = 0; width = _calibrationPoints[3].X - _calibrationPoints[2].X;
                        break;

                    case 1:
                        // sell
                        left = _calibrationPoints[3].X - _calibrationPoints[2].X; width = _calibrationPoints[4].X - _calibrationPoints[3].X;
                        break;

                    case 2:
                        //buy
                        left = _calibrationPoints[4].X - _calibrationPoints[2].X; width = _calibrationPoints[5].X - _calibrationPoints[4].X;
                        break;

                    case 3:
                        // freight
                        left = _calibrationPoints[5].X - _calibrationPoints[2].X; width = _calibrationPoints[6].X - _calibrationPoints[5].X;
                        break;

                    case 4:
                        // demand
                        left = _calibrationPoints[6].X - _calibrationPoints[2].X; width = _calibrationPoints[7].X - _calibrationPoints[6].X;
                        break;

                    case 5:
                        // demand level
                        left = _calibrationPoints[7].X - _calibrationPoints[2].X; width = _calibrationPoints[8].X - _calibrationPoints[7].X;
                        break;

                    case 6:
                        // supply
                        left = _calibrationPoints[8].X - _calibrationPoints[2].X; width = _calibrationPoints[9].X - _calibrationPoints[8].X;
                        break;

                    case 7:
                        // supply level
                        left = _calibrationPoints[9].X - _calibrationPoints[2].X; width = _calibrationPoints[10].X - _calibrationPoints[9].X;
                        break;

                    default:
                        left = 0; width = _calibrationPoints[3].X - _calibrationPoints[2].X;
                        break;
                    }
                    var fudgeFactor = 0;// _bOriginal.Height * 6 / 1440;
                    left  = left + fudgeFactor;
                    width = width - fudgeFactor;

                    DarkPixels = 0;

                    if (_callingForm.cbCheckAOne.Checked)
                    {
                        if (PixelTest == null)
                        {
                            PixelTest = new EBPixeltest();
                        }

                        if (columnCounter == 3)
                        {
                            var brainerousOut = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow));

                            // check how much dark pixels are on the bitmap
                            for (int i = 0; i < brainerousOut.Height; i++)
                            {
                                for (int j = 0; j < brainerousOut.Width; j++)
                                {
                                    if (brainerousOut.GetPixel(j, i).GetBrightness() < Form1.RegulatedNoiseSettings.EBPixelThreshold)
                                    {
                                        DarkPixels++;
                                    }
                                }
                            }

                            PixelTest.addPicture(brainerousOut, DarkPixels);
                        }
                    }
                    else
                    {
                        //  RNGraphics.Crop a little bit more form the left border because sometimes if theres
                        // the line of the table it was recognized as "1" or "7"
                        left  += 10;
                        width -= 10;

                        if (columnCounter != 0 && columnCounter != 5 && columnCounter != 7)
                        {   //If it's a numeric column write it out for Brainerous to process later
                            var brainerousOut = RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow));

                            if (Form1.RegulatedNoiseSettings.EBPixelAmount > 0)
                            {
                                // check how much dark pixels are on the bitmap -> we process only bitmaps
                                // with something on it (minimum one digit supposed, a "1" hat about 25 pixels in default 1920x1200)
                                for (int i = 0; i < brainerousOut.Height; i++)
                                {
                                    for (int j = 0; j < brainerousOut.Width; j++)
                                    {
                                        if (brainerousOut.GetPixel(j, i).GetBrightness() < Form1.RegulatedNoiseSettings.EBPixelThreshold)
                                        {
                                            DarkPixels++;
                                        }
                                    }
                                }
                            }

                            if (DarkPixels >= Form1.RegulatedNoiseSettings.EBPixelAmount)
                            {
                                brainerousOut.Save("./Brainerous/images/" + bitmapCtr + ".png");
                            }

                            bitmapCtr++;
                        }
                        else
                        {   // It's a text column, we'll use Tesseract
                            // Prepare some different versions of the bitmap, we will take the best result
                            var c = new Bitmap[7];
                            c[0] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow, width, heightRow)));
                            c[1] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left + 1, startRow, width, heightRow)));
                            c[2] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left - 1, startRow, width, heightRow)));
                            c[3] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow - 1, width, heightRow)));
                            c[4] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left + 1, startRow - 1, width, heightRow)));
                            c[5] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left - 1, startRow - 1, width, heightRow)));
                            c[6] = (RNGraphics.Crop(_bTrimmed_4_OCR, new Rectangle(left, startRow + 2, width, heightRow - 2)));

                            var t  = new string[c.Length];
                            var cf = new float[c.Length];


                            for (int i = 0; i < c.Length; i++)
                            {
                                t[i] = AnalyseFrameUsingTesseract((Bitmap)(c[i].Clone()), engine, out cf[i]);
                            }

                            int   result     = 0;
                            float confidence = cf[0];

                            for (int i = 1; i < c.Length; i++)
                            {
                                if (confidence < cf[i])
                                {
                                    result = i; confidence = cf[i];
                                }
                            }

                            originalBitmaps[rowCtr, columnCounter] = (Bitmap)(c[result].Clone());

                            switch (columnCounter)
                            {
                            //bodges for number columns
                            case 1:
                            case 2:
                            case 3:
                                t[result] = t[result].Replace(" ", "").Replace("O", "0").Replace("I", "1").Replace("'", "");
                                t[result] = System.Text.RegularExpressions.Regex.Replace(t[result], @"[a-zA-Z\s]+", string.Empty);     // remove any alphas that remain
                                break;

                            case 5:
                            case 7:
                                t[result] = t[result].Replace(" ", "").Replace("-", "");
                                if (t[result] == "HIGH" || t[result] == "MED" || t[result] == "LOW")
                                {
                                    cf[result] = 1;
                                }
                                break;
                            }
                            if ((columnCounter == 5 && t[result].Contains("ENTER")) ||
                                (columnCounter == 6 && (t[result].Contains("NGAR") || t[result].Contains("SURFACE"))))
                            {
                                t[result]  = "";
                                cf[result] = 1;
                            }
                            commodityColumnText[rowCtr, columnCounter]      += t[result];
                            originalBitmapConfidences[rowCtr, columnCounter] = cf[result];
                        }
                    }

                    columnCounter++;
                }
                rowCtr++;
            }

            if (_callingForm.cbCheckAOne.Checked)
            {
                PixelTest.StartModal(_callingForm);
            }
            else
            {
                if (textRowLocations.Count > 0)
                {
                    // Call out to Brainerous to process the numeric bitmaps we saved earlier
                    var outputFromBrainerous = "";
                    var pr = new Process();
                    pr.StartInfo.UseShellExecute        = false;
                    pr.StartInfo.CreateNoWindow         = true;
                    pr.StartInfo.RedirectStandardOutput = true;
                    pr.StartInfo.FileName         = "./Brainerous/nn_training.exe";
                    pr.StartInfo.WorkingDirectory = "./Brainerous/";
                    pr.Start();
                    outputFromBrainerous = pr.StandardOutput.ReadToEnd();

                    while (outputFromBrainerous.Contains("Failed to pad successfully"))
                    {
                        var o2 = outputFromBrainerous.IndexOf("Failed to ");
                        var o3 = outputFromBrainerous.Substring(0, o2);
                        var o4 = outputFromBrainerous.Substring(o2).IndexOf("./images", StringComparison.InvariantCultureIgnoreCase);

                        // I had a string with "Failed to pad successfully" and only some trash behind but no "./images"
                        // so "o4" was "-1" and this results in strange behaviour
                        if (o4 > 0)
                        {
                            var o5 = outputFromBrainerous.Substring(o2 + o4);
                            outputFromBrainerous = o3 + "\r\n" + o5;
                        }
                        else
                        {
                            outputFromBrainerous = o3;
                        }
                    }

                    pr.WaitForExit();

                    List <string> splitOutput = ((string[])outputFromBrainerous.Replace("\r", "").Split('\n')).ToList();

                    for (var i = 0; i < (textRowLocations.Count * 10); i += 2)
                    {
                        string Filename = (i / 2).ToString() + ".png";
                        if ((splitOutput.Count <= i) || (splitOutput[i].Length < 14) || (splitOutput[i].Substring(9) != Filename))
                        {
                            splitOutput.Insert(i, "./images/" + Filename);
                            splitOutput.Insert(i + 1, "");
                        }
                    }


                    // Load the result from Brainerous into the OCR output
                    for (var i = 0; i < textRowLocations.Count; i++)
                    {
                        commodityColumnText[i, 1]       = splitOutput[i * 10 + 1];
                        originalBitmaps[i, 1]           = null;
                        originalBitmapConfidences[i, 1] = 1;
                        commodityColumnText[i, 2]       = splitOutput[i * 10 + 3];
                        originalBitmaps[i, 2]           = null;
                        originalBitmapConfidences[i, 2] = 1;
                        commodityColumnText[i, 3]       = splitOutput[i * 10 + 5];
                        originalBitmaps[i, 3]           = null;
                        originalBitmapConfidences[i, 3] = 1;
                        commodityColumnText[i, 4]       = splitOutput[i * 10 + 7];
                        originalBitmaps[i, 4]           = null;
                        originalBitmapConfidences[i, 4] = 1;
                        commodityColumnText[i, 6]       = splitOutput[i * 10 + 9];
                        originalBitmaps[i, 6]           = null;
                        originalBitmapConfidences[i, 6] = 1;
                    }
                }
            }

            _bOriginal.Dispose();
            _bOriginalClone.Dispose();
            engine.Dispose();

            if (_callingForm.cbCheckAOne.Checked)
            {
                _callingForm.setCheckbox(_callingForm.cbCheckAOne, false);
                Form1.InstanceObject.clearOcrOutput();
            }
            else
            {
                // Send the results for this screenshot back to the Form
                _callingForm.DisplayCommodityResults(commodityColumnText, originalBitmaps, originalBitmapConfidences, rowIds, CurrentScreenshot);
            }

            // ...and if we've got any buffered screenshots waiting to be processed, process the next one
            if (ScreenshotBuffer.Count > 0)
            {
                var screenshot = ScreenshotBuffer[0];
                ScreenshotBuffer.Remove(screenshot);
                ProcessNewScreenshot(screenshot);
            }

            Working = false;

            Debug.WriteLine("set to " + Working);
        }