반응형

Microsoft Azure의 일부인 MCS(Microsoft Cognitive Services)라는 클라우드 기반의 API를 활용하여 이미지에서 텍스트의 영역을 감지하고 문자 인식(OCR)을 하는 방법에 대해 설명드리도록 하겠습니다. 비용은 가격 책정 계층이 F0 (Free) 인 경우 분당 20건씩, 월 5,000건까지는 무료입니다. (상세 가격)

더보기
  • 164개 언어의 인쇄 텍스트 추출
  • 9개 언어의 필기 텍스트 추출
  • 위치 및 신뢰도 점수가 있는 텍스트 줄 및 단어
  • 언어 식별이 필요하지 않음
  • 혼합 언어, 혼합 모드 지원(인쇄 및 필기)
  • 여러 페이지로 구성된 대형 문서에서 페이지 및 페이지 범위 선택
  • 텍스트 줄 출력을 위한 자연스러운 읽기 순서 옵션(라틴어만 해당)
  • 텍스트 줄에 대한 필기 분류(라틴어만 해당)
  • 온-프레미스 배포를 위한 Distroless Docker 컨테이너로 사용 가능


1. MCS API 키 발급

MCS API를 이용하여 OCR을 수행하기 위해서는 먼저 Microsoft Azure에 대한 자격 증명 키 발급이 필요합니다. Microsoft 계정이 필요하며 계정이 없다면 계정 생성이 필요합니다.

Microsoft Azure 포털로 이동하여 [Azure를 체험해 보기]를 클릭합니다.

포털은 아직 로그인하지 않은 경우 [체험 계정 만들기]를 클릭하여 로그인 페이지로 이동하며 이미 로그인이 된 경우에는 다른 페이지로 리디렉션됩니다 .

이미 Azure 계정이 있는 경우 다음이 표시됩니다. 그렇지 않으면 포털에서 국가, 이름, 이메일 주소 등과 같은 추가 세부 정보를 입력하는 화면으로 이동됩니다.

또한 시스템에서 가입자의 신원을 확인하기 위해 지불 카드 세부 정보를 입력을 요청하며 명목상으로 수수료가 부과될 수 있습니다.

Azure 계정이 없는 경우 세부 정보를 제공하면 계정에 30일 동안 유효한 $200의 무료 Azure 크레딧이 제공됩니다. 이 크레딧을 사용하여 Azure에서 제공하는 다양한 서비스를 사용해 볼 수 있습니다.

정상적으로 로그인이 되었다면 아래 페이지로 이동하며, 이동한 페이지 상단에는 리소스, 서비스 및 문서 검색창이 있습니다. 검색창에 Computer Vision을 입력하고 선택합니다. 

[Computer Vision 만들기] 를 클릭합니다.

사용 가능한 옵션에서 구독을 선택합니다. 리소스 그룹 이 아직 생성 되지 않은 경우 생성해야 합니다. 인스턴스 세부정보에서 이름을 자유롭게 지정하고 지역은 네트워크와 가장 가까운 지역을 선택합니다. 그리고 가격 책정 계층을 선택하고 하단에 검토 승인 체크 후 [검토 +만들기]를 클릭합니다.

유효성 검사 통과 라는 문구가 확인되면 마지막으로 [만들기] 버튼을 클릭합니다.

성공적으로 리소스가 생성되었다면 대시보드 확인이 가능합니다. 리소스 관리에서 [키 및 엔드포인트]를 클릭하시면 키와 엔드포인트 정보를 확인 할 수 있습니다.

2. Azure Computer Vision API 개발 환경 구성

테스트를 위해서 OpenCV와  Azure Computer Vision 라이브러리가 필요합니다. 라이브러리는 pip 를 이용하여 간단히 설치가 가능합니다.

pip install opencv-contrib-python
pip install azure-cognitiveservices-vision-computervision

3. Azure Computer Vision API Script 구현

Import Packages

import io
import time
import sys
import numpy as np
import platform
from PIL import ImageFont, ImageDraw, Image
from matplotlib import pyplot as plt

import cv2
from azure.cognitiveservices.vision.computervision import ComputerVisionClient
from azure.cognitiveservices.vision.computervision.models import OperationStatusCodes
from msrest.authentication import CognitiveServicesCredentials

Jupyter Notebook 또는 Colab에서 이미지를 확인하기위한 Function

def plt_imshow(title='image', img=None, figsize=(8 ,5)):
    plt.figure(figsize=figsize)
 
    if type(img) == list:
        if type(title) == list:
            titles = title
        else:
            titles = []
 
            for i in range(len(img)):
                titles.append(title)
 
        for i in range(len(img)):
            if len(img[i].shape) <= 2:
                rgbImg = cv2.cvtColor(img[i], cv2.COLOR_GRAY2RGB)
            else:
                rgbImg = cv2.cvtColor(img[i], cv2.COLOR_BGR2RGB)
 
            plt.subplot(1, len(img), i + 1), plt.imshow(rgbImg)
            plt.title(titles[i])
            plt.xticks([]), plt.yticks([])
 
        plt.show()
    else:
        if len(img.shape) < 3:
            rgbImg = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
        else:
            rgbImg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
 
        plt.imshow(rgbImg)
        plt.title(title)
        plt.xticks([]), plt.yticks([])
        plt.show()

OpenCV의  putText 를 이용하여 한글을 출력하는 경우 한글이 깨지는 문제를 해결하기 위한 Funtion

