如何使用pytesseract为有意义的连续词组生成单个边界框
问题说明
使用pytesseract.image_to_data()开展OCR识别时,默认绘制所有粒度的边界框会得到单单词独立框选的效果,原始实现代码如下:
import pytesseract from pytesseract import Output import cv2 img = cv2.imread('Page_2.jpg') d = pytesseract.image_to_data(img, output_type=Output.DICT) n_boxes = len(d['level']) for i in range(n_boxes): (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i]) cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
目标是将类似invoice number的连续有意义词组用单个边界框整体包裹。



实现方案
方案1:调用Tesseract内置行级识别结果
image_to_data返回结果的level字段对应不同识别粒度:
- 层级1:整页
- 层级2:文本块
- 层级3:段落
- 层级4:单行文本
- 层级5:单个单词
原始代码遍历了所有层级的框,因此拿到最细粒度的单词框。直接筛选level=4的行级结果绘制,即可得到同一行连续文本的整体边界框,代码修改如下:
import pytesseract from pytesseract import Output import cv2 img = cv2.imread('Page_2.jpg') d = pytesseract.image_to_data(img, output_type=Output.DICT) n_boxes = len(d['level']) for i in range(n_boxes): # 仅绘制行级边界框 if d['level'][i] == 4: x, y, w, h = d['left'][i], d['top'][i], d['width'][i], d['height'][i] cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
如果行内存在间距过大的无关文本,可在拿到行级结果后,基于行内单词的水平间距做二次过滤,仅合并间距小于阈值(通常设为平均字符宽度的1-2倍)的相邻单词,避免无关内容被整体框选。
方案2:自定义规则合并语义词组
如果需要精准框选特定语义词组(如仅框选"invoice number"这类字段,不框选整行其他内容),可按以下逻辑实现:
- 提取所有
level=5的单词结果,记录每个单词的文本、坐标、所属行号 - 按行号对单词分组,同一行内单词按x轴坐标从小到大排序
- 遍历同组相邻单词,符合合并规则则归为同一词组:可预设目标词表匹配,也可通过单词间距、垂直对齐度判断是否属于同一语义块
- 合并后的词组框取组内所有单词的最小x、y为左上角,最大x+w、y+h为右下角,绘制矩形即可。
该方案灵活度最高,可根据业务场景自由调整合并规则。
内容的提问来源于stack exchange,提问作者aditya
相关产品推荐
相关产品推荐

