0Pricing
AI Agents · 课时

扫描文档的 OCR

通过 pytesseract 使用 Tesseract,进行图像预处理并提高准确率。

扫描文档的 OCR 是 CoddyKit 上的免费 AI Agents 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。

何时需要 OCR

并非所有文档都是原生数字化的 PDF。扫描文档、文字照片、手写笔记以及基于图像的 PDF,都需要使用光学字符识别(OCR)来提取文本。

OCR 会将文字的像素图像转换为机器可读的字符。两个领先的 Python 库是:pytesseract(谷歌的 Tesseract)和 EasyOCR(基于深度学习,支持多语言)。

pytesseract 基础

pytesseract 是谷歌 Tesseract OCR 引擎的 Python 封装器。请先安装 Tesseract(操作系统级安装),然后运行 pip install pytesseract Pillow。

import pytesseract
from PIL import Image

# Simple text extraction
image = Image.open('scanned_document.png')
text = pytesseract.image_to_string(image)
print(text)

# Specify language (default: English)
text_fr = pytesseract.image_to_string(
    Image.open('french_doc.png'),
    lang='fra'
)

# Get detailed output with bounding boxes
data = pytesseract.image_to_data(
    image,
    output_type=pytesseract.Output.DICT
)
for i, word in enumerate(data['text']):
    if word.strip():
        conf = data['conf'][i]
        print(f'Word: {word!r:20} Confidence: {conf}')

图像预处理:灰度化

OCR 的准确度在很大程度上取决于图像质量。第一步预处理是转换为灰度图——颜色会增加噪声,却不会帮助识别字符。

请使用 Pillow 或 OpenCV 进行预处理。灰度化可以减少噪声,并改善 Tesseract 对字符边界的检测。

from PIL import Image, ImageOps
import numpy as np

def preprocess_grayscale(image_path):
    img = Image.open(image_path)

    # Convert to grayscale
    img = img.convert('L')  # 'L' = 8-bit grayscale

    # Optionally resize for better OCR (Tesseract works best at ~300 DPI)
    # Scale up small images
    width, height = img.size
    if width < 800:
        scale = 800 / width
        new_size = (int(width * scale), int(height * scale))
        img = img.resize(new_size, Image.LANCZOS)

    return img

img = preprocess_grayscale('scan.jpg')
text = pytesseract.image_to_string(img)
print(text[:300])

图像预处理:阈值处理

阈值处理会将灰度图像转换为纯黑白图像。这样可以去除灰色阴影、光照不均和背景噪声,让文字在 OCR 处理时更加清晰突出。

from PIL import Image, ImageFilter
import numpy as np

def apply_threshold(img):
    # Method 1: Simple fixed threshold
    img_array = np.array(img)
    threshold = 128
    binary = np.where(img_array > threshold, 255, 0).astype(np.uint8)
    return Image.fromarray(binary)

def adaptive_threshold(img):
    # Method 2: Otsu's method via OpenCV (better for uneven lighting)
    try:
        import cv2
        img_array = np.array(img)
        _, binary = cv2.threshold(
            img_array, 0, 255,
            cv2.THRESH_BINARY + cv2.THRESH_OTSU
        )
        return Image.fromarray(binary)
    except ImportError:
        return apply_threshold(img)

img = preprocess_grayscale('uneven_scan.png')
img_clean = adaptive_threshold(img)
text = pytesseract.image_to_string(img_clean)
print(text[:300])

图像预处理:校正倾斜

扫描文档通常会有轻微旋转。即使只有 2 度的倾斜,也会明显降低 OCR 的准确度。校正倾斜会在将图像传给 OCR 引擎之前,检测并修正旋转角度。

import numpy as np
from PIL import Image

