티스토리 뷰

늦었지만 강의 마무리 하도록 하겠습니다.

마지막 강의를 시작하기 전에 2강에서 댓글로 질문해주신 부분 답변드리고 시작할게요.

 

1. OpenCvSharp.OpenCVException 관련에러

- 보통 이 에러가 나는 경우는 비교대상 ScreenMat 이미지가 FindMat 보다 작아서 발생합니다.

두 이미지가 정상적인지 확인해보세요~!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        public void searchIMG(Bitmap screen_img, Bitmap find_img)
        {
            //스크린 이미지 선언
            using (Mat ScreenMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(screen_img))
            //찾을 이미지 선언
            using (Mat FindMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(find_img))
            //스크린 이미지에서 FindMat 이미지를 찾아라
            using (Mat res = ScreenMat.MatchTemplate(FindMat, TemplateMatchModes.CCoeffNormed))
            {
                //찾은 이미지의 유사도를 담을 더블형 최대 최소 값을 선언합니다.
                double minval, maxval = 0;
                //찾은 이미지의 위치를 담을 포인트형을 선업합니다.
                OpenCvSharp.Point minloc, maxloc;
                //찾은 이미지의 유사도 및 위치 값을 받습니다. 
                Cv2.MinMaxLoc(res, out minval, out maxval, out minloc, out maxloc);
                Debug.WriteLine("찾은 이미지의 유사도 : " + maxval);
 
                //이미지를 찾았을 경우 클릭이벤트를 발생!!
                if(maxval >= 0.8)
                {
                    InClick(maxloc.X, maxloc.Y);
                }
            }
        }
cs


2. 클릭 이슈

모모앱플레이어 일경우에만 확인해서 클릭이벤트를 내려주는 함수 입니다.

다른 용도로 사용하면 클릭 이벤트가 발생하지 않습니다.

오직 모모앱플레이어에서만 동작합니다.~!

다른 프로그램에서 사용하고 싶으시면 FindWindowEx 함수의 값들을 바꿔줘야 합니다.

현재에는 "RenderWindow""TheRender" 모모용으로 작성되어 있습니다.

원하시는 프로그램을 실행해서 실제 클릭값을 전달할 핸들이무엇인지 알아내야합니다.(spy++로 확인가능)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        //x,y 값을 전달해주면 클릭이벤트를 발생합니다.
        public void InClick(int x, int y)
        {
            //클릭이벤트를 발생시킬 플레이어를 찾습니다.
            IntPtr findwindow = FindWindow(null, AppPlayerName);
            if (findwindow != IntPtr.Zero)
            {
                //플레이어를 찾았을 경우 클릭이벤트를 발생시킬 핸들을 가져옵니다.
                IntPtr hwnd_child = FindWindowEx(findwindow, IntPtr.Zero, "RenderWindow""TheRender");
                IntPtr lparam = new IntPtr(x | (y << 16));
 
                //플레이어 핸들에 클릭 이벤트를 전달합니다.
                SendMessage(hwnd_child, WM_LBUTTONDOWN, 1, lparam);
                SendMessage(hwnd_child, WM_LBUTTONUP, 0, lparam);
            }
        }
cs

 

3. 캡처 안됨 이슈

OS 별로 PrintWindow 전달 인자값을 변경해줘야합니다.

윈10일경우 0x2 이외에는 0x0 설정하고 PrintWindow 호출하시면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
            int nFlags = 0;
 
            OperatingSystem os = Environment.OSVersion;
            Version v = os.Version;
            if (v.Major == 10){
                nFlags = 0x2;
            }
            else{
                nFlags = 0x0;
            }
 
            using (Graphics gfxBmp = Graphics.FromImage(bmp))
            {
                IntPtr hdc = gfxBmp.GetHdc();
                PrintWindow(hwnd, hdc, nFlags);
                gfxBmp.ReleaseHdc(hdc);
            }
cs


4. 찾은 이미지 클릭 위치가 안맞음

InClick 좌표값에 X좌표 + 이미지가로/2 , Y좌표 + 이미지세로/2 - 모모앱 메뉴 사이즈 를 해주면 이미지 가운데를 잘 클릭합니다.

