真正能落地的表格ocr方案必须分两步:先用opencv定位单元格(灰度二值化→霍夫线检测→线段聚类→交叉生成roi),再逐单元格调用pytesseract(--psm 7 --oem 3,resize≥30px,倾斜校正),最后用openpyxl逐格写入并处理合并单元格。

直接用 pytesseract 识别表格图片,90% 的情况会把行列结构全打乱——它只输出纯文本,不保留表格拓扑。真正能落地的方案必须分两步:先用图像处理或检测模型定位单元格,再对每个单元格单独 OCR。
用 cv2 + numpy 提取表格线框和单元格坐标
很多表格有清晰的横线/竖线,OpenCV 的霍夫线变换能稳定检出。关键不是“画出来”,而是拿到每条线的坐标,再聚类合并相近线段,最后交叉生成单元格左上/右下角坐标。
- 先转灰度、二值化(
cv2.THRESH_BINARY + cv2.THRESH_OTSU效果通常比固定阈值好) - 用
cv2.HoughLinesP检测线段,minLineLength和maxLineGap得调:太小会碎成多段,太大则漏线 - 把所有竖线 x 坐标排序去重(容忍 3px 误差),横线 y 坐标同理,得到列边界和行边界数组
- 遍历组合,每个
(x_i, y_j)到(x_{i+1}, y_{j+1})就是一个单元格 ROI
用 pytesseract.image_to_string 逐单元格识别,禁用自动换行
直接对整图 OCR 会触发 tesseract 的段落分析逻辑,强行折行、合并相邻列。但传入一个已裁切的单元格图像时,应关闭所有布局猜测。
- 必须加配置:
config='--psm 7 --oem 3'(psm 7 表示“单行文本”,避免分词;oem 3 是 LSTM 引擎,对印刷体更稳) - 单元格图像要 resize 到高度 ≥30px,tesseract 对小字号识别率断崖下跌
- 如果单元格内文字倾斜,先用
cv2.minAreaRect算角度并仿射校正,否则识别错误率翻倍
写入 Excel 时用 openpyxl 而非 pandas.DataFrame.to_excel
pandas 写 Excel 会强制把所有内容当字符串或数字处理,丢失空单元格、合并单元格、跨行文本等原始结构信息。而表格截图里常有跨行标题或空列,必须用底层控制。
- 用
openpyxl.Workbook()新建工作簿,ws.cell(row=r, column=c).value = text逐格赋值 - 若原图中某单元格实际跨了 2 行,在写入前需调用
ws.merge_cells(start_row=r, start_column=c, end_row=r+1, end_column=c) - 注意:openpyxl 行列索引从 1 开始,不是 0 —— 这个错会导致整张表偏移
最易被忽略的是图像 DPI 和字体缩放:手机拍的表格图若未 resize,tesseract 会因像素过密把“1”和“l”、“0”和“O”全认混;而扫描件 DPI 过低(
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