def deskew(img):
    try:
        import cv2
        img_array = np.array(img)

        # Find rotation angle using Hough line transform
        edges = cv2.Canny(img_array, 50, 150, apertureSize=3)
        lines = cv2.HoughLines(edges, 1, np.pi/180, threshold=100)

        if lines is None:
            return img  # no lines detected, return unchanged

        angles = []
        for line in lines:
            rho, theta = line[0]
            angle = np.degrees(theta) - 90
            if -45 < angle < 45:
                angles.append(angle)

        if not angles:
            return img

        median_angle = np.median(angles)
        if abs(median_angle) > 0.5:  # only deskew if significant tilt
            print(f'Deskewing by {median_angle:.2f} degrees')
            return img.rotate(-median_angle, expand=True, fillcolor=255)
        return img
    except ImportError:
        return img  # OpenCV not available — skip deskew

Tesseract 语言选项

Tesseract 支持 100 多种语言。请使用操作系统的软件包管理器下载语言包。对于多语言文档,请使用 + 分隔符指定多种语言。

import pytesseract
from PIL import Image

# List available languages
import subprocess
result = subprocess.run(['tesseract', '--list-langs'], capture_output=True, text=True)
print('Available languages:')
print(result.stdout)

# Single language
text_en = pytesseract.image_to_string(Image.open('doc.png'), lang='eng')

# Multiple languages (auto-detect best match)
text_multi = pytesseract.image_to_string(
    Image.open('doc.png'),
    lang='eng+fra+deu'  # English + French + German
)

# Tesseract config options for better accuracy
custom_config = r'--oem 3 --psm 6'  # OEM 3=LSTM, PSM 6=assume uniform block of text
text_tuned = pytesseract.image_to_string(
    Image.open('doc.png'),
    config=custom_config
)

EasyOCR:基于深度学习

EasyOCR 使用深度学习模型,在处理质量下降的图像、弯曲文字和非拉丁文字方面优于 Tesseract。它不需要进行操作系统级安装。

使用 pip install easyocr 安装。首次运行时会下载模型权重(约 200 MB)。

import easyocr

# Initialize reader (downloads model on first run)
reader = easyocr.Reader(
    ['en', 'tr'],  # list of languages
    gpu=False       # set True if CUDA available
)

# Read text from image
results = reader.readtext('scanned_page.png')

for (bbox, text, confidence) in results:
    print(f'Text: {text!r:30} Confidence: {confidence:.2f}')
    # bbox = [[x1,y1],[x2,y2],[x3,y3],[x4,y4]] (four corners)

# Get plain text only
text_only = ' '.join(result[1] for result in results)
print('Full text:', text_only[:300])

使用 EasyOCR 处理多语言文档

EasyOCR 能够很好地处理混合语言文档,适用于国际合同、带有多语言图注的研究论文,或包含其他文字系统技术术语的文档。

import easyocr

# For Arabic-English mixed document
reader_ar = easyocr.Reader(['ar', 'en'], gpu=False)
results = reader_ar.readtext('arabic_contract.png')

# For CJK languages
reader_cjk = easyocr.Reader(['ch_sim', 'en'], gpu=False)  # Simplified Chinese + English
results_cjk = reader_cjk.readtext('chinese_report.png')

# Filter by confidence threshold
HIGH_CONFIDENCE = 0.7
def filter_confident_results(results, threshold=HIGH_CONFIDENCE):
    return [
        (bbox, text, conf)
        for bbox, text, conf in results
        if conf >= threshold
    ]

完整的预处理流程

将所有预处理步骤——灰度化、阈值处理和校正倾斜——串联到一个流程函数中。在处理后的图像上运行 OCR,并同时返回文本和置信度指标。

import pytesseract
from PIL import Image

def ocr_pipeline(image_path, lang='eng', engine='tesseract'):
    print(f'Processing: {image_path}')

    # 1. Load
    img = Image.open(image_path)

    # 2. Preprocess
    img = img.convert('L')         # grayscale
    img = adaptive_threshold(img)  # binarize
    img = deskew(img)              # correct rotation

    # 3. OCR
    if engine == 'easyocr':
        reader = easyocr.Reader([lang], gpu=False)
        results = reader.readtext(image_path)
        text = ' '.join(r[1] for r in results if r[2] > 0.5)
    else:
        config = f'--oem 3 --psm 6 -l {lang}'
        text = pytesseract.image_to_string(img, config=config)

    # 4. Clean
    text = '\n'.join(
        line.strip() for line in text.splitlines()
        if line.strip()
    )
    return text

