Example #1
0
        public bool IsDinoInventoryVisible()
        {
            if (_screenCaptureProcess == null)
            {
                _screenCaptureProcess = Process.GetProcessesByName(screenCaptureApplicationName).FirstOrDefault();
                if (_screenCaptureProcess == null)
                {
                    return(false);
                }
            }

            if (Win32API.GetForegroundWindow() != _screenCaptureProcess.MainWindowHandle)
            {
                return(false);
            }

            Bitmap screenshotBmp = Win32API.GetScreenshotOfProcess(screenCaptureApplicationName, waitBeforeScreenCapture);

            if (screenshotBmp == null ||
                !CheckResolutionSupportedByOcr(screenshotBmp))
            {
                return(false);
            }

            const OcrTemplate.OcrLabels label = OcrTemplate.OcrLabels.Level;
            Rectangle rec     = ocrConfig.labelRectangles[(int)label];
            Bitmap    bmp     = SubImage(screenshotBmp, rec.X, rec.Y, rec.Width, rec.Height);
            string    statOCR = PatternOcr.ReadImageOcr(bmp, true, Properties.Settings.Default.OCRWhiteThreshold);

            return(Regex.IsMatch(statOCR, @":\d+$"));
        }
Example #2
0
        // todo not used, remove?
        //private static Rectangle letterRect(Bitmap source, int hStart, int hEnd)
        //{
        //    int startWhite = -1, endWhite = -1;
        //    for (int j = 0; j < source.Height; j++)
        //    {
        //        for (int i = hStart; i < hEnd; i++)
        //        {
        //            if (startWhite == -1 && source.GetPixel(i, j).R == 255)
        //            {
        //                startWhite = j;
        //            }

        //            if (endWhite == -1 && source.GetPixel(i, (source.Height - j) - 1).R == 255)
        //            {
        //                endWhite = (source.Height - j);
        //            }
        //            if (startWhite != -1 && endWhite != -1)
        //                return new Rectangle(hStart, startWhite, hEnd - hStart, endWhite - startWhite);
        //        }
        //    }


        //    return Rectangle.Empty;
        //}

        public double[] DoOcr(out string OCRText, out string dinoName, out string species, out string ownerName, out string tribeName, out Sex sex, string useImageFilePath = "", bool changeForegroundWindow = true)
        {
            string finishedText = string.Empty;

            dinoName  = string.Empty;
            species   = string.Empty;
            ownerName = string.Empty;
            tribeName = string.Empty;
            sex       = Sex.Unknown;
            double[] finalValues = new double[1] {
                0
            };
            if (ocrConfig == null)
            {
                OCRText = "Error: no ocr configured";
                return(finalValues);
            }

            Bitmap screenshotbmp;

            _ocrControl.debugPanel.Controls.Clear();
            _ocrControl.ClearLists();

            if (System.IO.File.Exists(useImageFilePath))
            {
                screenshotbmp = (Bitmap)Image.FromFile(useImageFilePath);
            }
            else
            {
                // grab screenshot from ark
                screenshotbmp = Win32API.GetScreenshotOfProcess(screenCaptureApplicationName, waitBeforeScreenCapture, true);
            }
            if (screenshotbmp == null)
            {
                OCRText = "Error: no image for OCR. Is ARK running?";
                return(finalValues);
            }

            if (!CheckResolutionSupportedByOcr(screenshotbmp))
            {
                OCRText = "Error while calibrating: The game-resolution is not supported by the currently loaded OCR-configuration.\n"
                          + $"The tested image has a resolution of {screenshotbmp.Width} × {screenshotbmp.Height} px,\n"
                          + $"the resolution of the loaded ocr-config is {ocrConfig.resolutionWidth} × {ocrConfig.resolutionHeight} px.\n\n"
                          + "Load a ocr-config file with the resolution of the game to make it work.";
                return(finalValues);
            }

            // TODO resize image according to resize-factor. used for large screenshots
            if (ocrConfig.resize != 1 && ocrConfig.resize > 0)
            {
                Bitmap resized = new Bitmap((int)(ocrConfig.resize * ocrConfig.resolutionWidth), (int)(ocrConfig.resize * ocrConfig.resolutionHeight));
                using (var graphics = Graphics.FromImage(resized))
                {
                    graphics.CompositingMode    = CompositingMode.SourceCopy;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode      = SmoothingMode.HighQuality;
                    graphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;

                    using (var wrapMode = new ImageAttributes())
                    {
                        wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                        graphics.DrawImage(screenshotbmp, new Rectangle(0, 0, 1920, 1080), 0, 0, screenshotbmp.Width, screenshotbmp.Height, GraphicsUnit.Pixel, wrapMode);
                    }

                    screenshotbmp?.Dispose();
                    screenshotbmp = resized;
                }
            }

            if (enableOutput && _ocrControl != null)
            {
                _ocrControl.DisplayBmpInOcrControl(screenshotbmp);
            }

            finalValues    = new double[ocrConfig.labelRectangles.Length];
            finalValues[8] = -1; // set imprinting to -1 to mark it as unknown and to set a difference to a creature with 0% imprinting.

            if (changeForegroundWindow)
            {
                Win32API.SetForegroundWindow(Application.OpenForms[0].Handle);
            }


            bool wild = false; // todo: set to true and find out if the creature is wild in the first loop
            int  stI  = -1;

            for (int lbI = 0; lbI < ocrConfig.labelNames.Count; lbI++)
            {
                stI++;
                if (lbI == 8)
                {
                    stI = 8;
                }
                string statName = ocrConfig.labelNames[stI];

                switch (statName)
                {
                case "NameSpecies":
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipName)
                    {
                        dinoName = string.Empty;
                        continue;
                    }
                    break;

                case "Tribe":
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipTribe)
                    {
                        tribeName = string.Empty;
                        continue;
                    }

                    break;

                case "Owner":
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipOwner)
                    {
                        ownerName = string.Empty;
                        continue;
                    }
                    break;
                }

                Rectangle rec = ocrConfig.labelRectangles[lbI];

                // wild creatures don't have the xp-bar, all stats are moved one row up
                if (wild && stI < 9)
                {
                    rec.Offset(0, ocrConfig.labelRectangles[0].Top - ocrConfig.labelRectangles[1].Top);
                }

                Bitmap testbmp = SubImage(screenshotbmp, rec.X, rec.Y, rec.Width, rec.Height);
                //AddBitmapToDebug(testbmp);

                string statOcr;

                try
                {
                    if (statName == "NameSpecies")
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, false, 0.85f, _ocrControl);
                    }
                    else if (statName == "Level")
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, true, 1.1f, _ocrControl).Replace(".", ": ");
                    }
                    else if (statName == "Tribe" || statName == "Owner")
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, false, 0.8f, _ocrControl);
                    }
                    else
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, true, ocrControl: _ocrControl).Trim('.'); // statValues are only numbers
                    }
                }
                catch (OperationCanceledException)
                {
                    OCRText = "Canceled";
                    return(finalValues);
                }

                if (statOcr == string.Empty &&
                    (statName == "Health" || statName == "Imprinting" || statName == "Tribe" || statName == "Owner"))
                {
                    if (wild && statName == "Health")
                    {
                        stI--;
                        wild = false;
                    }
                    continue; // these can be missing, it's fine
                }

                finishedText += (finishedText.Length == 0 ? string.Empty : "\r\n") + statName + ":\t" + statOcr;

                // parse the OCR String

                var r = new Regex(@"^[_\/\\]*(.*?)[_\/\\]*$");
                statOcr = r.Replace(statOcr, "$1");

                if (statName == "NameSpecies")
                {
                    r = new Regex(@".*?([♂♀])?[_.,-\/\\]*([^♂♀]+?)(?:[\(\[]([^\[\(\]\)]+)[\)\]]$|$)");
                }
                else if (statName == "Owner" || statName == "Tribe")
                {
                    r = new Regex(@"(.*)");
                }
                else if (statName == "Level")
                {
                    r = new Regex(@".*\D(\d+)");
                }
                else
                {
                    r = new Regex(@"(?:[\d.,%\/]*\/)?(\d+[\.,']?\d?)(%)?\.?"); // only the second numbers is interesting after the current weight is not shown anymore

                    //if (onlyNumbers)
                    //r = new Regex(@"((\d*[\.,']?\d?\d?)\/)?(\d*[\.,']?\d?\d?)");
                    //else
                    // r = new Regex(@"([a-zA-Z]*)[:;]((\d*[\.,']?\d?\d?)\/)?(\d*[\.,']?\d?\d?)");
                }

                MatchCollection mc = r.Matches(statOcr);

                if (mc.Count == 0)
                {
                    if (statName == "NameSpecies" || statName == "Owner" || statName == "Tribe")
                    {
                        continue;
                    }
                    //if (statName == "Torpor")
                    //{
                    //    // probably it's a wild creature
                    //    // todo
                    //}
                    //else
                    //{
                    finishedText    += "error reading stat " + statName;
                    finalValues[stI] = 0;
                    continue;
                    //}
                }

                if (statName == "NameSpecies" || statName == "Owner" || statName == "Tribe")
                {
                    if (statName == "NameSpecies" && mc[0].Groups.Count > 0)
                    {
                        if (mc[0].Groups[1].Value == "♀")
                        {
                            sex = Sex.Female;
                        }
                        else if (mc[0].Groups[1].Value == "♂")
                        {
                            sex = Sex.Male;
                        }
                        dinoName = mc[0].Groups[2].Value;
                        species  = mc[0].Groups[3].Value;
                        if (species.Length == 0)
                        {
                            species = dinoName;
                        }

                        // remove non-letter chars
                        r       = new Regex("[^a-zA-Z]");
                        species = r.Replace(species, string.Empty);
                        // replace capital I with lower l (common misrecognition)
                        r       = new Regex("(?<=[a-z])I(?=[a-z])");
                        species = r.Replace(species, "l");
                        // readd spaces before capital letters
                        r       = new Regex("(?<=[a-z])(?=[A-Z])");
                        species = r.Replace(species, " ");

                        finishedText += "\t→ " + sex.ToString() + ", " + species;
                    }
                    else if (statName == "Owner" && mc[0].Groups.Count > 0)
                    {
                        ownerName     = mc[0].Groups[0].Value;
                        finishedText += "\t→ " + ownerName;
                    }
                    else if (statName == "Tribe" && mc[0].Groups.Count > 0)
                    {
                        tribeName     = mc[0].Groups[0].Value.Replace("Tobe", "Tribe").Replace("Tdbe", "Tribe").Replace("Tribeof", "Tribe of ");
                        finishedText += "\t→ " + tribeName;
                    }
                    continue;
                }

                if (mc[0].Groups.Count > 2 && mc[0].Groups[2].Value == "%" && statName == "Weight")
                {
                    // first stat with a '%' is damage, if oxygen is missing, shift all stats by one
                    finalValues[4] = finalValues[3]; // shift food to weight
                    finalValues[3] = finalValues[2]; // shift oxygen to food
                    finalValues[2] = 0;              // set oxygen (which wasn't there) to 0
                    stI++;
                }

                var splitRes = statOcr.Split('/', ',', ':');
                var ocrValue = splitRes[splitRes.Length - 1] == "%" ? splitRes[splitRes.Length - 2] : splitRes[splitRes.Length - 1];

                ocrValue = PatternOcr.RemoveNonNumeric(ocrValue);

                double.TryParse(ocrValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.GetCultureInfo("en-US"), out double v); // common substitutions: comma and apostrophe to dot,

                if (statName == "MeleeDamage" && v > 1000)
                {
                    v = v / 10;
                }

                finishedText += $"\t→ {v}";

                // TODO: test here that the read stat name corresponds to the stat supposed to be read
                finalValues[stI] = v;
            }

            OCRText = finishedText;

            // TODO reorder stats to match 12-stats-order

            return(finalValues);

            /*
             * Bitmap grab = Win32Stuff.GetSreenshotOfProcess(screenCaptureApplicationName);
             * AddBitmapToDebug(grab);
             *
             * //grab.Save("E:\\Temp\\Calibration8.png", ImageFormat.Png);
             * if (changeForegroundWindow)
             *  Win32Stuff.SetForegroundWindow(Application.OpenForms[0].Handle);
             */
        }
