NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# C# .NET 매크로 프로그램 만들기. (인공지능 딥러닝을 사용해서 화면 인식하기)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 앞서 이미지 전체 매치 액션을 개발했는데요. 이와 거의 비슷한 옵션을 가진 액션이 하나 더 있습니다. 방식은 완전히 다르지만요. 오늘 알아볼 내용은 딥러닝을 이용해서 윈도우 화면을 인식하는 방법입니다. 근래에 와서는 이미지 딥러닝은 다크넷의 욜로로 거의 통합되는듯한 분위기입니다. 어쩌면 한참전부터 그랬었는데 제가 모르고 있었던걸지도 모르겠군요.

     

    엔지엠 매크로에는 욜로 V3와 욜로 V8이 포함되어 있습니다. 그리고, 각각 CPU와 GPU 모드가 있습니다. 새로운 버전에서는 욜로 V3는 삭제하고, 욜로 V8만 사용할 예정입니다. 아무래도 인식율이나 속도면에서 욜로 V8이 훨씬 좋기 때문인데요. 이외에도 모델 파일의 용량도 10분의 1 수준이라서 관리측면에서도 뛰어납니다.

     

    대부분의 기능은 이미지 전체 매치와 동일하기 때문에 모델 파일을 복사해서 새로운 모델을 만들고, 세부 내용만 약간 바꾸면 될거 같네요.

    public class YoloMatchesModel : BaseModel, ISearchArea, IImageConditionResultSave, IMouseTracker

     

    이미지 전체 매치는 찾을 이미지와 찾아야 하는 화면 이미지 2개가 필요한데요. 일반적으로 Source, Target 이미지라고 부릅니다. 타겟 이미지에 소스 이미지가 있는지 체크하는거니까요. 하지만, 욜로에서는 소스 이미지가 필요 없습니다. 데이타셋을 만들어서 모델을 작성했기 때문입니다. 욜로를 이용해서 데이타셋을 만들고, 학습시켜서 모델을 만드는 방법은 아래 글을 참고하시면 됩니다.

    [ 딥러닝 환경구축 ]

    [ 데이타셋 만들기 ]

    [ 딥러닝 학습하기 ]

    [ 욜로 딥러닝 사용방법 ]

     

    내용이 다소 복잡해 보이지만, 한두번 하다보면 금방 익숙해집니다. 원래 처음이 어려운법이죠^^

     

    이미지 전체 매치와 속성이 90프로 동일하지만, 욜로 매치에는 몇가지 속성이 추가되어야 합니다. 아래 속성들은 데이타셋을 만들 때 입력했던 클래스를 보여주는 결과 데이터입니다. 클래스는 이름, 아이디, 정확도가 있습니다. 이름과 아이디는 데이타셋을 만들 때 사용자가 작성하지만, 정확도(Confidence: 신뢰)는 액션이 실행된 후 결과값으로 나옵니다. 아래는 목록이므로 인덱스 또는 정렬에 따른 값을 표시하는 단일 항목들도 추가해야 합니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassNames")]
    [LocalizedDescription("ClassNames")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public string[]? ClassNames { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassIds")]
    [LocalizedDescription("ClassIds")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public int[]? ClassIds { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassConfidences")]
    [LocalizedDescription("ClassConfidences")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public int[]? ClassConfidences { get; set; }

     

    아래는 단일 항목들입니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassName")]
    [LocalizedDescription("ClassName")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public string? ClassName { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassId")]
    [LocalizedDescription("ClassId")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public int? ClassId { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ClassConfidence")]
    [LocalizedDescription("ClassConfidence")]
    [Browsable(true)]
    [ReadOnly(true)]
    [DefaultValue(null)]
    public int? ClassConfidence { get; set; }

     

    딥러닝은 대부분 그래픽 카드를 이용해서 연산을 합니다. 요즘에는 기술과 알고리즘이 좋아져서 예전처럼 큰 차이가 나거나 하지는 않습니다. 그렇더라도 GPU를 사용하면 좀 더 빠르게 처리할 수 있을겁니다. 물론, 그래픽 카드가 좋아야 합니다. 그리고, 쿠다 관련 인터페이스도 모두 설치가 되어 있어야 합니다.

     

    이제 욜로 딥러닝을 이용해서 이미지를 찾는 부분 코딩을 해볼까요? 아래와 같이 모델 선택 속성이 비어 있는지 체크부터 해줍니다.

    var id = base.Execute(player);
    
    if (!Ai.Common.Helper.NullCheckAndWriteLine(player, nameof(SelectYoloModel), SelectYoloModel))
        return id;

     

    대상 이미지 다시 말해서 윈도우 화면이나 프로그램 캡쳐한 이미지를 욜로 모델과 같이 넘겨주면, 결과 정보를 받아올 수 있습니다.

    var yoloInfos = Ai.Api.YoloManager.Manager.Predictor(target, SelectYoloModel, AccuracyRate, UseGpu);

     

    욜로 매니저의 프리딕터(Predictor: 예언자)는 잘 사용하지 않는데... 아무튼, 메소드를 호출하면 아래와 같은 결과 데이터가 만들어집니다.

    List<Tuple<System.Drawing.Rectangle, float, int, string>>

     

    실제 nuget을 통해 설치한 욜로 라이브러리는 디텍트 메소드를 통해서 이미지를 분석합니다.

    var results = _yoloV8Predictor.Detect(image);

     

    results의 box 인스턴스 안에 모든 정보가 들어 있는데요. 엔지엠 매크로의 모든 라이브러리에 패키지를 설치하는건 불편하고 관리가 안되니 Ai 코어에 하나만 설치하고, 닷넷 인스턴스로 변환해서 들고 다니면 됩니다. 그래서, 아래와 같이 튜플을 이용해서 데이터를 변환해주고 있습니다.

    for (int i = 0; i < results.Boxes.Length; i++)
    {
        var info = results.Boxes[i];
    
        if (info.Confidence > accuracyRate * 0.01f)
        {
            result.Add(new Tuple<System.Drawing.Rectangle, float, int, string>(
                new System.Drawing.Rectangle(info.Bounds.X, info.Bounds.Y, info.Bounds.Width, info.Bounds.Height),
                info.Confidence,
                info.Class.Id,
                info.Class.Name));
        }
    }

     

    이 후 로직은 이미지 전체 매치와 동일하게 찾아진 오브젝트들을 어떻게 처리할지에 대한 내용입니다.

    switch (Sort)
    {
        case Definition.Sort.Ascending:
            switch (SortOptionXY)
            {
                case Definition.PointFormulaOption.All:
                    rects = rects.OrderBy(o => o.Location).ToList();
                    break;
                case Definition.PointFormulaOption.X:
                    rects = rects.OrderBy(o => o.X).ToList();
                    break;
                case Definition.PointFormulaOption.Y:
                    rects = rects.OrderBy(o => o.Y).ToList();
                    break;
            }
            break;

     

    정렬에 대한 처리가 완료되면, 마우스 처리도 해줍니다.

    var drag = new Mouse.DragModel()
    {
        Steps = Steps,
        Interval = Interval,
        Coordinate = start,
        CoordinateEnd = end,
        MouseButton = MouseButton,
        UseRelative = UseRelative,
        InputType = InputType
    };
    drag.Execute(player);
    break;

     

    테스트에 사용할 이미지는 아래와 같은 사람입니다.

    VkhJjyb.png

     

     

    저는 이미 학습된 모델을 가지고 있어서 해당 모델을 사용하도록 하겠습니다. 그리고, 찾기 영역을 그림판의 안쪽으로 설정하세요.

    Ot0pToC.png

     

     

    이제 간단하게 테스트를 해볼께요. 아래 동영상처럼 학습된 모델에 따라서 다양한 것들을 처리할 수 있습니다.

     

     

    마지막으로 마우스 이동에서 전부 이어서 드래그하는 방법도 알아볼께요. 우선, 드래그 옵션에 전체 드래그를 하나 추가했습니다.

    [LocalizedCategory("Drag")]
    [LocalizedDisplayName("UseAllDrag")]
    [LocalizedDescription("UseAllDrag")]
    [Browsable(true)]
    [DefaultValue(false)]
    public bool UseAllDrag { get; set; }

     

    로직은 복잡할게 없습니다. 단순히 생각해보면, 시작점과 끝점을 가진 여러개의 좌표를 순서대로 시작, 다음, 시작, 다음... 이어가다가 마지막에서만 다음과 끝으로 마무리하면 됩니다. 이렇게 로직을 만들고, 여러개의 오브젝트가 검출될 수 있는 이미지로 변경하고 다시 실행 해볼께요.

     

     

    위 동영상에서 설명하고 있듯이 찾은 모든 오브젝트를 연결해서 마우스로 드래그할 수 있었습니다. 이전 버전에서는 없었던 기능인데요. 새로운 엔지엠 매크로는 다양한 방식으로 사용자가 응용할 수 있도록 많은 기능들이 포함되어 있습니다. 하지만, 불필요한 설정들은 대부분 제거 했습니다. 아무래도 이미지 처리 부분에 있어서 여러가지 설정들이 필요해서 만든 것들인데요. 점점 이미지 처리 기술이 발전하면서 이런 전처리에 관련된 내용들이 큰 의미가 없어졌습니다.

     

    쉽고, 빠르게 가는게 베스트입니다. 이런 트렌드에 맞게 가능하면 성능은 높이고, 기능은 심플하게 만드는데 중점을 두어야겠습니다.

     

    개발자에게 후원하기

    MGtdv7r.png

     

    추천, 구독, 홍보 꼭~ 부탁드립니다.

    여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~

    감사합니다~

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.