text = ocr_pipeline('invoice_scan.jpg')
print(text[:500])

处理基于图像的 PDF

有些 PDF 在 PDF 容器内部以图像形式存储扫描页面。请检测这些“图像 PDF”,先使用 PyMuPDF 提取图像,再逐页应用 OCR。

import fitz
from PIL import Image
import io
import pytesseract

def is_image_pdf(doc):
    # Check if first page has very little extractable text
    text = doc[0].get_text().strip()
    return len(text) < 50

def ocr_pdf(filepath):
    doc = fitz.open(filepath)
    if not is_image_pdf(doc):
        # Native text — no OCR needed
        return '\n'.join(doc[i].get_text() for i in range(len(doc)))

    print('Image PDF detected — running OCR')
    all_text = []

    for page_num in range(len(doc)):
        page = doc[page_num]
        # Render page as image at 300 DPI
        mat = fitz.Matrix(300/72, 300/72)  # scale to 300 DPI
        pix = page.get_pixmap(matrix=mat)
        img = Image.open(io.BytesIO(pix.tobytes('png')))
        text = pytesseract.image_to_string(img)
        all_text.append(f'--- Page {page_num+1} ---\n{text}')

    doc.close()
    return '\n'.join(all_text)

置信度过滤与后处理

OCR 输出中可能包含错误,尤其是在图像质量下降时。请对文本进行后处理:过滤低置信度词语,纠正常见的 OCR 错误(例如将 0 误识为 O、将 1 误识为 l),并规范空白字符。

import re

COMMON_OCR_ERRORS = {
    r'\b0([a-z])\b': r'O\1',
    r'\bl([0-9])\b': r'1\1',
    r'\|': 'I',
    r'  +': ' ',
}

def post_process_ocr(text):
    for pattern, replacement in COMMON_OCR_ERRORS.items():
        text = re.sub(pattern, replacement, text)
    lines = [line.strip() for line in text.splitlines()]
    return '\n'.join(line for line in lines if line)

def high_confidence_ocr(words_with_conf, min_confidence=60):
    words = [w for w, conf in words_with_conf if w.strip() and conf >= min_confidence]
    return post_process_ocr(' '.join(words))

fake_ocr_output = [('0range', 90), ('|s', 40), ('l5', 85), ('good', 95)]
print(high_confidence_ocr(fake_ocr_output))

知识检查

在 OCR 之前对图像应用阈值(二值化)的目的是什么?

回顾:扫描文档的 OCR

OCR 会将扫描图像转换为机器可读的文本。pytesseract 封装了谷歌的 Tesseract,速度快、成熟稳定,并支持 100 多种语言包。EasyOCR 使用深度学习,在处理质量下降的图像和多语言文本方面表现更好。

请始终进行预处理:转换为灰度图,应用 Otsu 阈值处理进行二值化,并校正倾斜以修正旋转。对于基于图像的 PDF,请使用 PyMuPDF 将页面渲染为高 DPI 图像,然后运行 OCR。根据置信度阈值过滤结果,以排除噪声。

常见问题解答

「扫描文档的 OCR」课时是免费的吗?

是的 — 「扫描文档的 OCR」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。

「扫描文档的 OCR」这节课中我会学到什么?

通过 pytesseract 使用 Tesseract,进行图像预处理并提高准确率。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 AI Agents 需要有经验吗?

无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「扫描文档的 OCR」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 AI Agents 课中编写并运行代码吗?

能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 PyMuPDF 和 pdfplumber 解析 PDF
  2. 扫描文档的 OCR
  3. 多文档问答代理
  4. 文档分类与路由
← 返回 AI Agents