1
2
3
4
5
6
                //이미지를 찾았을 경우 클릭이벤트를 발생!!
                int offsetY = 35;
                if(maxval >= 0.8)
                {
                    InClick(maxloc.X + FindMat.Width/2, maxloc.Y + FindMat.Height / 2 - offsetY);
                }
cs

 

자 이제 마지막 강의로는 모모앱플레이어의 사이즈가 변경이 되어도 이미지를 찾고 클릭하는 방법을 알아보도록하겠습니다.

방법부터 설명하도록 하겠습니다.

아주 간단한 방법입니다.

모모앱플레이어의 캡처된 화면을 임의로 고정된 사이즈로 변경해서 실제사이즈와 변경된 사이즈로 비율을 구하고 찾은 이미지의 좌표값에 비율을 곱해주는 방법입니다.

차근 차근 해보시면 무슨 말인지 알게 될 거에요 !!

자 먼저 모모앱플레이어가 어떤 사이즈로 설정해놔도 특정 크기로 변경할 사이즈를 정합시다.

1
2
3
4
5
6
        //모모앱플레이어 크기를 저정할 변수
        double full_width = 0;
        double full_height = 0;
        //모모앱플레이어 지정한 크기
        double pix_width = 850;
        double pix_height = 494;
cs

저는 모니터화면에서 모모앱플레이어 창크기가 전체화면에 1/4 정도되는 사이즈로 줄여서 가로세로 크기 확인 후 850 494 로 지정하였습니다.

이제 캡쳐해오는 화면을 850 494 지정한 사이즈로 변경해보겠습니다.

먼저 Form1.cs 디자인 창으로 들어가서 아래와같이 pictureBox1 사이즈를 충분히 크게 만들어주세요.

(캡처해서 사이즈 변경한 스크린샷을 보여줄거에요.)

 

button1_Click 함수로 돌아가서 28 , 29 번 줄을 추가해줍시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr findwindow = FindWindow(null, AppPlayerName);
            if (findwindow != IntPtr.Zero)
            {
                //플레이어를 찾았을 경우
                Debug.WriteLine("앱플레이어 찾았습니다.");
 
                //찾은 플레이어를 바탕으로 Graphics 정보를 가져옵니다.
                Graphics Graphicsdata = Graphics.FromHwnd(findwindow);
 
                //찾은 플레이어 창 크기 및 위치를 가져옵니다. 
                Rectangle rect = Rectangle.Round(Graphicsdata.VisibleClipBounds);
 
                //플레이어 창 크기 만큼의 비트맵을 선언해줍니다.
                Bitmap bmp = new Bitmap(rect.Width, rect.Height);
 
                //비트맵을 바탕으로 그래픽스 함수로 선언해줍니다.
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    //찾은 플레이어의 크기만큼 화면을 캡쳐합니다.
                    IntPtr hdc = g.GetHdc();
                    PrintWindow(findwindow, hdc, nFlags);
                    g.ReleaseHdc(hdc);
                }
 
                //캡처해온 이미지 사이즈를 변경하여 저장합니다.
                System.Drawing.Size resize = new System.Drawing.Size((int)pix_width, (int)pix_height);
                bmp = new Bitmap(bmp, resize);
 
                // pictureBox1 이미지를 표시해줍니다.
                pictureBox1.Image = bmp;
 
                searchIMG(bmp, Stone_Img);
            }
            else
            {
                //플레이어를 못찾을경우
                Debug.WriteLine("못찾았어요");
            }
        }
cs

 

우리가 원하는 사이즈로 변경이 되었는지 확인해봅시다 프로그램을 실행하고 버튼을 눌렀을 때 아래와 같이 나온다면 정상적인 상태입니다.

 

이제 찾을 이미지를 다시 저장합시다.

앞에서는 듀랑고의 돌을 찾는걸로 했는데요 이번에는 라그나로크m 에서 이미지를 찾아 저장하도록하겠습니다.

!!중요. 모모앱플레이어에서 캡처한 파일이 아닌 현재 우리가 만들고 있는 프로그램 실행해서

위에 보이는 창 스크린에서 캡처를 해주셔야합니다.

 