Example #3
0
        public double[] DoOcr(out string OcrText, out string dinoName, out string species, out string ownerName, out string tribeName, out Sex sex, string useImageFilePath = "", bool changeForegroundWindow = true)
        {
            string finishedText = string.Empty;

            dinoName  = string.Empty;
            species   = string.Empty;
            ownerName = string.Empty;
            tribeName = string.Empty;
            sex       = Sex.Unknown;
            double[] finalValues = { 0 };
            if (ocrConfig == null)
            {
                OcrText = "Error: OCR not configured";
                return(finalValues);
            }

            Bitmap screenShotBmp;

            _ocrControl.debugPanel.Controls.Clear();
            _ocrControl.ClearLists();

            if (File.Exists(useImageFilePath))
            {
                screenShotBmp = (Bitmap)Image.FromFile(useImageFilePath);
            }
            else
            {
                // grab screen shot from ark
                screenShotBmp = Win32API.GetScreenshotOfProcess(screenCaptureApplicationName, waitBeforeScreenCapture, true);
            }
            if (screenShotBmp == null)
            {
                OcrText = "Error: no image for OCR. Is ARK running?";
                return(finalValues);
            }

            if (!CheckResolutionSupportedByOcr(screenShotBmp))
            {
                OcrText = "Error while calibrating: The game-resolution is not supported by the currently loaded OCR-configuration.\n"
                          + $"The tested image has a resolution of {screenShotBmp.Width} × {screenShotBmp.Height} px,\n"
                          + $"the resolution of the loaded ocr-config is {ocrConfig.resolutionWidth} × {ocrConfig.resolutionHeight} px.\n\n"
                          + "Load or create a ocr-config file with the resolution of the game to make it work.";
                return(finalValues);
            }

            // TODO resize image according to resize-factor. used for large screenshots
            if (ocrConfig.resize != 1 && ocrConfig.resize > 0)
            {
                Bitmap resized = new Bitmap((int)(ocrConfig.resize * ocrConfig.resolutionWidth), (int)(ocrConfig.resize * ocrConfig.resolutionHeight));
                using (var graphics = Graphics.FromImage(resized))
                {
                    graphics.CompositingMode    = CompositingMode.SourceCopy;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode      = SmoothingMode.HighQuality;
                    graphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;

                    using (var wrapMode = new ImageAttributes())
                    {
                        wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                        graphics.DrawImage(screenShotBmp, new Rectangle(0, 0, resized.Width, resized.Height), 0, 0, screenShotBmp.Width, screenShotBmp.Height, GraphicsUnit.Pixel, wrapMode);
                    }

                    screenShotBmp.Dispose();
                    screenShotBmp = resized;
                }
            }

            if (enableOutput)
            {
                _ocrControl?.DisplayBmpInOcrControl(screenShotBmp);
            }

            finalValues    = new double[ocrConfig.labelRectangles.Length];
            finalValues[8] = -1; // set imprinting to -1 to mark it as unknown and to set a difference to a creature with 0% imprinting.

            if (changeForegroundWindow)
            {
                Win32API.SetForegroundWindow(Application.OpenForms[0].Handle);
            }

            HammingWeight.InitializeBitCounts();

            // TODO OCR performance measurement
            //var sw = new Stopwatch();
            //sw.Start();

            var whiteThreshold = Properties.Settings.Default.OCRWhiteThreshold;

            bool wild = false; // todo: set to true and find out if the creature is wild in the first loop
            int  stI  = -1;

            var labels = (OcrTemplate.OcrLabels[])Enum.GetValues(typeof(OcrTemplate.OcrLabels));

            for (int lbI = 0; lbI < labels.Length; lbI++)
            {
                stI++;
                if (lbI == 8)
                {
                    stI = 8;
                }
                var label = labels[stI];

                switch (label)
                {
                case OcrTemplate.OcrLabels.NameSpecies:
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipName)
                    {
                        dinoName = string.Empty;
                        continue;
                    }
                    break;

                case OcrTemplate.OcrLabels.Tribe:
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipTribe)
                    {
                        tribeName = string.Empty;
                        continue;
                    }

                    break;

                case OcrTemplate.OcrLabels.Owner:
                    if (ocrConfig.RecognitionPatterns.TrainingSettings.SkipOwner)
                    {
                        ownerName = string.Empty;
                        continue;
                    }
                    break;
                }

                Rectangle rec = ocrConfig.labelRectangles[lbI];

                // wild creatures don't have the xp-bar, all stats are moved one row up
                if (wild && stI < 9)
                {
                    rec.Offset(0, ocrConfig.labelRectangles[0].Top - ocrConfig.labelRectangles[1].Top);
                }

                Bitmap testbmp = SubImage(screenShotBmp, rec.X, rec.Y, rec.Width, rec.Height);
                //AddBitmapToDebug(testbmp);

                string statOcr;

                try
                {
                    if (label == OcrTemplate.OcrLabels.NameSpecies)
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, false, whiteThreshold, rec.X, rec.Y, _ocrControl);
                    }
                    else if (label == OcrTemplate.OcrLabels.Level)
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, true, whiteThreshold, rec.X, rec.Y, _ocrControl).Replace(".", ": ");
                    }
                    else if (label == OcrTemplate.OcrLabels.Tribe || label == OcrTemplate.OcrLabels.Owner)
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, false, whiteThreshold, rec.X, rec.Y, _ocrControl);
                    }
                    else
                    {
                        statOcr = PatternOcr.ReadImageOcr(testbmp, true, whiteThreshold, rec.X, rec.Y, _ocrControl).Trim('.'); // statValues are only numbers
                    }
                }
                catch (OperationCanceledException)
                {
                    OcrText = "Canceled";
                    return(finalValues);
                }

                if (statOcr == string.Empty &&
                    (label == OcrTemplate.OcrLabels.Health || label == OcrTemplate.OcrLabels.Imprinting || label == OcrTemplate.OcrLabels.Tribe || label == OcrTemplate.OcrLabels.Owner))
                {
                    if (wild && label == OcrTemplate.OcrLabels.Health)
                    {
                        stI--;
                        wild = false;
                    }
                    continue; // these can be missing, it's fine
                }

                finishedText += $"{(finishedText.Length == 0 ? string.Empty : "\r\n")}{label}:\t{statOcr}";

                // parse the OCR String

                var r = new Regex(@"^[_\/\\]*(.*?)[_\/\\]*$");
                statOcr = r.Replace(statOcr, "$1");

                if (label == OcrTemplate.OcrLabels.NameSpecies)
                {
                    r = new Regex(@".*?([♂♀])?[_.,-\/\\]*([^♂♀]+?)(?:[\(\[]([^\[\(\]\)]+)[\)\]]$|$)");
                }
                else if (label == OcrTemplate.OcrLabels.Owner || label == OcrTemplate.OcrLabels.Tribe)
                {
                    r = new Regex(@"(.*)");
                }
                else if (label == OcrTemplate.OcrLabels.Level)
                {
                    r = new Regex(@".*\D(\d+)");
                }
                else
                {
                    r = new Regex(@"(?:[\d.,%\/]*\/)?(\d+[\.,']?\d?)(%)?\.?"); // only the second numbers is interesting after the current weight is not shown anymore
                }

                MatchCollection mc = r.Matches(statOcr);

                if (mc.Count == 0)
                {
                    if (label == OcrTemplate.OcrLabels.NameSpecies || label == OcrTemplate.OcrLabels.Owner || label == OcrTemplate.OcrLabels.Tribe)
                    {
                        continue;
                    }
                    //if (statName == "Torpor")
                    //{
                    //    // probably it's a wild creature
                    //    // todo
                    //}
                    //else
                    //{
                    finishedText    += $"error reading stat {label}";
                    finalValues[stI] = 0;
                    continue;
                    //}
                }

                if (label == OcrTemplate.OcrLabels.NameSpecies || label == OcrTemplate.OcrLabels.Owner || label == OcrTemplate.OcrLabels.Tribe)
                {
                    if (label == OcrTemplate.OcrLabels.NameSpecies && mc[0].Groups.Count > 0)
                    {
                        if (mc[0].Groups[1].Value == "♀")
                        {
                            sex = Sex.Female;
                        }
                        else if (mc[0].Groups[1].Value == "♂")
                        {
                            sex = Sex.Male;
                        }
                        dinoName = mc[0].Groups[2].Value;
                        species  = mc[0].Groups[3].Value;
                        if (species.Length == 0)
                        {
                            species = dinoName;
                        }

                        // remove non-letter chars
                        r       = new Regex(@"[^a-zA-Z]");
                        species = r.Replace(species, string.Empty);
                        // replace capital I with lower l (common misrecognition)
                        r       = new Regex(@"(?<=[a-z])I(?=[a-z])");
                        species = r.Replace(species, "l");
                        // readd spaces before capital letters
                        //r = new Regex("(?<=[a-z])(?=[A-Z])");
                        //species = r.Replace(species, " ");

                        finishedText += $"\t→ {sex}, {species}";
                        dinoName      = RemoveUnrecognizedCharacters(dinoName);
                        species       = RemoveUnrecognizedCharacters(species);
                    }
                    else if (label == OcrTemplate.OcrLabels.Owner && mc[0].Groups.Count > 0)
                    {
                        ownerName     = mc[0].Groups[0].Value;
                        finishedText += $"\t→ {ownerName}";
                        ownerName     = RemoveUnrecognizedCharacters(ownerName);
                    }
                    else if (label == OcrTemplate.OcrLabels.Tribe && mc[0].Groups.Count > 0)
                    {
                        tribeName     = mc[0].Groups[0].Value;
                        finishedText += $"\t→ {tribeName}";
                        tribeName     = RemoveUnrecognizedCharacters(tribeName);
                    }
                    continue;
                }

                if (mc[0].Groups.Count > 2 && mc[0].Groups[2].Value == "%" && label == OcrTemplate.OcrLabels.Weight)
                {
                    // first stat with a '%' is damage, if oxygen is missing, shift all stats by one
                    finalValues[4] = finalValues[3]; // shift food to weight
                    finalValues[3] = finalValues[2]; // shift oxygen to food
                    finalValues[2] = 0;              // set oxygen (which wasn't there) to 0
                    stI++;
                }

                var splitRes = statOcr.Split('/', ',', ':');
                var ocrValue = splitRes[splitRes.Length - 1] == "%" ? splitRes[splitRes.Length - 2] : splitRes[splitRes.Length - 1];

                ocrValue = PatternOcr.RemoveNonNumeric(ocrValue);

                double.TryParse(ocrValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.GetCultureInfo("en-US"), out double v); // common substitutions: comma and apostrophe to dot,

                finishedText += label == OcrTemplate.OcrLabels.Level ? $"\t→ {v:F0}" : $"\t→ {v:F1}";

                // TODO: test here that the read stat name corresponds to the stat supposed to be read
                finalValues[stI] = v;

                string RemoveUnrecognizedCharacters(string s) => s.Replace("�", string.Empty);
            }

            OcrText = finishedText;

            // TODO OCR performance output
            //sw.Stop();
            //Debug.WriteLine($"OCR took {sw.ElapsedMilliseconds} ms.");

            // TODO reorder stats to match 12-stats-order

            return(finalValues);
        }