def put_text(image, text, x, y, color=(0, 255, 0), font_size=22):
    if type(image) == np.ndarray:
        color_coverted = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = Image.fromarray(color_coverted)
 
    if platform.system() == 'Darwin':
        font = 'AppleGothic.ttf'
    elif platform.system() == 'Windows':
        font = 'malgun.ttf'
        
    image_font = ImageFont.truetype(font, font_size)
    font = ImageFont.load_default()
    draw = ImageDraw.Draw(image)
 
    draw.text((x, y), text, font=image_font, fill=color)
    
    numpy_image = np.array(image)
    opencv_image = cv2.cvtColor(numpy_image, cv2.COLOR_RGB2BGR)
 
    return opencv_image

키 값과 엔드포인트 URL로 클라이언트를 초기화합니다. 키 값과 엔드포인트 URL은 위에 설명한 것처럼 Microsoft Azrue 리소스 관리 페이지에서 확인 하실 수 있습니다.

SUBSCRIPTION_KEY = "<YOUR_SUBSCRIPTION_KEY>"
ENDPOINT_URL = "<YOUR_ENDPOINT_URL>"

computervision_client = ComputerVisionClient(ENDPOINT_URL, CognitiveServicesCredentials(SUBSCRIPTION_KEY))

Load Image

이미지는 stream 으로 변환하여  load 합니다.

path = 'asset/images/test_image9.jpg' 
imageData = open(path, "rb").read()
sbuf = io.BytesIO(imageData)

Request to Azure Computer Vision API

MCS API를 이용하여 이미지를 보내고 응답을 기다립니다.

더보기

read_in_stream(image, language=None, pages=None, model_version='latest', reading_order='basic', custom_headers=None, raw=False, callback=None, **operation_config)

response = computervision_client.read_in_stream(sbuf, raw=True)
operationLocation = response.headers["Operation-Location"]
operationID = operationLocation.split("/")[-1]

get_read_result API를 호출하면서 결과가 확인 될 때까지 상태를 주기적으로 확인하는 polling 방식을 사용합니다. 상태가 succeeded 인 경우 이후 출력을 위한 처리 로직을 수행합니다. polling 방식은 연결을 유지하기때문에 동기화 관점의 장점도 있고 MCS API는 다건의 결과를 한번에 반환하기때문에 대량을 처리 할 경우 분명 장점이 있지만 루프를 사용하기도하고 잠재적으로 오류가 발생 할 수 있다는 단점도 있습니다.

더보기

폴링(polling)이란 하나의 장치(또는 프로그램)가 충돌 회피 또는 동기화 처리 등을 목적으로 다른 장치(또는 프로그램)의 상태를 주기적으로 검사하여 일정한 조건을 만족할 때 송수신 등의 자료처리를 하는 방식

Check Result

while True:
    read_result = computervision_client.get_read_result(operationID)
    if read_result.status not in ['notStarted', 'running']:
        break
    time.sleep(1)

if read_result.status == OperationStatusCodes.succeeded:
    img = cv2.imread(path)
    roi_img = img.copy()

    for text_result in read_result.analyze_result.read_results:
        for line in text_result.lines:
            text = line.text
            box = list(map(int, line.bounding_box))
            (tlX, tlY, trX, trY, brX, brY, blX, blY) = box
            pts = ((tlX, tlY), (trX, trY), (brX, brY), (blX, blY))

            topLeft = pts[0]
            topRight = pts[1]
            bottomRight = pts[2]
            bottomLeft = pts[3]

            cv2.line(roi_img, topLeft, topRight, (0,255,0), 2)
            cv2.line(roi_img, topRight, bottomRight, (0,255,0), 2)
            cv2.line(roi_img, bottomRight, bottomLeft, (0,255,0), 2)
            cv2.line(roi_img, bottomLeft, topLeft, (0,255,0), 2)
            roi_img = put_text(roi_img, text, topLeft[0], topLeft[1] - 10, font_size=30)

            print(text)
            
    plt_imshow(["Original", "ROI"], [img, roi_img], figsize=(16, 10))

더보기
와줘서 고마워
thank you for coming

테스트 이미지에서 MCS OCR API는 올바르게 OCR을 수행한 결과를 확인 할 수 있습니다. 향후 각 API에 대해 OCR 성능 벤치마킹을 정리 할 예정이지만 아래 이미지만 보더라도 이전 Google Cloud Vision API 보다 좋은 결과를 보이고 있습니다.

더보기

バス
Bus
公共汽车 버스타
TAXI
タクシー
Taxi
出租汽车 택시타
선)

공개적으로 연결이 가능한 URL의 이미지를 직접 입력하고 OCR결과를 확인 할 수도 있습니다.

더보기
read_image_url = "https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/master/articles/cognitive-services/Computer-vision/Images/readsample.jpg"

# Call API with URL and raw response (allows you to get the operation location)
read_response = computervision_client.read(read_image_url,  raw=True)

# Get the operation location (URL with an ID at the end) from the response
read_operation_location = read_response.headers["Operation-Location"]
# Grab the ID from the URL
operation_id = read_operation_location.split("/")[-1]

# Call the "GET" API and wait for it to retrieve the results 
while True:
    read_result = computervision_client.get_read_result(operation_id)
    if read_result.status not in ['notStarted', 'running']:
        break
    time.sleep(1)

# Print the detected text, line by line
if read_result.status == OperationStatusCodes.succeeded:
    for text_result in read_result.analyze_result.read_results:
        for line in text_result.lines:
            print(line.text)
            print(line.bounding_box)

MCS OCR API는 자동 언어 식별 및 다국어 문서를 지원합니다. OCR 수행을 특정 언어로 처리되도록 하려는 경우에만 language Argument를 입력하시면 됩니다. 지원되는 언어는 가이드 페이지에서 확인이 가능합니다.

반응형