[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,62 +2,190 @@
|
||||
id: wiki-2026-0508-optical-character-recognition
|
||||
title: Optical Character Recognition
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [CV-OCR-001]
|
||||
aliases: [OCR, Text Recognition, Document AI]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 1.0
|
||||
tags: [ai, Computer-Vision, ocr, text-recognition, Deep-Learning, tesseract]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [ocr, document-ai, tesseract, paddleocr, donut, vision-language]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-26
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack: { language: python, framework: paddleocr/transformers }
|
||||
---
|
||||
|
||||
# Optical Character Recognition (OCR, 광학 문자 인식)
|
||||
# Optical Character Recognition
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> "픽셀의 덩어리에서 언어의 형상을 발견하고, 물리적 세상의 기록을 디지털 지식의 흐름으로 복원하라" — 이미지나 스캔된 문서 내의 텍스트를 식별하여 컴퓨터가 편집하고 검색할 수 있는 텍스트 데이터로 변환하는 기술.
|
||||
## 한 줄
|
||||
이미지·스캔·PDF에서 텍스트를 추출하는 기술 — 전통 CRNN 파이프라인부터 modern Donut/TrOCR/Surya 및 VLM 직접 추출까지.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **추출된 패턴:** "Localization, Recognition, and Linguistic [[Refinement|Refinement]]" — 먼저 글자가 어디에 있는지 영역을 찾고(Detection), 각 영역의 이미지를 문자로 번역하며(Recognition), 언어 모델을 통해 문맥상 자연스러운 단어로 교정하는 3단계 처리 패턴.
|
||||
- **주요 기술적 진화:**
|
||||
- **Classic OCR (Tesseract):** 정해진 폰트와 깔끔한 배경 위주로 작동.
|
||||
- **Deep Learning OCR (CRNN, Transformer):** 비정형 배경, 휘어진 텍스트, 다양한 필체 인식 가능.
|
||||
- **Scene Text Recognition:** 자연 환경 속 간판이나 사물의 텍스트 탐지.
|
||||
- **의의:** 방대한 종이 문서의 디지털화(Digital Transformation)를 가능케 하며, 자율주행차의 표지판 인식, 번역 앱의 실시간 텍스트 치환 등 실생활 지능의 필수 관문 역할.
|
||||
## 핵심
|
||||
- **Pipeline**: detection (DBNet/CRAFT) → recognition (CRNN/Transformer) → post-process(NMS, layout).
|
||||
- **Engines**:
|
||||
- Tesseract (오래됨, 다국어, 무료, 정밀도 낮음)
|
||||
- **EasyOCR** (PyTorch, 80+ 언어)
|
||||
- **PaddleOCR** (강력, 중국어/한국어 우수)
|
||||
- **Surya** (modern multilingual, layout)
|
||||
- **TrOCR** (HF, 단어/라인 인식)
|
||||
- **Donut** (OCR-free document understanding)
|
||||
- **VLM-OCR**: GPT-5 Vision, Claude Sonnet 4.7, Qwen2.5-VL — 복잡 양식·표·손글씨에서 강함.
|
||||
- **Layout**: LayoutLMv3, DocFormer, Nougat(논문).
|
||||
- 평가: CER(Character Error Rate), WER, F1 on key fields.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 단순히 '글자 하나하나'를 맞히는 단계를 넘어, 이제는 문서의 레이아웃(표, 리스트 등)까지 파악하여 구조화된 JSON/Markdown으로 변환하는 Layout [[Analysis|Analysis]] 기술이 현대 OCR의 핵심 경쟁력이 됨.
|
||||
- **정책 변화:** Antigravity 프로젝트는 외부 데이터 수집 시 이미지나 PDF 내의 텍스트를 지식화하기 위해, 최신 트랜스포머 기반 OCR 엔진을 활용하여 높은 정확도의 텍스트 추출을 보장함.
|
||||
## 💻 패턴
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- Computer-Vision-Foundations, [[Natural-Language-Processing|Natural-Language-[[Processing]]-NLP]], [[Object-Detection-Foundations|Object-Detection-Foundations]], [[Image-Segmentation|Image-Segmentation]]
|
||||
- **Raw Source:** 10_Wiki/Topics/AI/Optical-Character-Recognition.md
|
||||
```python
|
||||
# 1. Tesseract — 빠른 baseline
|
||||
# brew install tesseract tesseract-lang
|
||||
import pytesseract
|
||||
from PIL import Image
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
img = Image.open("invoice.png")
|
||||
text = pytesseract.image_to_string(img, lang="eng+kor")
|
||||
data = pytesseract.image_to_data(img, output_type=pytesseract.Output.DICT)
|
||||
# data 안에 (text, conf, left, top, width, height) 포함
|
||||
```
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
```python
|
||||
# 2. EasyOCR — Python-only 다국어
|
||||
# pip install easyocr
|
||||
import easyocr
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
reader = easyocr.Reader(["en", "ko"])
|
||||
results = reader.readtext("receipt.jpg", detail=1)
|
||||
for box, text, conf in results:
|
||||
print(f"{conf:.2f}: {text}")
|
||||
```
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
```python
|
||||
# 3. PaddleOCR — 강력한 한·중·영
|
||||
# pip install paddleocr paddlepaddle
|
||||
from paddleocr import PaddleOCR
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
ocr = PaddleOCR(use_angle_cls=True, lang="korean", show_log=False)
|
||||
res = ocr.ocr("doc.png", cls=True)
|
||||
for line in res[0]:
|
||||
box, (txt, conf) = line
|
||||
print(txt, conf)
|
||||
```
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
```python
|
||||
# 4. Surya — modern, layout + reading order
|
||||
# pip install surya-ocr
|
||||
from surya.ocr import run_ocr
|
||||
from surya.model.detection.model import load_model as det_model, load_processor as det_proc
|
||||
from surya.model.recognition.model import load_model as rec_model
|
||||
from surya.model.recognition.processor import load_processor as rec_proc
|
||||
from PIL import Image
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
img = Image.open("page.png")
|
||||
preds = run_ocr([img], [["ko", "en"]],
|
||||
det_model(), det_proc(),
|
||||
rec_model(), rec_proc())
|
||||
for line in preds[0].text_lines:
|
||||
print(line.text, line.confidence)
|
||||
```
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
```python
|
||||
# 5. TrOCR (HuggingFace) — 라인 단위
|
||||
from transformers import TrOCRProcessor, VisionEncoderDecoderModel
|
||||
from PIL import Image
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
proc = TrOCRProcessor.from_pretrained("microsoft/trocr-large-printed")
|
||||
model = VisionEncoderDecoderModel.from_pretrained("microsoft/trocr-large-printed")
|
||||
|
||||
img = Image.open("line.png").convert("RGB")
|
||||
pix = proc(img, return_tensors="pt").pixel_values
|
||||
ids = model.generate(pix)
|
||||
print(proc.batch_decode(ids, skip_special_tokens=True)[0])
|
||||
```
|
||||
|
||||
```python
|
||||
# 6. Donut — OCR-free document QA / parsing
|
||||
from transformers import DonutProcessor, VisionEncoderDecoderModel
|
||||
import torch
|
||||
|
||||
proc = DonutProcessor.from_pretrained("naver-clova-ix/donut-base-finetuned-cord-v2")
|
||||
model = VisionEncoderDecoderModel.from_pretrained("naver-clova-ix/donut-base-finetuned-cord-v2")
|
||||
|
||||
prompt = "<s_cord-v2>"
|
||||
ids = proc.tokenizer(prompt, add_special_tokens=False, return_tensors="pt").input_ids
|
||||
pix = proc(Image.open("receipt.png").convert("RGB"), return_tensors="pt").pixel_values
|
||||
out = model.generate(pix, decoder_input_ids=ids, max_length=512)
|
||||
print(proc.token2json(proc.batch_decode(out)[0]))
|
||||
# {"menu":[...], "total":...} 직접 JSON 출력
|
||||
```
|
||||
|
||||
```python
|
||||
# 7. VLM 직접 OCR (Claude Vision)
|
||||
import anthropic, base64
|
||||
|
||||
img_b64 = base64.b64encode(open("scan.png", "rb").read()).decode()
|
||||
client = anthropic.Anthropic()
|
||||
resp = client.messages.create(
|
||||
model="claude-sonnet-4-7",
|
||||
max_tokens=2048,
|
||||
messages=[{"role": "user", "content": [
|
||||
{"type": "image", "source": {"type": "base64",
|
||||
"media_type": "image/png", "data": img_b64}},
|
||||
{"type": "text", "text":
|
||||
"Extract all text. Output JSON with fields: title, date, line_items[{name, qty, price}], total."},
|
||||
]}],
|
||||
)
|
||||
print(resp.content[0].text)
|
||||
```
|
||||
|
||||
```python
|
||||
# 8. PDF → 텍스트 (pdfplumber + OCR fallback)
|
||||
import pdfplumber, pytesseract
|
||||
from pdf2image import convert_from_path
|
||||
|
||||
def pdf_to_text(path):
|
||||
out = []
|
||||
with pdfplumber.open(path) as pdf:
|
||||
for i, page in enumerate(pdf.pages):
|
||||
t = page.extract_text() or ""
|
||||
if len(t.strip()) < 20: # scanned page → OCR
|
||||
img = convert_from_path(path, first_page=i+1, last_page=i+1)[0]
|
||||
t = pytesseract.image_to_string(img)
|
||||
out.append(t)
|
||||
return "\n\n".join(out)
|
||||
```
|
||||
|
||||
## 결정 기준
|
||||
|
||||
| 상황 | 추천 |
|
||||
|---|---|
|
||||
| 빠른 prototype, 인쇄 영문 | Tesseract |
|
||||
| 다국어 일반 | PaddleOCR / EasyOCR |
|
||||
| 한국어 정밀 | PaddleOCR(ko) / Surya |
|
||||
| 현대 다국어 + layout | Surya |
|
||||
| 라인 단위 정밀 | TrOCR |
|
||||
| 영수증·송장·양식 → 구조 JSON | Donut / VLM |
|
||||
| 복잡 표·손글씨 | Claude Sonnet / GPT-5 Vision |
|
||||
| 학술 PDF (수식) | Nougat |
|
||||
| 디지털 PDF | pdfplumber, OCR fallback |
|
||||
|
||||
## 🔗 Graph
|
||||
- Related: `[[Document-AI]]`, `[[LayoutLM]]`, `[[Vision-Language-Models]]`, `[[Image-Preprocessing]]`, `[[PDF-Processing]]`, `[[Surya]]`, `[[PaddleOCR]]`
|
||||
|
||||
## 🤖 LLM 활용
|
||||
- VLM은 OCR + reasoning 동시 수행 (영수증 → 항목별 카테고리 자동 분류).
|
||||
- 전통 OCR + LLM 후처리: 오타·줄바꿈 normalize, 누락 필드 추론.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- 저화질 이미지를 그대로 입력 (전처리 필수: deskew, binarize, dpi≥300).
|
||||
- Tesseract만 믿고 한국어 받침 깨진 채 배포.
|
||||
- VLM에 큰 PDF를 한 번에 — chunk per page.
|
||||
- confidence threshold 무시하고 raw text 사용.
|
||||
|
||||
## 🧪 검증
|
||||
- Ground truth와 CER/WER 측정.
|
||||
- Field-level F1 (date/total/total_tax 등 critical 필드).
|
||||
- 다양한 폰트·해상도·회전 sample suite 유지.
|
||||
|
||||
## 🕓 Changelog
|
||||
- 2026-05-08 Phase 1: 초안.
|
||||
- 2026-05-10 Manual cleanup: 8 패턴, Surya/Donut/VLM 추가.
|
||||
|
||||
Reference in New Issue
Block a user