C#/C# 리니지m/

C#으로 만드는 리니지m 매크로 (2-1)hp인식 - tesseract

2019. 10. 2.

tesseract 설치와 기본사용법은 링크 참조

2019/10/01 - [프로그래밍/C# 프로그래밍] - C# tesseract 설치

2019/10/01 - [프로그래밍/C# 프로그래밍] - C# tesseract를 이용한 OCR

 

 

지난 시간 프로젝트에 이어서 하겠습니다.

조그마한 picturebox 1

label 2

button 2개를 추가해줍니다.

 

using문 추가해주고

using Tesseract;

 

버튼2 클릭 이벤트

private void Button2_Click(object sender, EventArgs e)
        {
            Rectangle rect = new Rectangle(130, 13, 85, 20);
            // x,y 시작좌표 x,y범위 생성

            Bitmap cap = screen.Clone(rect, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            // 캡쳐뜬 이미지에서 위의 Rect 만큼 자르기

            cap = new Bitmap(cap, new Size(170, 40));
            // 인식률을 높이기위해 두배크기로 리사이즈

            for(int i = 0; i &lt cap.Width; i++)
            {
                for(int j = 0; j &lt cap.Height; j++)
                {
                    Color c = cap.GetPixel(i, j);
                    int binary = (c.R + c.G + c.B) / 3;

                    if (binary &gt 190)
                        cap.SetPixel(i, j, Color.White);
                    else
                        cap.SetPixel(i, j, Color.Black);
                }
            }
            // 간단한 for을 통한 Binary(이진화)

            screen = cap;

            pictureBox2.Image = screen;
            // picturebox2 에 자르고 키우고 이진화한 이미지 띄우기
        }
        

 

주석 설명처럼 전체 이미지에서 hp숫자 부분만 캡처 후

인식률을 높이기위한 전처리 소스입니다.

 

버튼3 클릭 이벤트

private void Button3_Click(object sender, EventArgs e)
        {
            Pix pix = PixConverter.ToPix(screen);
            
            var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.TesseractOnly);
            // tesseractengine 생성
            string whitelist = "0123456789/";
            engine.SetVariable("tessedit_char_whitelist", whitelist);
            // 인식률을 높이기위한 숫자와 '/' 만 화이트리스트 적용

            var result = engine.Process(pix);

            string HP = result.GetText();

            HP = HP.Replace(" ", "");
            // 공백제거

            label1.Text = HP;

            string[] split = HP.Split('/');
            // 현재와 맥스수치를 나눠주기 구분점 '/'
            label2.Text = "HP : " + (Convert.ToSingle(split[0]) * 100 / Convert.ToSingle(split[1])).ToString("##.##") + "%";
        }
        

 

버튼2에서 새로만든 이미지를 통해

tesseract를 이용하여 숫자인식

더불어 %로 표기하기위한 소스입니다.

 

이제 디버깅후 테스트 해봅시다.

실행후 앱플레이어명을 적은후

버튼1 클릭

지난 시간에 했던것 처럼 잘 캡처 되었네요

이제 버튼2 클릭

hp부분만 캡처자르기되어 이진화까지 잘된것을 볼 수 있습니다.

이제 버튼3 클릭

화면에 보이는 hp와 동일한 숫자가 인식되었고 %계산도 잘되었네요.

 

tesseract의 장점은 상용화 되어있어서 편하게 접할 수 있다 지만

단점으로는 전처리를 아무리해도 오인식하는 경우가 생기기도 합니다.

또 생각보다 컴퓨터 리소스를 많이 잡아먹는다는점

후에 하겠지만 반복으로 돌리면 리소스가 치솟는걸 보게됩니다

하여 정확하진않지만 픽셀서치로 근사% 구하는법 을 다음시간에 알려드리겠습니다.

 

더보기
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Tesseract;

namespace imagesearch
{
    public partial class Form1 : Form
    {
        [DllImport("User32", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string IpClassName, string IpWindowName);

        [DllImport("user32")]
        private static extern IntPtr FindWindowEx(IntPtr hWnd1, int hWnd2, string lp1, string lp2);

        [DllImport("user32.dll")]
        internal static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcblt, int nFlags);

        Bitmap screen;

        public Form1()
        {
            InitializeComponent();
        }
        
        private void Button1_Click(object sender, EventArgs e)
        {
            string a = textBox1.Text;

            IntPtr b = FindWindow(null, a);

            IntPtr c = FindWindowEx(b, 0, "RenderWindow", "TheRender");

            Graphics gdata = Graphics.FromHwnd(c);

            Rectangle rect = Rectangle.Round(gdata.VisibleClipBounds);

            Bitmap bmp = new Bitmap(rect.Width, rect.Height);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                IntPtr hdc = g.GetHdc();
                PrintWindow(c, hdc, 0x2);
                g.ReleaseHdc(hdc);
            }

            screen = new Bitmap(bmp, new Size(1280, 720));

            pictureBox1.Image = screen;
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            Rectangle rect = new Rectangle(130, 13, 85, 20);
            // x,y 시작좌표 x,y범위 생성

            Bitmap cap = screen.Clone(rect, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            // 캡쳐뜬 이미지에서 위의 Rect 만큼 자르기

            cap = new Bitmap(cap, new Size(170, 40));
            // 인식률을 높이기위해 두배크기로 리사이즈

            for(int i = 0; i &lt cap.Width; i++)
            {
                for(int j = 0; j &lt cap.Height; j++)
                {
                    Color c = cap.GetPixel(i, j);
                    int binary = (c.R + c.G + c.B) / 3;

                    if (binary &gt 190)
                        cap.SetPixel(i, j, Color.White);
                    else
                        cap.SetPixel(i, j, Color.Black);
                }
            }
            // 간단한 for을 통한 Binary(이진화)

            screen = cap;

            pictureBox2.Image = screen;
            // picturebox2 에 자르고 키우고 이진화한 이미지 띄우기
        }

        private void Button3_Click(object sender, EventArgs e)
        {
            Pix pix = PixConverter.ToPix(screen);
            
            var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.TesseractOnly);
            // tesseractengine 생성
            string whitelist = "0123456789/";
            engine.SetVariable("tessedit_char_whitelist", whitelist);
            // 인식률을 높이기위한 숫자와 '/' 만 화이트리스트 적용

            var result = engine.Process(pix);

            string HP = result.GetText();

            HP = HP.Replace(" ", "");
            // 공백제거

            label1.Text = HP;

            string[] split = HP.Split('/');
            // 현재와 맥스수치를 나눠주기 구분점 '/'
            label2.Text = "HP : " + (Convert.ToSingle(split[0]) * 100 / Convert.ToSingle(split[1])).ToString("##.##") + "%";
        }
    }
}