如何在pytesseract的image_to_boxes中降低文本粒度实现单词级框选?
解决单词级文本边界框识别问题
针对你遇到的情况,给你几个实用的解决思路:
1. 调整Tesseract的页面分割模式(PSM)
image_to_data出现漏检,大概率是页面分割模式参数没适配你的图片。可以根据文本排版尝试不同的PSM参数:
- 如果图片是单行文本,用
psm=7 - 如果是整块无格式的文本块,用
psm=6 - 多行规整文本可以用默认
psm=3搭配--oem=3(混合引擎模式)
示例代码:
import pytesseract from PIL import Image img = Image.open("你的图片.png") # 配置单行文本识别模式 custom_config = r'--oem 3 --psm 7' data = pytesseract.image_to_data(img, config=custom_config, output_type=pytesseract.Output.DICT) # 过滤空文本条目,提取单词级框 word_boxes = [] for i in range(len(data['text'])): text = data['text'][i].strip() if text: x = data['left'][i] y = data['top'][i] w = data['width'][i] h = data['height'][i] word_boxes.append((x, y, x+w, y+h, text))
2. 手动合并image_to_boxes的字符框为单词框
如果调整PSM后效果仍不好,可以用image_to_boxes拿到每个字符的框,再根据位置特征合并成单词:
- 同一行的字符(y轴范围重叠)
- 字符间的水平间距小于设定阈值(比如字符宽度的一半)
示例代码:
import pytesseract from PIL import Image img = Image.open("你的图片.png") img_height = img.height boxes = pytesseract.image_to_boxes(img).splitlines() word_boxes = [] current_word = [] line_y_min, line_y_max = None, None for box in boxes: char, x1, y1, x2, y2, _ = box.split() x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) # 转换坐标(Tesseract的y轴从图片底部开始计算) y1, y2 = img_height - y1, img_height - y2 if not current_word: current_word.append((x1, y1, x2, y2, char)) line_y_min, line_y_max = y1, y2 else: # 判断是否为同一行且间距符合单词内字符的间距 same_line = abs(y1 - line_y_min) < 10 and abs(y2 - line_y_max) < 10 gap = x1 - current_word[-1][2] if same_line and gap < 20: # 间距阈值可根据图片实际情况调整 current_word.append((x1, y1, x2, y2, char)) else: # 合并当前单词的边界框 word_x1 = min([b[0] for b in current_word]) word_y1 = min([b[1] for b in current_word]) word_x2 = max([b[2] for b in current_word]) word_y2 = max([b[3] for b in current_word]) word_text = ''.join([b[4] for b in current_word]) word_boxes.append((word_x1, word_y1, word_x2, word_y2, word_text)) current_word = [(x1, y1, x2, y2, char)] line_y_min, line_y_max = y1, y2 # 处理最后一个单词 if current_word: word_x1 = min([b[0] for b in current_word]) word_y1 = min([b[1] for b in current_word]) word_x2 = max([b[2] for b in current_word]) word_y2 = max([b[3] for b in current_word]) word_text = ''.join([b[4] for b in current_word]) word_boxes.append((word_x1, word_y1, word_x2, word_y2, word_text))
3. 图片预处理优化
针对字体过大、字母间距大的情况,预处理能提升Tesseract的识别准确性:
- 对图片做二值化处理,减少背景干扰
- 调整对比度,强化文本边缘
- 适当缩放图片,让字符大小更贴合Tesseract的默认识别范围
示例二值化代码:
img = Image.open("你的图片.png").convert('L') threshold = 127 # 把灰度图转为黑白二值图 img = img.point(lambda x: 0 if x < threshold else 255, '1')
内容的提问来源于stack exchange,提问作者Bex T.
相关产品推荐
相关产品推荐