프로젝트 폴더 ->img 폴더 -> stone.PNG 를 저장해줬습니다.

이제는 비율을 계산해서 클릭하는 부분을 수정해보도록 합시다.

button1_Click 함수에서 현재 모모앱플레이어의 가로 세로 크기를 저장해줍시다. (16, 17 번째줄)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr findwindow = FindWindow(null, AppPlayerName);
            if (findwindow != IntPtr.Zero)
            {
                //플레이어를 찾았을 경우
                Debug.WriteLine("앱플레이어 찾았습니다.");
 
                //찾은 플레이어를 바탕으로 Graphics 정보를 가져옵니다.
                Graphics Graphicsdata = Graphics.FromHwnd(findwindow);
 
                //찾은 플레이어 창 크기 및 위치를 가져옵니다. 
                Rectangle rect = Rectangle.Round(Graphicsdata.VisibleClipBounds);
 
                //현재 모모앱플레이어 화면 크기를 지정해줍니다.
                full_width = rect.Width;
                full_height = rect.Height;
 
                //플레이어 창 크기 만큼의 비트맵을 선언해줍니다.
                Bitmap bmp = new Bitmap(rect.Width, rect.Height);
 
                //비트맵을 바탕으로 그래픽스 함수로 선언해줍니다.
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    //찾은 플레이어의 크기만큼 화면을 캡쳐합니다.
                    IntPtr hdc = g.GetHdc();
                    PrintWindow(findwindow, hdc, nFlags);
                    g
cs

 

 

searchIMG 함수로 와서 클릭시에 좌표값을 모모앱 크기에 맞게 변환하도록 하겠습니다.

먼저 22 23 번 줄은 강의2번에서 댓글로 달아주신 부분입니다. 체크시 이미지 크기 반영하여 클릭 위치 조정했습니다.

26번줄이 우리가 임의로 지정한 사이즈 대비 현재 모모앱플레이어크기 비율을 계산하는 구간입니다.

여기서 나온 값을 실제 모모앱플레이어 화면에 적용하기 위해 곱해줍니다.(32번 줄)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        public void searchIMG(Bitmap screen_img, Bitmap find_img)
        {
            //스크린 이미지 선언
            using (Mat ScreenMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(screen_img))
            //찾을 이미지 선언
            using (Mat FindMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(find_img))
            //스크린 이미지에서 FindMat 이미지를 찾아라
            using (Mat res = ScreenMat.MatchTemplate(FindMat, TemplateMatchModes.CCoeffNormed))
            {
                //찾은 이미지의 유사도를 담을 더블형 최대 최소 값을 선언합니다.
                double minval, maxval = 0;
                //찾은 이미지의 위치를 담을 포인트형을 선업합니다.
                OpenCvSharp.Point minloc, maxloc;
                //찾은 이미지의 유사도 및 위치 값을 받습니다. 
                Cv2.MinMaxLoc(res, out minval, out maxval, out minloc, out maxloc);
                Debug.WriteLine("찾은 이미지의 유사도 : " + maxval);
 
                //이미지를 찾았을 경우 클릭이벤트를 발생!!
                int offsetY = 35;
 
                //찾은 이미지를 클릭할 x,y 좌표값
                int click_x = maxloc.X + FindMat.Width / 2;
                int click_y = maxloc.Y + FindMat.Height / 2 - offsetY;
 
                //임의로 줄인 캡처화면 실제 모모앱플레이어화면 비율 계산
                double change_size = full_width / pix_width;
 
                if (maxval >= 0.8)
                {
                    //클릭할 위치에 비율만큼 곱해서 실제 모모앱플레이어 크기에 맞게 좌표값 변환 후 클릭
                    InClick((int)(click_x * change_size), (int)(click_y * change_size));
                }
            }
        }
cs

자 실행해보도록 하죠.

 

클릭하는 크기가 정확하지는 않습니다. 아무래도 비율로 계산하다보니 오차가 조금 있습니다. 참고부탁드릴게요.~!

 

이 블로그가 도움이 되었다면, 후원을 부탁드립니다
http://yc0345.tistory.com/218

댓글