OCR
광학 문자 인식 Optical Character Recognition
- 과정
- 이미지 전처리
- 텍스트 위치 추정 → 문자 분리 / 텍스트 추출
- 문자 인식
- 후처리
- 텍스트 추출의 어려움
- 다양한 크기, 색상, 방향 등
- 여러 개의 글자를 하나의 단어로 인식하는 문제
- 하나의 단어를 여러 개의 글자로 인식하는 문제
- 다른 이미지 인식 과제와 달리 문자의 종류는 제한되어 있음
- 별도로 개발할 필요 없이 오픈소스 라이브러리만으로 해결할 수 있음
PaddleOCR
- 중국 Baidu에서 개발한 딥러닝 기반 OCR 라이브러리
- 한국어 포함 100개 이상의 언어 지원
- OmniDocBench v1.6에서 96.3% 정확도
- 가장 성능이 높은 오픈소스 라이브러리 중에 하나
PaddleOCR의 구조
- 모델 하나로 페이지 전체를 처리하면 속도가 느리고, 레이아웃으로 인한 환각이 생기기 쉬움
- 레이아웃 분석 + 요소별 인식으로 나누어 2단계 처리

레이아웃 분석
- 문서 페이지에서 텍스트, 표, 수식, 차트 같은 영역을 찾고, 각 영역의 종류와 읽는 순서를 예측
- RT-DETR 기반 객체 탐지 모델
- 문서 안의 요소 위치를 bounding box로 찾음
- 요소 유형을 분류함: text, table, formula, chart 등
- Pointer Network
- 탐지된 요소들의 읽는 순서를 예측함
- 6개 Transformer layer 사용하여, 요소 간 상대적 순서를 N x N 행렬로 계산
- 이후 deterministic decoding으로 최종 reading order를 복원

요소별 인식 VLM
- 대부분 이미지 처리 모델은 입력을 고정된 크기로 변환 → 텍스트가 찌그러짐
- NaViT(Native Resolution ViT): 이미지를 텍스트처럼 길이가 가변적인 데이터로 취급하는 비전 트랜스포머 모델
- 이미지 처리 결과를 소형 언어 모델 ERNIE에 입력하여 텍스트 생성

훈련
- 텍스트: 약 2천만 개 이상
- 109개 언어 포함
- 인쇄체, 손글씨, 스캔 문서, 예술적 폰트 등 포함
- 표: 500만 개 이상
- 수식: 7백만개 이상 LaTeX 생성 수식 및 손글씨
- 차트: 80만 개 이상
PaddleOCR 실습
설치:
!pip install paddlepaddle==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
!pip install "paddleocr[all]"
- colab에서 설치 후 restart session
불러오기:
from paddleocr import PaddleOCR
ocr = PaddleOCR(
use_doc_orientation_classify=False, # 문서 방향 분류 사용 안 함
use_doc_unwarping=False, # 문서 왜곡 보정 사용 안 함
use_textline_orientation=False, # 텍스트 라인 방향 분류 사용 안 함
engine="paddle",
lang="korean", # 언어: 한국어 (영어는 "en")
)
PaddleOCR 실습
- 이미지 처리: 텍스트 감지 임계값을 낮추려면
text_det_thresh인자를 사용(기본값 0.3)
result = ocr.predict(input="blueprint.jpg")
결과:
res = result[0] # 첫 번째 이미지 결과
res["rec_texts"] # 인식된 텍스트
res["rec_polys"] # 텍스트별 폴리곤(다각형)의 꼭지점 좌표
res["rec_boxes"] # 텍스트별 박스의 왼쪽 위, 오른쪽 아래 꼭지점 좌표
시각화:
res.save_to_img("output")
PaddleOCR 수동 시각화
from PIL import Image, ImageDraw, ImageFont
try:
# 한글 출력을 위해 나눔고딕과 같은 한글 폰트가 필요합니다.
font = ImageFont.truetype("NanumGothic.ttf", 20)
except IOError:
print("NanumGothic.ttf 폰트를 찾을 수 없습니다. 기본 폰트를 사용합니다.")
font = ImageFont.load_default()
img = Image.open("blueprint.jpg").convert("RGB")
draw = ImageDraw.Draw(img)
for text, poly in zip(res["rec_texts"], res["rec_polys"]):
# 텍스트를 감싸는 다각형(폴리곤)을 파란색으로 그립니다.
# PIL의 polygon은 (x1,y1), (x2,y2)... 형태의 튜플 리스트를 인자로 받습니다.
draw.polygon([tuple(p) for p in poly], outline="#0000FF", width=2)
# 인식된 텍스트를 폴리곤의 첫 번째 꼭짓점 위치에 빨간색으로 씁니다.
# 텍스트가 박스 안쪽에 그려지도록 위치를 약간 조정할 수 있습니다.
text_position = tuple(poly[0])
pos = (text_position[0] + 5, text_position[1] + 5)
draw.text(pos, text, fill="#FF0000", font=font)
img
PDF 변환
설치:
pip install pdf2image
mamba install -y poppler # mamba 또는 conda 사용
변환:
import pdf2image
import numpy as np
pages = pdf2image.convert_from_path("교안.pdf") # PDF에서 페이지들을 이미지 배열로
page_arrays = [np.array(p) for p in pages]
result = ocr.predict(input=page_arrays) # 텍스트 추출