為了提高識別率,先用opencv-python對掃描的圖片做預處理(減少背景雜音),然後調用pytesseract識別圖片上的文字。處理方式就是:
1、將圖片的顏色模式轉成灰度模式,再用OTSU做二值化處理
2、將處理結果保存成臨時圖片文件
3、調用pytesseract識別臨時圖片上的文字,識別完畢後刪掉臨時圖片
選擇要識別文字的圖片調用tkinter打開圖形化對話窗口,tkinter是python內置模塊,可直接引進不必安裝。對tkinter不做太多解釋,只是藉助它的功能函數打開對話窗口。引入內置os的功能函數刪除臨時文件。
from PIL import Image # pytesseract識別圖片上的文字時要用import pytesseract # 識別圖片上的文字import cv2 # 圖片預處理,減少背景雜音import os # 刪除臨時文件from tkinter import Tk # 幫忙用圖形化界面找到要識別的圖片文件from tkinter.filedialog import askopenfilenameTk().withdraw() # 這裡不是要全部圖形化界面,所以就不顯示根窗口了imgName = askopenfilename() # 顯示「打開」窗口,返回選中的圖片文件的路徑+文件名字符串# 預處理圖片greyImg = cv2.imread(imgName, 0) # 預處理第一步,彩色模式轉成灰度模式:以灰度模式打開圖片,生成灰度圖片greyImg = cv2.threshold(greyImg, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# 預處理第二步,OTSU二值法,返回的是列表,第二個元素(索引為1)指向被處理的圖片# 將預處理結果保存成臨時文件,文件名用它在系統的進程ID(os.getpid())filename = "{}.png".format(os.getpid())cv2.imwrite(filename, greyImg)# 調用pytesseract將圖片上的文字識別出來txt = pytesseract.image_to_string(Image.open(filename))os.remove(filename) # 刪除臨時圖片文件with open("toFile.txt", 'w', encoding='utf-8') as fObject: fObject.write(txt) # 將識別出來的字符串保存到文本文件
提高圖片文字的識別率和正確率是個大話題,跟圖片上文字的背景有關係,跟圖片解析度有關係,跟識別用的字庫的識別能力也有關係(字庫可以訓練),牽扯的技術手段很多。除了減少背景雜音外,還有一些預處理工作我們也可以做,比如把圖片上有文字的部分截取下來識別(效果很明顯);把圖片上的文字分成一小段一小段識別,甚至分成一個一個字符來識別……有興趣的朋友可以自己研究。
實例二:識別pdf上的文字識別pdf上的文字分幾步進行:
1、引入wand模塊,把pdf文件轉成圖片序列,通過序列的索引可以獲得pdf的每一頁。
2、遍歷這個圖片序列,把序列的每一頁變成wand圖片對象,轉成灰度模式(簡單預處理下,以提高識別度),接下來本應添加進圖像列表req_image中,但卻遇到一個問題:
PyOCR模塊做圖片文字識別的功能函數的形參只接收pillow的Image模塊打開的圖片PIL.Image.open(),不接受wand圖形對象,PIL.Image.open()也不接收wand圖片對象。當然可以wand圖像對象保存成圖片文件,然後PIL.Image.open()打開這個圖片文件。
有個更快的處理方法,不用硬碟(硬碟慢)做媒介用緩存(buffer):先用wand圖片對象的make_blob把圖片轉成二進位數據流,把二進位數據流放入列表req_image中。
3、遍歷列表req_image,ByteIO()讀取二進位數據流,返回值可以被PIL.Image.open()接受。接下去就可以調用PyOCR模塊的功能函數做圖片文字轉換了。
4、將識別結果放進列表final_text,用pprint模塊的pprint()顯示出來。pprint,pretty print顧名思義,輸出結果規整好看一些。
from wand.image import Image as wandImage # pdf –> jpegfrom PIL import Image as pillowIMage # PyOCR需要import pyocr.builders # OCR識別import io # 將Wand處理結果傳給給Pillowimport pprint # 美美的列印出來# PyOCR初始化tool = pyocr.get_available_tools()[0] # 獲得OCR內核工具,這裡用的是Tesseractlang = tool.get_available_languages()[0]# 獲得識別用語言,這裡用的是簡體中文,參見20.2 PyOCR的初始化程序req_image = [] # 存放pdf轉換過來的圖片二進位數據流final_text = [] # 存放識別結果,每個元素是每一頁識別出來的文字ima_pdf = wandImage(filename='instance.pdf', resolution=300)# 打開pdf文件,生成wand圖片對象。解析度設為300,設高解析度有助於提高識別率image_jpeg = ima_pdf.convert('jpeg') # pdf文件轉成圖片,實際上是個圖片序列,序列的長度與pdf的頁數相同for img in image_jpeg.sequence: # 遍歷圖片序列的每頁圖片 img_page = wandImage(image=img) # 生成為wand圖片對象 img_page.type = 'grayscale' # 轉成灰度模式有助於OCR識別文字req_image.append(img_page.make_blob('jpeg')) # 轉成二進位數據流放進列表for img in req_image: # 一頁一頁OCR識別文字 text = tool.image_to_string( pillowIMage.open(io.BytesIO(img)), # io.BytesIO()從內存中讀入二進位數據流 lang=lang, # 識別語言 builder=pyocr.builders.TextBuilder() # 識別器 ) final_text.append(text) # 識別出來的結果添進列表pprint.pprint(final_text) # 顯示識別結果