Example #1
0
        private void HandleHotkey(object sender, KeyPressedEventArgs e)
        {
            // Capture the primary screen
            Bitmap   bitmap   = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
            // Save the image as jpg for possible upload later
            bitmap.Save(@"img\screenshot.jpg", ImageFormat.Jpeg);
            Image <Bgr, byte> image = new Image <Bgr, byte>(bitmap);

            // Apply an adaptive threshold to improve OCR recognition
            image = image
                    .Convert <Gray, byte>()
                    .ThresholdAdaptive(
                new Gray(255),
                AdaptiveThresholdType.GaussianC,
                Emgu.CV.CvEnum.ThresholdType.Binary,
                51,
                new Gray(-10)
                ).Convert <Bgr, byte>();
            bool errors     = false;
            var  platvalues = new int[4] {
                -1, -1, -1, -1
            };
            var subimages = new Image <Bgr, byte> [8];

            for (int i = 0; i < 8; i++)
            {
                // Extract the subimage containing the item name
                // this has to be done sequentially and not in parallel
                // TODO: multiline names
                subimages[i] = image.Copy(rectangles[i]);
            }
            // returns a funtion that tries to recognize item i
            // if big is true, considers a 2-line item name
            Action <int> recognize(bool big)
            {
                return((i) => {
                    var subimage = subimages[big ? 4 + i : i];
                    // Save the image as jpg for possible upload later
                    subimage.ToBitmap().Save($@"img\{i}.jpg", ImageFormat.Jpeg);
                    // Only one OCR instance per thread or runtime errors happen
                    var ocr = new Tesseract(
                        @".\tessdata",
                        "weng",
                        OcrEngineMode.TesseractOnly,
                        // Fun fact: no Q or J appears on any name
                        "ABCDEFGHIJKLMNOPRSTUVWXYZ&"
                        );
                    ocr.SetImage(subimage);
                    ocr.Recognize();
                    var str = ocr.GetUTF8Text().Trim();
                    // Save the originally recognized text
                    reportStrings[i, 0] = str;
                    var item = EditDistance.BestMatch(str);
                    // Save the fixed name
                    reportStrings[i, 1] = item;
                    if (item == "NOT RECOGNIZED")
                    {
                        if (big)
                        {
                            errors = true;
                        }
                        else
                        {
                            recognize(true)(i);
                        }
                    }
                    else
                    {
                        platvalues[i] = GetWarframeMarketPrice(item);
                    }
                });
            }

            // We run both the OCR and the warframe.market query in parallel
            Parallel.For(0, 4, recognize(false));
            // Labels can only be edited in the main thread
            for (int i = 0; i < 4; i++)
            {
                var name = reportStrings[i, 1];
                labels[i, 0].Text = Items.Normalize(name);
                if (platvalues[i] >= 0)
                {
                    labels[i, 1].Text = Items.Ducats[name] + "";
                    labels[i, 2].Text = platvalues[i] + "";
                }
                else
                {
                    labels[i, 1].Text = labels[i, 2].Text = "???";
                }
            }
            // Minimize and restore window to bring it to the front
            WindowState = FormWindowState.Minimized;
            WindowState = FormWindowState.Normal;
            if (errors && Properties.Settings.Default.submit_errors)
            {
                SubmitErrorAsync();
            }
            else
            {
                submitErrorButton.Enabled = true;
            }
        }