카테고리 없음

[Azure OpenAI] Document Intelligence 📄 OCR 문서 읽기

bigpotworks 2025. 3. 20. 09:48

Azure 에서 제공하는 Document Intelligence Studio 를 활용해서 지능형 문서 처리 솔루션을 만드는 실습을 해보았다.

 

일부는 한글이 지원되지만 다수의 모델은 영문 전용인 점 참고!

 

Prebuilt Models 를 살펴보면 

  • Invoices: 고객 및 공급업체 세부 정보 추출 (한글 지원)
  • Health Insueance card: 보험 적용 세부 정보를 추출 (영문)
  • Business Card: 명함 세부 정보 추출 (한글 지원)

등등, 사용처를 보면 어떤 기술인지 얼추 감이 온다.

 

상단의 OCR/Read 를 실습해본다.

 

OCR(Optical Character Recognition)은 광학 문자 인식을 뜻하며, 텍스트 이미지를 기계가 읽을 수 있는 텍스트로 변환하는 기술으로, 텍스트 인식이라고도 불리기도 한다.

 

요즘은 스마트폰 앨범에서도, 구글번역 앱에서도 다 지원되는 기능이라 익숙하다.

 

 

해당 API 를 가져와서 파이썬과 그라디오로 구현해보도록 한다.

 

import gradio as gr
import requests
import time
from PIL import Image, ImageDraw
import random


# Document Intelligence API를 호출하여 문서 분석 결과를 반환하는 함수
def request_document_intelligence(file_path):
    endpoint = "https://fimtrus-document-intelligence.cognitiveservices.azure.com/documentintelligence/documentModels/prebuilt-read:analyze?_overload=analyzeDocument&api-version=2024-11-30"
    
    headers = {
        "Ocp-Apim-Subscription-Key": #비밀,  # API 키 입력 필요
        "Content-Type": "image/png"  # 이미지 형식 지정
    }
    
    # 이미지 파일을 바이너리 형태로 읽어오기
    with open(file_path, "rb") as image:
        image_data = image.read()
    
    # Azure Document Intelligence API 요청 보내기
    response = requests.post(endpoint, headers=headers, data=image_data)
    
    # API가 비동기적으로 결과를 반환하므로, 202 응답이 올 경우 진행 상태를 확인해야 함
    if response.status_code == 202:
        result_url = response.headers['Operation-Location']  # 결과를 가져올 URL
        
        while(True):
            # 결과 요청하여 상태 확인
            result_response = requests.get(result_url, headers={
                "Ocp-Apim-Subscription-Key": headers["Ocp-Apim-Subscription-Key"]
            })
            result_response_json = result_response.json()
            result_status = result_response_json['status']
            
            if result_status == "running":
                print(result_status)  # 진행 중 상태 출력
                time.sleep(1)  # 1초 대기 후 다시 확인
                continue
            else:
                break  # 완료되면 루프 종료
            
        # 분석 성공 시 결과 반환
        if result_status == "succeeded":
            print(result_status)
            print(result_response_json)
            return result_response_json
        else:
            return None  # 실패 시 None 반환

# 랜덤한 색상을 생성하는 함수
def random_color():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

# 분석 결과를 받아 입력 이미지 위에 텍스트 영역을 시각적으로 표시하는 함수
def draw_image(file_path, result_response):
    image = Image.open(file_path)  # 입력 이미지 열기
    draw = ImageDraw.Draw(image)  # 이미지를 수정할 수 있도록 draw 객체 생성
    
    block_list = result_response['analyzeResult']['paragraphs']  # 분석된 문단 목록 가져오기
    
    for block in block_list:
        line_color = random_color()  # 문단별 랜덤 색상 지정
        polygon_list = block['boundingRegions'][0]['polygon']  # 문단 영역의 다각형 좌표
        points = [(polygon_list[i], polygon_list[i + 1]) for i in range(0, len(polygon_list), 2)]  # 좌표를 튜플 형태로 변환  
        content = block['content']  # 문단의 텍스트 내용
        
        # 텍스트 영역을 이미지 위에 그리기
        draw.polygon(points, outline=line_color, width=2)  # 다각형 테두리 그리기
        draw.text((points[0][0], points[0][1] - 10), content, fill=line_color)  # 텍스트 표시
        
    return image  # 수정된 이미지 반환


# Gradio UI 구성
with gr.Blocks() as demo:
    
    # 버튼 클릭 시 실행될 함수
    def click_send(file_path):
        result_response = request_document_intelligence(file_path)  # Document Intelligence API 호출
        image = draw_image(file_path, result_response)  # 이미지에 분석 결과 반영
        return image  # 수정된 이미지 반환
    
    input_image = gr.Image(label="입력 이미지", type="filepath")  # 입력 이미지 업로드
    send_button = gr.Button("전송")  # 분석 요청 버튼
    output_image = gr.Image(label="출력 이미지", interactive=False, type="pil")  # 분석 결과 표시
    
    send_button.click(click_send, inputs=[input_image], outputs=[output_image])  # 버튼 클릭 이벤트 연결
    
demo.launch()  # Gradio 인터페이스 실행

# 테스트용 코드 (실제 사용 시 주석 해제 후 파일 경로 입력하여 사용)
# result_response = request_document_intelligence(file)
# draw_image(file, result_response)

 

그라디오 화면은 이렇다

 

 

상단에 텍스트가 포함된 이미지 파일을 넣어주면, 출력 이미지에 텍스트로 인식한 부분에 폴리곤 박스를 그려준다.