最近在使用Python识别PNG图像中包含的文字时遇到一个问题。解决过程记录如下。
(Python使用tesserocr的安装过程不再描述。)
在使用tesserocr识别PNG图像中的文字时,如果PNG比较“干净”,背景没有噪音时,过程比较简单,代码如下:
from PIL import Image import tesserocr image = Image.open(r'../data/demo01.png') print(tesserocr.image_to_text(image))
输出结果为:
This is some text, written in Arial, that will be read by Tesseract. Here are some symbols: !@#$%"&’()
效果还算可以。
但是如果PNG图片背景有些复杂,在识别之前需要对PNG做一些处理,比如针对下面这幅PNG图片:
这里使用的是简单的阈值过滤,即小于阈值的像素值均设置为黑色(0),大于阈值的像素值设置为白色(255);然后再对处理后的图像进行处理。代码如下:
from PIL import Image import tesserocr def clear_file(file_path, new_file_path): image = Image.open(file_path) # 为图像设置一个阈值过滤器并保存 image = image.point(lambda x: 0 if x < 143 else 255) image.save(new_file_path) return image image = clear_file(r'..\data\demo02.png', r'..\data\demo02_cleaned.png') print(tesserocr.image_to_text(image))
本以为会顺利输出结果,但是执行结果却是报了一堆错误:
…… File "E:\PrivatedData\programs\python\wasp\env\lib\site-packages\PIL\Image.py", line 2212, in save save_handler(self, fp, filename) File "lib\site-packages\PIL\JpegImagePlugin.py", line 632, in _save raise OSError(f"cannot write mode {im.mode} as JPEG") from e OSError: cannot write mode RGBA as JPEG
错误非常奇怪,明明是PNG图像,怎么说要处理JPEG图像呢?
通过跟踪,发现在选择图像文件的处理方法时,有如下代码(在Image.py的save函数中):
if save_all: save_handler = SAVE_ALL[format.upper()] else: save_handler = SAVE[format.upper()]
代码的主要意图是要根据format的值来选择图片的处理函数,而此时format的值为‘JPEG’,因此Pillow就用JPEG的处理函数来处理PNG图像了,所以会出错。
很奇怪,不是根据扩展名来识别图像格式吗。我从头到尾就没有使用到JPEG图像。我不知道Pillow的Image类在什么时候、用什么方式确定format的值。
想在网上查找tesserocr的API文档,看能不能把这个format传递过去,但是没有找到。
于是尝试自己设置图像的format,看能否通过。于是有了下面的代码:
image = clear_file(r'..\data\demo02.png', r'..\data\demo02_cleaned.png') image.format = 'PNG' print(tesserocr.image_to_text(image))
输出结果为:
This Is some text, wntten In Arial, that will be " Tesseract Here are some symbols: l@#$%"&
这里只是一小段练习代码。如果在正式项目中,可以根据图片文件的扩展名来给image.format赋值。当然能不使用“硬”代码更好,但我一直没有找到相关的文档,不知道问题的根本原因是什么。先把这个记录下来,其他继续研究吧。