NGMsoftware

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

    학습


    C# C# .NET 매크로 프로그램 만들기. (선착순, 예약, 티켓팅 매크로의 자동 입력 방지 문자 처리 방법 - CAPTCHA 캡…

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 오늘은 OCR 기능에 대해 알아볼텐데요. 엔지엠 매크로에는 이미 OCR 문자 판독 기능이 포함되어 있습니다. OCR(Optical Character Recognition)은 윈도우 화면에서 텍스트를 추출하는 방법입니다. 자료 수집 및 서류 보관에 대한 중요성이 커짐에 따라 문서 전자화 시스템을 도입하고 있는 기업들이 증가하고 있습니다. 이러한 가운데 수작업 위주의 입력 저장 방식을 혁신하기 위한 기술로 광학문자인식이라고 하는 OCR이 급부상하였습니다. 스캐너를 통해 입력된 문서 영상에서 문자에 해당하는 부분의 내용을 인식하는 기술을 말합니다.

     

    하지만, 요즘은 실시간으로 윈도우 화면을 스캔해서 텍스트를 추출할 수 있는데요. 문제는 이렇게 스캔한 텍스트를 문서화 하거나 선착순, 예약 또는 티켓팅과 같이 자동화를 방지하고자 하는 캡챠(CAPCHA)를 인식하는데 사용하기도 합니다. 기술적으로 보면 다양하지만, 거의 대부분은 무료로 사용할 수 있는 테서랙트(Tesseract)를 많이 이용하고 있습니다. 하지만, 단순 학습만 시킨 모델에서 캡챠를 인식하는데는 한계가 분명 존재합니다.

     

    그래서, 인공지능과 결합된 OCR을 사용해서 문제를 해결해야 합니다. 이와 관련된 솔루션들이 많습니다. 캡차에만 특화된 서비스도 존재하니까요. 엔지엠 매크로는 범용적인 개발도구라서 기본적인 내용을 포함하고, 사용자가 서비스를 이용하는 방식으로 개발되어 있습니다. 또한, 기능을 확장해서 더 좋은 품질의 서비스를 만들기 위한 방법들도 제공하고 있습니다. 만약, 내가 어도비의 OCR 서비스를 이용하고 있다면 커스텀 액션으로 엔지엠 매크로에 추가할 수 있습니다. 복잡한 비즈니스 로직은 엔지엠 매크로가 처리하고, 윈도우 화면 또는 이미지에서 텍스트를 추출하는건 어도비의 OCR이 처리하면 됩니다.

     

    여기에서는 구글의 비전 AI를 이용해서 캡차(자동 입력 방지 문자)를 어떻게 인식할 수 있는지 알아보도록 하겠습니다. 우선, 모델을 하나 추가해야겠죠?

    HJRdU4F.png

     

     

    구글 API를 사용하기 위해서는 미리 구글 계정을 만들고, API 사용 신청을 해야 합니다. 대부분 무료로 이용할 수 있지만 일부 API는 유료로 사용해야 하기 때문에 신용카드를 결제 정보에 등록해야 합니다. 저는 신용카드를 사용하지 않습니다. 체크카드만 가지고 있는데요. 다행스럽게도 체크카드도 등록할 수 있습니다. 할부나 빚의 위험성을 잘 알기 때문에 신용카드나 대출을 사용하지 않습니다. 그래서, 신용카드가 없는데요. 약간 불편할 때도 있지만 생활에 크게 어려운점은 없습니다. 항상 주어신 상황에 맞게 살아가는게 좋은거 같아요. 미래의 수입까지 현재로 끌어와서 사용하면 지금은 당장 편할지 몰라도 미래에는 더 많은 노동을 해야하고 시간을 갈아 넣어야 하거든요.

     

    구글 API 폴더에 미리 다른 API까지 모두 추가해둔 상태입니다. 클래스만 만들어놓고 아직 코딩은 안했으니까요. 다음에 같이 하나씩 해보도록 할께요. 일단은 비전 AI를 만들어서 사용 해보겠습니다. 아래와 같이 윈도우 화면 또는 이미지에서 추출한 텍스트를 표시할 결과 속성을 만들어줍니다. 아래와 같이 각각 결과를 담을 속성도 만들었습니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("Result")]
    [LocalizedDescription("Result")]
    [Browsable(true)]
    [DefaultValue(null)]
    [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
    public string? Result { get; set; }

     

    구글의 비전 AI가 분석 후 처리 결과를 보내줄 때 크게 3개의 카테고리에 담아서 줍니다. 분석한 텍스트와 정확도 그리고, 문자들의 위치입니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultDescription")]
    [LocalizedDescription("ResultDescription")]
    [Browsable(true)]
    [DefaultValue(null)]
    [EditorAttribute(typeof(MultilineStringEditor), typeof(UITypeEditor))]
    public string? ResultDescription { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultScore")]
    [LocalizedDescription("ResultScore")]
    [Browsable(true)]
    [DefaultValue(typeof(float), "0")]
    public float ResultScore { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultPoint")]
    [LocalizedDescription("ResultPoint")]
    [Browsable(true)]
    [DefaultValue(typeof(System.Drawing.Point), "0, 0")]
    public System.Drawing.Point ResultPoint { get; set; }

     

    이번에는 위와 동일하지만, 배열 형태로 담을 속성들도 만들어 줄께요. 왜냐하면 텍스트 인식이 하나의 단어만 처리할수도 있지만, 문장 또는 페이지와 같이 다량의 텍스트가 포함될수도 있기 때문입니다. 아래 테스트에서도 확인할 수 있지만, 꼭 자동 방지 문자 또는 자동 방지 숫자뿐만 아니라 PDF에서 텍스트를 추출하거나 영수증 또는 스마트스토어나 쿠팡 및 폐쇄몰, 자사몰과 같은 곳에서 구매 정보가 문자로 날라올수도 있습니다. 이런 것들을 적절하게 파싱(Parsing)해서 업무를 자동화 할 수 있습니다.

     

    파싱 (Parsing)

    파싱(Parsing)은 컴퓨터 과학 및 프로그래밍에서 특정 형식으로 구성된 데이터를 분석하고 그 의미를 이해하는 과정을 의미합니다. 
    파싱은 주로 텍스트 기반 데이터를 해석하거나, 프로그래밍 언어의 소스 코드를 이해하거나, 문서를 구조화하고 내용을 추출하는 데 사용됩니다.

     

    각각의 결과를 담을 배열도 추가 해줍니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultDescriptions")]
    [LocalizedDescription("ResultDescriptions")]
    [Browsable(true)]
    [DefaultValue(null)]
    [EditorAttribute(typeof(MultilineStringEditor), typeof(UITypeEditor))]
    public string[]? ResultDescriptions { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultScores")]
    [LocalizedDescription("ResultScores")]
    [Browsable(true)]
    [DefaultValue(null)]
    public float[]? ResultScores { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("ResultPoints")]
    [LocalizedDescription("ResultPoints")]
    [Browsable(true)]
    [DefaultValue(null)]
    public System.Drawing.Point[]? ResultPoints { get; set; }

     

    텍스트 인식 영역에서 여러개의 문자가 있는 경우 변수를 이용해서 배열에 담고, 몇번째 값을 가져올지 로직을 작성할수도 있습니다. 하지만, 여기에서 직접 처리하도록 만드는것도 좋을듯 합니다. 따라서, 인덱스를 하나 추가하는게 좋겠군요. 이 부분은 다음에 하기로 하고, 일단 기본 기능부터 빠르게 개발 해봅시다. 아래 속성은 윈도우 화면에서 어느 부분의 텍스트를 인식할지 영역을 지정합니다.

    [LocalizedCategory("Action")]
    [LocalizedDisplayName("SearchArea")]
    [LocalizedDescription("SearchArea")]
    [Browsable(true)]
    [DefaultValue(typeof(System.Drawing.Rectangle), "0,0,0,0")]
    [Editor(typeof(TypeEditor.AreaCaptureEditor), typeof(System.Drawing.Design.UITypeEditor))]
    public System.Drawing.Rectangle SearchArea { get; set; }

     

    구글 API 문서를 보면 텍스트, 레이블, 오브젝트드등... 다양한 것들을 분석해서 처리할 수 있습니다. 그래서, 꼭 텍스트가 아니더라도 더 폭넓게 로직을 만들 수 있도록 옵션을 제공합니다.

    [LocalizedCategory("Action")]
    [LocalizedDisplayName("DetectionType")]
    [LocalizedDescription("DetectionType")]
    [Browsable(true)]
    [DefaultValue(typeof(Ai.Definition.GoogleVisionAiDetectType), "Text")]
    public Ai.Definition.GoogleVisionAiDetectType DetectType { get; set; } = Ai.Definition.GoogleVisionAiDetectType.Text;

     

    옵션은 이렇습니다. 여기서 SafeSearch라는 옵션이 있는데요. 이 옵션은 이미지 영역 또는 사용자가 선택한 이미지가 성인용 콘텐츠인지 판단해주는 기능입니다.

    public enum GoogleVisionAiDetectType
    {
        Object = 0,
        Text = 1,
        Labels = 2,
        SafeSearch = 3
    }

     

    사용자가 설정한 영역 또는 이미지로부터 파일을 읽어들여서 메모리스트림을 작성해줍니다.

    System.Drawing.Image? source = null;
    bool isFile = false;
    bool isDetected = false;
    
    if (string.IsNullOrEmpty(SelectImageFile))
        source = Ai.Common.Screen.Capture(this.SearchArea, player.Manager.Option.CaptureMode, player.Manager.Option.UseMultiMonitor);
    else
    {
        isFile = true;
        source = Ai.Api.ImageManager.ImageEditor.Load(SelectImageFile);
    
        if (player.Manager.Option.UseScaleAndLayout)
        {
            int sf = Ai.Common.Windows.GetScalingFactor();
            source = Ai.Common.ImageEditor.Resize(source, sf - player.Manager.Option.ScaleAndLayoutValue);
        }
    }

     

    메모리 스트림을 처리하고, 시크를 0으로 이동시켜 놓습니다.

    var stream = new System.IO.MemoryStream();
    System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Jpeg;
    
    switch (ImageFormat)
    {
        case Definition.ImageFormats.Png:
            imageFormat = System.Drawing.Imaging.ImageFormat.Png;
            break;
        case Definition.ImageFormats.Bmp:
            imageFormat = System.Drawing.Imaging.ImageFormat.Bmp;
            break;
        case Definition.ImageFormats.Gif:
            imageFormat = System.Drawing.Imaging.ImageFormat.Gif;
            break;
        case Definition.ImageFormats.Webp:
            imageFormat = System.Drawing.Imaging.ImageFormat.Webp;
            break;
        case Definition.ImageFormats.Tiff:
            imageFormat = System.Drawing.Imaging.ImageFormat.Tiff;
            break;
    }
    
    source.Save(stream, imageFormat);
    stream.Position = 0;

     

    음~ 코드를 작성하면서 메모리스트림의 디스포저(Disposer) 동작을 검색해서 알아보다가 매우 중요한 사실을 하나 발견했습니다. 스트림에서 시크(Seek)를 이용해서 위치를 결정하면 안되는군요. 포지션(Position)을 사용해야 합니다. 아래는 메모리스트림에 대한 마이크로소프트 문서입니다.

    8ptaOLB.png

     

     

    이제 핵심 코드 내용입니다. 구글 API의 비전 클라이언트를 생성해줍니다.

    Google.Cloud.Vision.V1.Image image = Google.Cloud.Vision.V1.Image.FromStream(stream);
    Google.Cloud.Vision.V1.ImageAnnotatorClient client = Google.Cloud.Vision.V1.ImageAnnotatorClient.Create();

     

    구글 클라우드 비전은 누겟(nuget)에서 검색한 후 패키지를 설치해야 코드를 사용할 수 있습니다. 아래는 이미지로부터 텍스트를 추출하고, 결과를 처리하는 방법입니다.

    var textAnnotations = client.DetectText(image).ToList();
    textAnnotations.Sort(new Comparison<EntityAnnotation>((n1, n2) => n2.Score.CompareTo(n1.Score)));
    Result = JsonConvert.SerializeObject(textAnnotations);

     

    이외에도 레이블이나 세이프서치등등... 몇가지 기능들을 더 구현해야 하지만, 이 부분은 크게 필요하지 않아서 코드를 작성하지 않았습니다. 우리가 필요한건 윈도우 화면에서 텍스트를 인식하고, 인식된 텍스트를 변수에 추가해서 키보드로 타이핑할 수 있도록 하는게 목적이기 때문입니다. 그리고, 엔지엠 매크로 6에 이미 다 구현되어 있는 기능인데요. 사실, 텍스트 인식말고 나머지는 사용하시는 분들을 한번도 본적이 없습니다.^^;

     

    이제 완성된 코드를 테스트 해볼까요? 테스트 및 기타 설명은 아래 유튜브 동영상을 참고하시면 됩니다.

     

     

    이 글이 도움이 되셨다면~ 커피 한잔이라도 후원 부탁드립니다^^

    개발자에게 후원하기

    MGtdv7r.png

     

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

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

    감사합니다~

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

    댓글목록

    등록된 댓글이 없습니다.