如何使用pytesseract获取文本图像整行/整段文本边界框坐标
问题根因
之前的实现未得到预期整行/整段外框,核心原因有两个:
- 自定义行合并的边界框更新逻辑错误:行/段外框是包裹所有子文本块的最小矩形,不能直接累加top、width、height参数,必须对同组所有单词框取坐标极值计算
- 自行判断同行的逻辑可靠性差:
pytesseract.image_to_data本身返回了完整的层级ID字段,不需要自己写坐标阈值判断行归属,自定义规则很容易因行间距、字体偏移出现错判,导致合并失败
正确实现方案
image_to_data返回结果自带3个层级标识字段,可直接用于分组:
block_num:检测到的独立文本块IDpar_num:文本块内的自然段落IDline_num:段落内的行ID
以上字段搭配页码字段page_num可唯一定位到一行,搭配block_num可唯一定位到一个段落/文本块。
完整实现代码
import cv2 import pytesseract from pytesseract import Output import pandas as pd # 读取图像 img = cv2.imread("your_text_image.png") # 获取OCR原始结果,lang参数按需替换为对应的语言包 ocr_result = pytesseract.image_to_data(img, output_type=Output.DICT, lang='eng+chi_sim') # 转为DataFrame并过滤无效条目 df = pd.DataFrame(ocr_result) df = df[ df['text'].notna() & (df['text'].str.strip() != '') & (df['conf'] != -1) # 过滤置信度为-1的无效识别结果 ].reset_index(drop=True) # 坐标列转为数值类型,避免字符串计算错误 for col in ['left', 'top', 'width', 'height']: df[col] = pd.to_numeric(df[col]) # 计算行级外框 line_groups = df.groupby(['page_num', 'block_num', 'par_num', 'line_num']) line_df = [] for group_key, group in line_groups: page, block, para, line = group_key # 取极值计算最小外框 left = group['left'].min() top = group['top'].min() right = (group['left'] + group['width']).max() bottom = (group['top'] + group['height']).max() line_df.append({ 'page_num': page, 'block_num': block, 'par_num': para, 'line_num': line, 'left': left, 'top': top, 'width': right - left, 'height': bottom - top, 'text': ' '.join(group['text'].str.strip().tolist()) }) line_df = pd.DataFrame(line_df) # 计算段落级外框 para_groups = df.groupby(['page_num', 'block_num', 'par_num']) para_df = [] for group_key, group in para_groups: page, block, para = group_key left = group['left'].min() top = group['top'].min() right = (group['left'] + group['width']).max() bottom = (group['top'] + group['height']).max() para_df.append({ 'page_num': page, 'block_num': block, 'par_num': para, 'left': left, 'top': top, 'width': right - left, 'height': bottom - top, 'text': ' '.join(group['text'].str.strip().tolist()) }) para_df = pd.DataFrame(para_df) # 绘制结果验证 # 红色线绘制行级框 for _, row in line_df.iterrows(): cv2.rectangle( img, (row['left'], row['top']), (row['left'] + row['width'], row['top'] + row['height']), (0, 0, 255), 2 ) # 蓝色线绘制段落级框 for _, row in para_df.iterrows(): cv2.rectangle( img, (row['left'], row['top']), (row['left'] + row['width'], row['top'] + row['height']), (255, 0, 0), 1 ) cv2.imwrite("ocr_box_result.png", img)
关键规则说明
同一分组(行/段落/整页)的外框计算必须遵循极值规则:
- 外框左边界 = 组内所有单词框
left的最小值 - 外框上边界 = 组内所有单词框
top的最小值 - 外框右边界 = 组内所有单词框
left + width的最大值 - 外框下边界 = 组内所有单词框
top + height的最大值 - 外框宽度 = 右边界 - 左边界
- 外框高度 = 下边界 - 上边界
如果需要整页文本的全局外框,直接对所有有效单词框套用以上极值规则计算即可。
内容的提问来源于stack exchange,提问作者sha25
相关产品推荐
相关产品推荐

