如何为Python裁剪后的图片设置/获取DPI以优化Tesseract OCR效果?
我用代码打开PDF,把第一页转成图片,再按坐标裁剪出矩形区域,用Tesseract提取每个区域的文本。但发现部分大尺寸图片的OCR识别效果比其他图片差很多。在命令行测试Tesseract时,发现它会自动估算图片分辨率,这直接影响识别结果。我试过调整--dpi参数,有的图片设为1800效果最好,有的设为300效果最佳。我想找到在提取文本前设置或获取图片DPI的方法,之前试过pix.set_dpi()和get_pixmap(dpi=..),但没任何改善,求相关建议。
附上我的代码:
page = doc.load_page(0) page_size = page.rect zoom = 3 mat = fitz.Matrix(zoom, zoom) pix = page.get_pixmap(matrix=mat) img_data = pix.samples img_array = np.frombuffer(img_data, dtype=np.uint8) img_array = img_array.reshape(pix.height, pix.width, pix.n) img = cv.cvtColor(img_array, cv.COLOR_RGB2BGR) #... k=0 result_dict = {} for i, rect in enumerate(rectangles): x1, y1, x2, y2 = rect roi = img[y1:y2, x1:x2] k+=1 text = pytesseract.image_to_string(roi, lang="eng+deu")
可行解决方案
1. 直接给Tesseract指定DPI参数
不需要修改图片本身的DPI元数据,在调用pytesseract.image_to_string()时通过config参数传入--dpi,针对不同图片或ROI动态调整:
# 示例:针对当前ROI指定1800 DPI text = pytesseract.image_to_string(roi, lang="eng+deu", config="--dpi 1800")
如果不确定最优DPI,可以做简单的批量测试:遍历常用DPI值(300、600、1200、1800),对比识别准确率,自动选择效果最好的参数。
2. 正确设置PyMuPDF生成图片的DPI
你之前用get_pixmap(dpi=..)没效果,是因为这个参数需要配合matrix正确使用,或者直接用dpi参数替代缩放矩阵。正确的用法是:
# 直接指定DPI生成图片,无需手动计算zoom pix = page.get_pixmap(dpi=300) # 或1800,根据需求设置
这样生成的图片会带有正确的DPI元数据,Tesseract会优先读取这个值,不需要额外指定--dpi参数。
3. 给OpenCV图片添加DPI元数据
如果必须用OpenCV处理图片,可以通过保存图片时写入DPI信息,再重新读取供Tesseract使用:
# 保存ROI时写入DPI参数 cv.imwrite("temp_roi.png", roi, [cv.IMWRITE_PNG_COMPRESSION, 0, cv.IMWRITE_PNG_RESOLUTION, 1800]) # 从保存的文件读取,Tesseract会识别DPI text = pytesseract.image_to_string("temp_roi.png", lang="eng+deu")
注意:PNG的分辨率参数单位是像素/英寸,直接传入数值即可。
4. 根据PDF原始尺寸计算最优DPI
PDF本身是矢量格式,你可以通过原始页面尺寸计算合适的DPI:
# 获取PDF页面的原始尺寸(单位:点,1点=1/72英寸) page_width = page.rect.width page_height = page.rect.height # 计算目标像素对应的DPI:比如要生成宽度为3000像素的图片 target_width_pixels = 3000 dpi = (target_width_pixels / page_width) * 72 # 用计算出的DPI生成图片 pix = page.get_pixmap(dpi=dpi)
这种方式能保证图片的缩放比例匹配原始文档的印刷分辨率,减少Tesseract的估算误差。
内容的提问来源于stack exchange,提问作者cheesesoup

