OCR với Claude — Trích xuất text từ hình ảnh và tài liệu
Điểm nổi bật
Nhấn để đến mục tương ứng
- 1 Tận dụng Claude hiệu quả: Tiêu chí Tesseract truyền thống Claude Vision Ảnh nghiêng, xoay Cần pre-process Xử lý được trực tiếp Font lạ, chữ tay — mẹo quan trọng là cung cấp đủ ngữ cảnh để AI trả về kết quả chính xác hơn 80% so với prompt chung chung.
- 2 Góc nhìn thực tế: import anthropic import base64 def ocrimageimagepath: str, language: str = "Vietnamese" -> str: """ Trich xuat toan. Điều quan trọng là hiểu rõ khi nào nên và không nên áp dụng phương pháp này.
- 3 Nội dung cốt lõi: "don thuoc", "bien ban hop", "nhat ky" """ with openimagepath, "rb" as f: data = base64.standardb64encodef.read.decode. Nắm vững phần này sẽ giúp bạn áp dụng hiệu quả hơn 70% so với đọc lướt toàn bài.
- 4 Tận dụng Claude hiệu quả: Tuy nhiên có một số lưu ý: def ocrvietnamesedocumentimagepath: str -> str: """OCR cho tai lieu tieng Viet.""" with — mẹo quan trọng là cung cấp đủ ngữ cảnh để AI trả về kết quả chính xác hơn 80% so với prompt chung chung.
- 5 Thành thật mà nói: Pre-process ảnh trước khi gửi from PIL import Image, ImageEnhance, ImageFilter def enhanceforocrimagepath: str ->. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
OCR (Optical Character Recognition) là bài toán cổ điển trong xử lý hình ảnh — nhận diện và trích xuất text từ ảnh. Các giải pháp OCR truyền thống như Tesseract hoạt động tốt với tài liệu in đều, nhưng gặp khó khăn với ảnh nghiêng, font chữ lạ, hoặc chữ viết tay.
Claude Vision thay đổi cuộc chơi: không chỉ đọc text mà còn hiểu context — biết đây là hóa đơn, danh thiếp, hay biên bản họp, và trả về thông tin theo cấu trúc phù hợp.
Tại sao Claude OCR tốt hơn Tesseract?
| Tiêu chí | Tesseract (truyền thống) | Claude Vision |
|---|---|---|
| Ảnh nghiêng, xoay | Cần pre-process | Xử lý được trực tiếp |
| Font lạ, chữ tay | Độ chính xác thấp | Khá tốt |
| Tiếng Việt có dấu | Cần cấu hình đặc biệt | Native support |
| Hiểu cấu trúc tài liệu | Không | Có (bảng, form, hóa đơn) |
| Trả về JSON có structure | Không, chỉ raw text | Có thể yêu cầu |
| Chi phí | Miễn phí, local | Tính theo token |
| Tốc độ với batch lớn | Nhanh hơn | Chậm hơn, có rate limit |
Kết luận: Dùng Tesseract cho batch lớn tài liệu in chuẩn. Dùng Claude khi cần độ chính xác cao với tài liệu phức tạp, hoặc khi cần structured output.
OCR cơ bản — Trích xuất raw text
import anthropic
import base64
def ocr_image(image_path: str, language: str = "Vietnamese") -> str:
"""
Trich xuat toan bo van ban tu mot anh.
Args:
image_path: Duong dan den file anh
language: Ngon ngu chinh trong anh
Returns:
Van ban duoc trich xuat
"""
with open(image_path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
# Xac dinh media type
ext = image_path.lower().rsplit(".", 1)[-1]
media_types = {
"jpg": "image/jpeg", "jpeg": "image/jpeg",
"png": "image/png", "gif": "image/gif", "webp": "image/webp"
}
media_type = media_types.get(ext, "image/jpeg")
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": media_type, "data": data}
},
{
"type": "text",
"text": f"""Trich xuat toan bo van ban trong hinh anh nay.
Ngon ngu chinh: {language}.
Huong dan:
- Giu nguyen dinh dang nguyen ban (xuat xuong dong, tab, khoang trang)
- Khong them nhan xet hay mo ta
- Neu co phan nao khong ro, danh dau [KHONG RO]
- Chi tra ve van ban, khong co gi them"""
}
]
}
]
)
return message.content[0].text
OCR có cấu trúc — Trích xuất theo field
Đọc hóa đơn / receipt
def extract_receipt(image_path: str) -> dict:
"""Trich xuat thong tin tu hoa don mua sam."""
with open(image_path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=2048,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": data}
},
{
"type": "text",
"text": """Trich xuat thong tin tu hoa don nay va tra ve JSON voi format sau:
{
"store_name": "ten cua hang",
"date": "ngay (DD/MM/YYYY)",
"time": "gio (HH:MM)",
"items": [
{"name": "ten san pham", "quantity": so_luong, "unit_price": don_gia, "total": thanh_tien}
],
"subtotal": tong_truoc_thue,
"tax": tien_thue,
"total": tong_cuoi,
"payment_method": "hinh_thuc_thanh_toan",
"cashier": "thu_ngan_neu_co"
}
Chi tra ve JSON, khong them gi khac."""
}
]
}
]
)
import json
try:
return json.loads(message.content[0].text)
except json.JSONDecodeError:
return {"raw": message.content[0].text}
Đọc danh thiếp (business card)
def extract_business_card(image_path: str) -> dict:
"""Trich xuat thong tin lien lac tu danh thiec."""
with open(image_path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=512,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": data}
},
{
"type": "text",
"text": """Trich xuat thong tin tu danh thiec nay, tra ve JSON:
{
"name": "ho ten day du",
"title": "chuc danh",
"company": "ten cong ty",
"email": "email hoac null",
"phone": ["so dien thoai 1", "so 2 neu co"],
"address": "dia chi hoac null",
"website": "website hoac null",
"social": {"linkedin": "...", "facebook": "..."}
}
Chi tra ve JSON."""
}
]
}
]
)
import json
try:
return json.loads(message.content[0].text)
except json.JSONDecodeError:
return {"raw": message.content[0].text}
Xử lý chữ viết tay
Chữ viết tay là thách thức lớn với OCR truyền thống nhưng Claude xử lý khá tốt:
def transcribe_handwriting(
image_path: str,
context: str = ""
) -> str:
"""
Chuyen chu viet tay thanh text.
Args:
image_path: Anh chua chu viet tay
context: Nguyen canh (e.g. "don thuoc", "bien ban hop", "nhat ky")
"""
with open(image_path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
context_hint = f"Day la {context}. " if context else ""
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-4-5", # Dung Opus cho handwriting phuc tap
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": data}
},
{
"type": "text",
"text": f"""{context_hint}Hay doc va chuyen chu viet tay trong anh thanh van ban dang.
Luu y:
- Co gang doc chinh xac tung chu
- Giu nguyen cau truc doan van va xuong dong
- Neu mot tu khong ro, doan hop ly va danh dau voi [?]
- Dung doan moi khi co khoang trong lon trong anh
- Tra ve van ban thuan tuy"""
}
]
}
]
)
return message.content[0].text
Tiếng Việt — Xử lý dấu thanh
Claude đọc tiếng Việt tốt hơn Tesseract đáng kể vì được train trên lượng lớn text Việt. Tuy nhiên có một số lưu ý:
def ocr_vietnamese_document(image_path: str) -> str:
"""OCR cho tai lieu tieng Viet."""
with open(image_path, "rb") as f:
data = base64.standard_b64encode(f.read()).decode()
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/jpeg", "data": data}
},
{
"type": "text",
"text": """Day la tai lieu tieng Viet. Trich xuat toan bo noi dung.
Yeu cau quan trong:
- Giu nguyen dau thanh dieu (a, a, a, a, a, v.v.)
- Giu nguyen dac tu (d, d) va chu co dau mui ten (u, u, o, o, a, e)
- Neu font kho doc dan den sai dau, hay su dung nguyen canh de suy luan
- Khong thay the tieng Viet bang tieng Anh
- Tra ve van ban thuan tuy, giu nguyen dinh dang"""
}
]
}
]
)
return message.content[0].text
Batch OCR — Xử lý nhiều trang
Khi cần OCR nhiều ảnh (ví dụ: tài liệu nhiều trang đã scan), xử lý tuần tự với rate limiting:
import time
from pathlib import Path
def batch_ocr(
image_paths: list,
output_dir: str = "ocr_output",
delay: float = 0.5
) -> dict:
"""
OCR nhieu anh, luu ket qua ra file.
Args:
image_paths: Danh sach duong dan anh
output_dir: Thu muc luu ket qua
delay: Delay giua cac request (giay)
Returns:
Dict {filename: extracted_text}
"""
Path(output_dir).mkdir(exist_ok=True)
results = {}
for i, path in enumerate(image_paths):
print(f"Dang xu ly {i+1}/{len(image_paths)}: {path}")
try:
text = ocr_image(path)
results[path] = text
# Luu ra file rieng
out_path = Path(output_dir) / (Path(path).stem + ".txt")
with open(out_path, "w", encoding="utf-8") as f:
f.write(text)
except Exception as e:
print(f"Loi khi xu ly {path}: {e}")
results[path] = f"ERROR: {e}"
# Rate limiting
if i < len(image_paths) - 1:
time.sleep(delay)
return results
Tips để tăng độ chính xác OCR
1. Pre-process ảnh trước khi gửi
from PIL import Image, ImageEnhance, ImageFilter
def enhance_for_ocr(image_path: str) -> bytes:
"""Tang chat luong anh truoc khi OCR."""
with Image.open(image_path) as img:
# Chuyen sang grayscale neu can
if img.mode not in ("L", "RGB"):
img = img.convert("RGB")
# Tang contrast
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Tang do sac net
img = img.filter(ImageFilter.SHARPEN)
# Luu vao buffer
import io
buf = io.BytesIO()
img.save(buf, format="JPEG", quality=95)
return buf.getvalue()
2. Cung cấp context cho Claude
Luôn nói với Claude đây là loại tài liệu gì — điều này giúp nó suy luận đúng hơn khi gặp phần khó đọc:
# Thay vi
"Trich xuat van ban"
# Nen dung
"Day la hoa don VAT cua mot cua hang ban le. Trich xuat toan bo noi dung."
# Hoac
"Day la bien ban cuoc hop cua mot cong ty Viet Nam. Doc va chuyen chu viet tay thanh van ban."
3. Chia nhỏ tài liệu lớn
Với tài liệu nhiều thông tin, chia nhỏ câu hỏi thay vì hỏi tất cả một lúc:
def extract_invoice_in_parts(image_path: str) -> dict:
"""Trich xuat hoa don theo tung phan."""
# Phan 1: Thong tin chung
header = ask_about_image(image_path,
"Chi trich xuat: so hoa don, ngay, ten ben ban, ten ben mua. JSON only.")
# Phan 2: Line items
items = ask_about_image(image_path,
"Chi trich xuat danh sach san pham/dich vu voi gia. JSON array only.")
# Phan 3: Tong ket
totals = ask_about_image(image_path,
"Chi trich xuat: tong tien, thue, tong cuoi, hinh thuc thanh toan. JSON only.")
return {"header": header, "items": items, "totals": totals}
Khi nào Claude OCR không phù hợp?
- Batch hàng nghìn trang — Chi phí cao, dùng Tesseract hoặc Google Document AI
- Real-time OCR — Latency API không phù hợp cho ứng dụng scan liên tục
- Tài liệu in đều, font chuẩn — Tesseract đủ tốt và miễn phí
- Cần on-premise, không gửi data ra ngoài — Claude là cloud API
Tổng kết
Claude Vision là công cụ OCR mạnh mẽ khi bạn cần:
- Đọc tài liệu phức tạp (ảnh nghiêng, font lạ, chữ tay)
- Trả về structured data (JSON) thay vì raw text
- Hỗ trợ tiếng Việt có dấu
- Hiểu context tài liệu để suy luận chính xác hơn
Tiếp theo: Xem Phân tích biểu đồ và slide deck để ứng dụng Vision vào data analysis, hoặc Crop Tool khi cần đọc tài liệu với text nhỏ ở nhiều vùng.
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.


