🐸 青蛙编程网
首页 / AI / 文字识别 OCR / 6. 综合练习:批量图片转文本

6. 综合练习:批量图片转文本

这是什么:批量图片转文本 = 一个跑完就能用的命令行小工具,把整个文件夹的截图批量转成文本文件。

为什么用:前面五章都是一次处理一张图,手工一张张点既慢又容易漏。真正的活儿是几十上百张截图堆在一起,能不能一句话全转出来才是关键。

如何用:本章把遍历文件夹、预处理、识别、保存结果四步串起来,写成 python batch_ocr.py 一条命令跑完。

6.1 功能设计

动手写代码前,先把「输入什么、输出什么」定下来:

项 内容
输入 一个图片文件夹(含 .png / .jpg / .jpeg)
处理 遍历 → 预处理 → 识别 → 取文字
输出 同目录下生成同名 .txt,每张图一个文件
关键约束 只处理图片后缀;跳过读不出的图;文件用 UTF-8 写

整个工具拆成三个函数,各管一件事:

preprocess()  →  把图变成模型喜欢的干净图(灰度/放大/去噪/二值化)
ocr_single()  →  把一张图变成一段文本
batch_ocr()   →  把一个文件夹跑完并落盘

好处是:以后想换识别引擎(EasyOCR → PaddleOCR),只需改 ocr_single 一个函数。

6.2 完整脚本(基于 EasyOCR)

import os
import cv2
import easyocr

reader = easyocr.Reader(['ch_sim', 'en'])

def preprocess(img_path, scale=2, threshold=130):
    """灰度 → 放大 → 去噪 → 二值化,返回可直接喂给 OCR 的图片"""
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise FileNotFoundError(f'读不出图片:{img_path}')
    img = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
    img = cv2.GaussianBlur(img, (5, 5), 0)
    _, binary = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
    return binary

def ocr_single(img_path):
    img = preprocess(img_path)
    # EasyOCR 直接吃 numpy 数组,不用先存成临时文件
    return reader.readtext(img, detail=0, paragraph=True)

def batch_ocr(folder):
    count = 0
    for filename in sorted(os.listdir(folder)):
        if not filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            continue
        img_path = os.path.join(folder, filename)
        text = '\n'.join(ocr_single(img_path))
        txt_path = os.path.splitext(img_path)[0] + '.txt'
        with open(txt_path, 'w', encoding='utf-8') as f:
            f.write(text)
        count += 1
        print(f'✅ {filename} → {txt_path}')
    print(f'共处理 {count} 张图片')

if __name__ == '__main__':
    batch_ocr('screenshots/')

6.3 运行与验收

# 1. 准备测试图(5–10 张)放进 screenshots/
# 2. 运行脚本
python batch_ocr.py

# 3. 检查输出(Windows 用 type,macOS/Linux 用 cat)
type screenshots\test1.txt

你会看到:

✅ test1.png → screenshots\test1.txt
✅ test2.png → screenshots\test2.txt
共处理 2 张图片

每一张图对应一个文本文件,后续可批量导入数据库或做关键词搜索。

6.4 进阶:置信度过滤

段落模式下没有置信度(第 3 章讲过),所以要按置信度筛掉低分行,就老老实实开 detail=1、别开 paragraph:

def batch_ocr_with_conf(folder, conf_thresh=0.8):
    count = 0
    for filename in sorted(os.listdir(folder)):
        if not filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            continue
        img_path = os.path.join(folder, filename)
        result = reader.readtext(img_path, detail=1)   # 要置信度,就别开 paragraph
        lines = [text for _, text, conf in result if conf >= conf_thresh]
        if not lines:
            print(f'⚠️ {filename}:没有一行过线(阈值 {conf_thresh})')
            continue
        txt_path = os.path.splitext(img_path)[0] + '.txt'
        with open(txt_path, 'w', encoding='utf-8') as f:
            f.write('\n'.join(lines))
        count += 1
        print(f'✅ {filename} → {txt_path}')
    print(f'共处理 {count} 张图片')

低分行人工复核 → 识别质量更稳。阈值别一上来就调太高:0.6~0.8 是常用区间。

6.5 再往前一步:让结果真正有用

文本落盘只是起点,三个常见的下游:

需求 怎么接
存进数据库做全文检索 把 text 写成一条记录,配上文件名和时间戳
交给 AI 做摘要 / 分类 读出 .txt,拼进 Prompt 送给 LLM(LLM 教程)
只挑关心的图片 用置信度阈值过滤,只处理高分图,省时间省算力

一句提醒:OCR 只负责「把字读出来」,读得准不准取决于图片质量和预处理(上一章);要更高精度就换 PaddleOCR 的中文模型。

6.6 常见翻车现场

报错 / 现象 原因 修法
ValueError: not enough values to unpack 开了 paragraph=True 却按三元组解包 段落模式只有两项,取 item[1];或关掉 paragraph
输出的 txt 是空的 图片没文字,或阈值太严 调低 conf_thresh,或先跑 6.2 原图版对照
FileNotFoundError 路径带了尾斜杠或图片在别的目录 用 os.path.abspath() 打印确认
脚本跑完但没生成文件 文件夹里没有图片,或后缀不在白名单 打印 os.listdir(folder) 核对
中文变成乱码 写文件时没指定编码 open(..., encoding='utf-8')

6.7 动手改

  1. 给脚本加「跳过空图」逻辑(图片大小为 0 时跳过)
  2. 把 batch_ocr_with_conf 改成「导出 JSON」,每条含 {filename, text, conf}
  3. 用 PaddleOCR 替换 EasyOCR,对比批量识别的准确率与耗时

6.8 小结

  • 批量 OCR = 预处理 + 识别 + 保存,三步链
  • 函数拆成三段,换引擎只改一处
  • EasyOCR 能直接吃 numpy 数组,不必落临时文件
  • 段落模式没有置信度,要复核就退回 detail=1
  • 以后遇到「把几十张截图变文本」的需求,直接复用这套流程

OCR 完成!你可以把截图里的任意内容「读」进程序了 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。