OCR 与图像

一份 TIFF 不一定只有一张图:逐帧处理才不漏页

一份 TIFF 打开后只处理了第一页,程序没有报错,却已经漏掉其余内容。对于多帧格式,“成功打开文件”与“完整处理文件”是两回事。入口应该先识别页数,再决定逐页处理、预算限制和交付清单。

阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。 一份 TIFF 打开后只处理了第一页,程序没有报错,却已经漏掉其余内容。对于多帧格式,“成功打开文件”与“完整处理文件”是两回事。入口应该先识别页数,再决定逐页处理、预算限制和交付清单。 迭代帧时复制当前图像 ImageSequence.Iterator 适合遍历多帧图像,但帧对象可能与底层解码状态相关。若后续要独立使用各页,应在迭代时复制或立即处理。不要把同一个可变对象的引用反复保存,再期待得到互不影响的页面。 构造两帧 TIFF 验证不漏页 from io import BytesIO from PIL import Image, ImageSequence first = Image.new("RGB", (12, 8), "white") second = Image.new("RGB", (12, 8), "black") stream = BytesIO() first.save(stream, format="TIFF", save_all=True, append_images=[second]) stream.seek(0) with Image.open(stream) as document: assert document.n_frames == 2 pages = [frame.copy() for frame in ImageSequence.Iterator(document)] assert len(pages) == 2 assert pages[0].getpixel((0, 0)) == (255, 255, 255) assert pages[1].getpixel((0, 0)) == (0, 0, 0) pages[0].putpixel((0, 0), (255, 0, 0)) assert pages[1].getpixel((0, 0)) == (0, 0, 0) 这里把两页全部留在内存,只适合这个极小合成例子。真实扫描卷宗应逐页处理或使用受控批次,并记录每页结果,不能把所有高分辨率帧复制后无限堆积。 页数之外还有逐页差异 项目 为什么逐页检查 可记录内容 尺寸 同文件页面不一定同大小 宽高与像素数 模式 黑白与彩色页可能混合 原始模式与转换策略 方向 不同页可能不同 每页方向变换 失败状态 某页损坏不应被忽略 页码、错误类别 部分成功要明确写出来 如果十页里处理了九页,不能仅返回一份文件并标记全部完成。清单应列出缺失页与原因,让用户决定重传、单独处理或接受部分交付。页号最好保持来源编号,不因失败页被跳过而重新编号。 翻译完整性从输入页数开始 用 OmniDoc(产品入口) 工作流处理多页扫描资料时,可以比较输入页清单与译后内容范围。页数相同不自动证明内容完整,但页数或页号缺失是很有价值的警报。完整性检查应先于语言润色。 参考: Pillow ImageSequence 。 - 1 -
更新于 2026-10-08