深度使用tesseract-OCR技術(shù)識別圖形驗證碼
前言:本片文章是基于我之前發(fā)的一篇文章《【爬蟲】8.1. 使用OCR技術(shù)識別圖形驗證碼》而寫的,鏈接為:
【爬蟲】8.1. 使用OCR技術(shù)識別圖形驗證碼,前面這篇文章比較基礎(chǔ)。入門了tesseract-OCR技術(shù)之后對它比較感興趣,故繼續(xù)深度學(xué)習(xí)以下。為了銜接比較好,故本篇文章前面講到的會和前面一篇文章有一些重復(fù)。
突然發(fā)現(xiàn)一個問題,csdn的圖片有水印…不管了,湊合看吧,但是代碼運行就要自己找圖片了
1. OCR技術(shù)
OCR,即Optical Character Recognition,中文叫做光學(xué)字符識別,是指使用電子設(shè)備(例如掃描儀和數(shù)碼相機(jī))檢查打印再紙上的字符,通過檢查暗、亮的模式確定字符形狀,然后使用字符識別方法將形狀轉(zhuǎn)化位計算機(jī)文字?,F(xiàn)在OCR技術(shù)已經(jīng)廣泛應(yīng)用于生產(chǎn)活動中,如文檔識別,證件識別,字幕識別,文檔搜索等。當(dāng)然用來識別本節(jié)所述的圖形驗證碼也沒有問題。
2. 準(zhǔn)備工作
我用的庫是pytesseract,有的人用的是tesserocr,其實兩者感覺差別不大:
- 打開tesseract下載的網(wǎng)頁 tesseract,下載最后一個(應(yīng)該是)tesseract-ocr-w64-setup-v5.3.0.2.221214這個版本,接著就是安裝,安裝過程中自己記好自己安裝在哪里!??!然后就是選擇語言包,建議不要全選會下載很慢。
- 將你記下來的安裝路徑的整個文件地址給添加到環(huán)境變量中去。
- 接著python安裝pytesseract,找到pytesseract.py文件,打開并找到tesseract_cmd這個變量(大約在30行左右)將里面的值修改為tesseract.exe文件的地址(這個文件在你一開始記下的文件地址里面,查找文件夾就找到了,不用進(jìn)其他的文件夾,注意轉(zhuǎn)義字符)。
- 搞定上述之后在cmd窗口運行tesseract --list-langs可以看到你下載的語言包。
- 重啟,然后運行你的示例代碼就行了,如果還不可以,那你去看其他下載教程。
以下是一篇在Ubuntu18.04安裝Tesseract庫的博客,需要的請?zhí)D(zhuǎn):
開源OCR識別庫-tesseract介紹-平凡的編程者-博客園(cnblogs.com)
3. 簡單作用了解
先簡單了解下有啥用吧。
3.1. 驗證碼圖片爬取-screenshot_as_png
這個網(wǎng)頁使用JavaScript渲染出來的,我們進(jìn)行爬取的時候使用selenium自動化測試工具。
from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image
from io import BytesIO
import time
def demo():
browser = webdriver.Chrome()
browser.get("https://captcha7.scrape.center")
time.sleep(3)
captcha = browser.find_element(By.CSS_SELECTOR,"#captcha")
image = Image.open(BytesIO(captcha.screenshot_as_png))
image.show()
if __name__ == "__main__":
demo()
這里使用了我很少見的BytesIO,這是一個類,它的功能是讀取二進(jìn)制數(shù)據(jù)流,而圖片就是二進(jìn)制數(shù)據(jù)流;還有就是captcha.screenshot_as_png這部分的功能就是將當(dāng)前頁面的內(nèi)容捕獲為一張圖像,以bytes二進(jìn)制數(shù)據(jù)保存;最后調(diào)用image的show方法來顯式驗證碼的圖像。
3.2. 識別測試-image_to_string
本小節(jié)的驗證碼案例網(wǎng)站為https://captcha7.scrape.center,使用的是image_to_string,當(dāng)然還有其他的,等會再說。
3.2.1. 正確識別
首先我們選用兩張圖片來進(jìn)行測試,第一張是有換行和明顯空格,第二張是一張驗證碼。
我們運行下面代碼:
import pytesseract
from PIL import Image
image1 = Image.open("tesseract_tt1.png")
result1 = pytesseract.image_to_string(image1)
image2 = Image.open("tesseract_tt2.png")
result2 = pytesseract.image_to_string(image2)
print(result1, end= '')
print("=========")
print(result2, end= '')
Demons
Lin
Ss ZzTU
=========
2034
我們可以看到在輸出SZTU這部分時候出現(xiàn)了SsZz這樣大小寫都輸出的情況,這是因為pytesseract庫在識別大小寫字母時候很難準(zhǔn)確識別出大小寫,你可以采取其他辦法來執(zhí)行,這里就不列出來。
3.2.2. 錯誤識別
我選取到了一張圖片,如下所示:
import pytesseract
from PIL import Image
image = Image.open("error.png")
result = pytesseract.image_to_string(image)
print(result, end= '')
04-8 d.
可以看到這個輸出結(jié)果明顯不是我們想要的,這是因為OCR識別技術(shù)是通過檢查暗、亮的模式確定字符形狀,不是我們想當(dāng)然的用腦子來看。所以,我們需要做一些額外處理,把干擾信息去掉,我們觀察發(fā)現(xiàn),圖片里哪些造成干擾的點,其顏色大多比文本的顏色更淺,因此可以通過顏色將干擾點去掉。首先將保存的圖片轉(zhuǎn)化為數(shù)組,看一下維度:
from PIL import Image
import numpy as np
image = Image.open("error.png")
print(np.array(image).shape)
print(image.mode)
(38, 112, 4)
RGBA
從結(jié)果上可以看出,這個圖片其實是一個三維數(shù)組,38和112代表圖片的高和寬,4則是每個像素點的表示向量,那為什么是4呢?因為最后一維是一個長度為4的數(shù)組分別表示R(紅)G(綠)B(藍(lán))A(透明度),即一個像素點由4個數(shù)字表示。那為什么是RGBA而不是RGB或者其他的呢?因為image.mode是RGBA,即由透明通道的真彩色。
mode屬性定義了圖片的類型和像素的位寬,一共由9種類型:
- 1:像素用1位表示,Python中表示為True或False,即二值化。
- L:像素用8位表示,取值位0-255,表示灰度圖像,數(shù)字越小,顏色越黑。
- P:像素用8位表示,即調(diào)色板數(shù)據(jù)。
- RGB:像素用3X8位表示,即真彩色。
- RGBA:像素用4X8位標(biāo)識,即有透明通道的真彩色。
- CMYK:像素用4X8位表示,即印刷四色模式。
- YCbCr:像素用3X8位表示,即彩色視頻格式。
- I:像素用32位整型表示。
- F:像素用32位浮點型表示。
3.2.3. 灰度調(diào)節(jié)
讓識別更加準(zhǔn)確,可以把RGBA轉(zhuǎn)化位更簡單的L,即把圖片轉(zhuǎn)化位灰度圖像。往圖片對象的convert方法中傳入L即可,代碼如下表示:
image = image.convert('L')
image.show()
我們選擇把圖片轉(zhuǎn)化位灰度圖像,然后根據(jù)閾值刪除圖片上的干擾點,成功識別出驗證碼,也可以調(diào)用image的show方法來查看圖像,代碼如下:
from PIL import Image
import numpy as np
image = Image.open("error.png")
image = image.convert('L')
threshold = 90
array = np.array(image)
array = np.where(array> threshold, 255, 0)
image = Image.fromarray((array.astype('uint8')))
# image.show()
result = pytesseract.image_to_string(image)
print(result)
這里先將變量threshold賦值位50.它代表灰度的閾值。接著將圖片轉(zhuǎn)化位Numpy數(shù)組,利用Numpy的where方法對數(shù)組進(jìn)行篩選和處理,其中將灰度大于閾值的圖片的像素設(shè)置為255表示白色,否則為0,表示黑色。Image.fromarray((array.astype(‘uint8’))) 是使用PIL(Python Imaging Library)庫將numpy數(shù)組轉(zhuǎn)換為圖像。
3.3. 識別實戰(zhàn)-使用image_to_string對象
看懂就行了,識別可能不太準(zhǔn)確。
import time
import re
import pytesseract
from selenium import webdriver
from io import BytesIO
from PIL import Image
from retrying import retry
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import numpy as np
def preprocess(image):
image = image.convert('L')
array = np.array(image)
array = np.where(array > 105, 255, 0)
image = Image.fromarray(array.astype('uint8'))
return image
@retry(stop_max_attempt_number=10, retry_on_result=lambda x: x is False)
def login():
browser.get('https://captcha7.scrape.center/')
browser.find_element(By.CSS_SELECTOR, '.username input[type="text"]').send_keys('admin')
browser.find_element(By.CSS_SELECTOR, '.password input[type="password"]').send_keys('admin')
captcha = browser.find_element(By.CSS_SELECTOR,'#captcha')
image = Image.open(BytesIO(captcha.screenshot_as_png))
image = preprocess(image)
image.show()
captcha = pytesseract.image_to_string(image)
print(captcha)
captcha = re.sub('[^A-Za-z0-9]', '', captcha)
browser.find_element(By.CSS_SELECTOR, '.captcha input[type="text"]').send_keys(captcha)
browser.find_element(By.CSS_SELECTOR, '.login').click()
try:
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//h2[contains(., "登錄成功")]')))
time.sleep(5)
browser.close()
return True
except TimeoutException:
return False
if __name__ == '__main__':
browser = webdriver.Chrome()
login()
4. pytesseract庫介紹
pytesseract提供了以下14個識別的api,可以滿足大多數(shù)用戶的需求,基本用到的有image_to_string,image_to_boxes,image_to_data,下面是它的14個api:
from pytesseract import ALTONotSupported # 用于表示ALTO XML格式不受支持的錯誤
from pytesseract import get_languages # 輸出識別出文字的語言
from pytesseract import get_tesseract_version # 獲取安裝的Tesseract OCR引擎的版本信息
from pytesseract import image_to_alto_xml # 將圖像識別結(jié)果輸出為ALTO XML格式的文檔,該格式通常用于文檔數(shù)字化和文本識別
from pytesseract import image_to_boxes # 將圖像中的文字識別為邊界框(box),并返回它們的坐標(biāo)信息
from pytesseract import image_to_data # 將圖像中的文字識別并返回詳細(xì)的數(shù)據(jù),包括文本、坐標(biāo)、置信度等信息
from pytesseract import image_to_osd # 識別圖像中的文字方向和腳本信息,以確定文本的定位和方向
from pytesseract import image_to_pdf_or_hocr # 將圖像中的文字識別并將結(jié)果輸出為PDF或HOCR(HTML OCR)格式的文檔
from pytesseract import image_to_string # 將圖像中的文字識別為字符串,并返回識別的文本內(nèi)容
from pytesseract import Output # 這是一個常量,用于指定返回識別結(jié)果的格式,例如文本、字典、數(shù)據(jù)等
from pytesseract import run_and_get_output # 執(zhí)行Tesseract OCR引擎并獲取其輸出,可以用于高級定制和控制
from pytesseract import TesseractError # 用于表示Tesseract OCR引擎的錯誤
from pytesseract import TesseractNotFoundError # 用于表示未找到Tesseract OCR引擎的錯誤
from pytesseract import TSVNotSupported # 用于表示TSV(制表符分隔值)格式不受支持的錯誤
__version__ = '0.3.10'
以下內(nèi)容使用的圖片均為上面使用過的?。。。。?!
5. image_to_string
從名字上來看是將圖片轉(zhuǎn)化為字符串格式,先來看看它的用法,再來說說它的其他參數(shù):
import pytesseract
from PIL import Image
image1 = Image.open("tesseract_tt1.png")
result1 = pytesseract.image_to_string(image1)
print(result1, end= '')
以下是它的其他常見的可選參數(shù):
- lang:指定要用于識別的語言,默認(rèn)為英語。
- config:允許你傳遞tesseract配置參數(shù),以微調(diào)識別過程,這可以包括有關(guān)字體、分辨率以及其他識別參數(shù)的設(shè)置,配置參數(shù)通常以鍵值對的形式傳遞。
- –dpi:設(shè)置圖像的分辨率(每英寸點數(shù))。這可以用于提高對低分辨率圖像的識別效果。
- –c tessedit_char_whitelist:允許您指定要識別的字符白名單。例如,–c tessedit_char_whitelist=0123456789可以限制識別的字符集為數(shù)字。
以下是使用cv2和pytesseract
import cv2
import pytesseract
img = cv2.imread('tesseract_tt1.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
string = pytesseract.image_to_string(img)
print(string)
print (type(string))
6. image_to_boxes
image_to_boxes
是 pytesseract 庫中的一個函數(shù),用于將圖像中的文字識別為邊界框(box),并返回它們的坐標(biāo)信息。每個邊界框包含了單個字符的位置和大小。這對于進(jìn)行文本布局分析和文本識別后的后續(xù)處理非常有用。
函數(shù)簽名:
image_to_boxes(image, lang=None, config='', output_type=pytesseract.Output.STRING)
參數(shù)說明:
-
image
:要識別的圖像,通常是一個 PIL 圖像對象。 -
lang
:可選參數(shù),指定要用于識別的語言。 -
config
:可選參數(shù),用于配置 Tesseract 的識別參數(shù)。 -
output_type
:可選參數(shù),指定返回結(jié)果的格式,默認(rèn)為字符串。
返回值:
- 如果
output_type
設(shè)置為pytesseract.Output.STRING
(默認(rèn)值),則返回一個包含邊界框信息的字符串,每行一個邊界框,每行的格式為:<字符> <x坐標(biāo)> <y坐標(biāo)> <右邊界x坐標(biāo)> <下邊界y坐標(biāo)> <頁>
模板代碼:
from pytesseract import image_to_boxes
from PIL import Image
image = Image.open('tesseract_tt2.png')
# 使用 image_to_boxes 函數(shù)進(jìn)行文字識別并獲取邊界框信息
boxes = image_to_boxes(image)
# 打印邊界框信息
for box in boxes.splitlines():
b = box.split()
char, x, y, x2, y2, page = b[0], int(b[1]), int(b[2]), int(b[3]), int(b[4]), int(b[5])
print(f"字符: {char}, 位置: 左上({x},{y}), 右下({x2},{y2}), 頁: {page}")
上述示例代碼演示了如何使用 image_to_boxes
函數(shù)進(jìn)行文字識別,并打印出識別的文本字符以及它們的位置信息。每個邊界框包括字符、左上角坐標(biāo)、右下角坐標(biāo)和所在頁。以下是輸出結(jié)果:
字符: 2, 位置: 左上(13,4), 右下(34,27), 頁: 0
字符: 0, 位置: 左上(45,12), 右下(55,27), 頁: 0
字符: 3, 位置: 左上(64,10), 右下(78,38), 頁: 0
字符: 4, 位置: 左上(90,16), 右下(102,34), 頁: 0
知道這些信息我們可以做以下事情,對于這些我就沒興趣了:
-
文本高亮或標(biāo)記:您可以使用字符的左上角和右下角坐標(biāo)信息來在原始圖像上繪制矩形框,從而高亮或標(biāo)記文本字符。這對于可視化識別結(jié)果或提供反饋非常有用。
-
文本提取:通過比較字符的所在頁信息,您可以將識別的文本分成不同的頁面或段落。這對于處理多頁文檔或大型文本文件很有幫助。
-
文本布局分析:通過分析字符的相對位置和頁碼信息,您可以推斷文本的布局結(jié)構(gòu),例如確定標(biāo)題、段落、表格或列表的位置。這有助于自動化文檔處理。
-
字符級別編輯:您可以根據(jù)字符的坐標(biāo)信息,進(jìn)行字符級別的編輯或糾正。例如,您可以檢測到字符位置偏差較大的情況,并嘗試進(jìn)行自動校正。
-
文本重排:如果需要將文本重新排列成特定格式,可以使用字符的坐標(biāo)信息將它們按照所在頁和位置進(jìn)行排序和排列。
-
自動分析文本流:通過字符的相對位置和頁碼信息,您可以自動分析文本流,例如確定文本的閱讀順序或制定自動化文檔處理規(guī)則。
7. image_to_data
以下內(nèi)容是參考這一篇博文:pytesseract image_to_data檢測并定位圖片中的文字 - LiveZingy
image_to_data
是 pytesseract 庫中的一個函數(shù),用于將圖像中的文字識別并返回詳細(xì)的數(shù)據(jù),包括文本、坐標(biāo)、置信度等信息。
函數(shù)簽名:
image_to_data(image, lang=None, config='', output_type=pytesseract.Output.DICT, nice=0)
參數(shù)說明:
-
image
:要識別的圖像,通常是一個 PIL 圖像對象。 -
lang
:可選參數(shù),指定要用于識別的語言。 -
config
:可選參數(shù),用于配置 Tesseract 的識別參數(shù)。 -
output_type
:可選參數(shù),指定返回結(jié)果的格式,默認(rèn)為字典(pytesseract.Output.DICT
)。 -
nice
:可選參數(shù),設(shè)置 Tesseract 進(jìn)程的優(yōu)先級,默認(rèn)為 0。
返回值:
- 根據(jù)
output_type
參數(shù)的不同,image_to_data
函數(shù)返回不同的對象。常見的output_type
包括字典、字符串、或數(shù)據(jù)對象。
如果 output_type
設(shè)置為 pytesseract.Output.DICT
,則返回一個包含詳細(xì)信息的字典,其中包括以下參數(shù):
-
'level'
:文本塊的級別(例如,字、詞、文本行等)。 -
'page_num'
:文本塊所在的頁碼。 -
'block_num'
:文本塊的編號。 -
'par_num'
:段落編號。 -
'line_num'
:文本行編號。 -
'word_num'
:單詞編號。 -
'left'
、'top'
、'width'
、'height'
:文本塊的位置和尺寸信息。 -
'conf'
:識別置信度。 -
'text'
:識別的文本內(nèi)容。
以下是一個示例代碼,演示如何使用 image_to_data
函數(shù)并理解其返回的對象:
import pytesseract
from PIL import Image
# 打開圖像文件
image = Image.open('tesseract_tt2.png')
# 使用 image_to_data 函數(shù)進(jìn)行文字識別并獲取詳細(xì)信息
data = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)
print(data)
# 打印詳細(xì)信息
for i, (word, left, top, width, height, conf) in enumerate(zip(data['text'], data['left'], data['top'], data['width'], data['height'], data['conf'])):
if i > 0: # 第一行通常包含表頭信息,可以跳過
print(f"文本: {word}, 位置: 左上({left},{top}), 寬度: {width}, 高度: {height}, 置信度: {conf}")
{'level': [1, 2, 3, 4, 5], 'page_num': [1, 1, 1, 1, 1], 'block_num': [0, 1, 1, 1, 1], 'par_num': [0, 0, 1, 1, 1], 'line_num': [0, 0, 0, 1, 1], 'word_num': [0, 0, 0, 0, 1], 'left': [0, 13, 13, 13, 13], 'top': [0, 0, 0, 0, 0], 'width': [112, 89, 89, 89, 89], 'height': [38, 34, 34, 34, 34], 'conf': [-1, -1, -1, -1, 60], 'text': ['', '', '', '', '2034']}
文本: , 位置: 左上(13,0), 寬度: 89, 高度: 34, 置信度: -1
文本: , 位置: 左上(13,0), 寬度: 89, 高度: 34, 置信度: -1
文本: , 位置: 左上(13,0), 寬度: 89, 高度: 34, 置信度: -1
文本: 2034, 位置: 左上(13,0), 寬度: 89, 高度: 34, 置信度: 60
根據(jù) image_to_data
的輸出結(jié)果,以下是各個參數(shù)的知識點解釋:
-
'level'
:文本塊的級別。這表示文本的層次結(jié)構(gòu),例如,1 表示文本塊級別,2 表示詞級別,以此類推。 -
'page_num'
:文本塊所在的頁碼。在單一圖像中識別文本時,通常為 1。 -
'block_num'
:文本塊的編號。文本塊是文本的更大單元,通常表示一個文本塊包含多個詞或多個文本行。 -
'par_num'
:段落編號。這表示文本塊所屬的段落編號。 -
'line_num'
:文本行編號。表示文本塊所在的文本行編號,通常在段落內(nèi)。 -
'word_num'
:單詞編號。表示文本塊內(nèi)的單詞編號,通常在文本行內(nèi)。 -
'left'
、'top'
、'width'
、'height'
:文本塊的位置和尺寸信息。'left'
和'top'
表示文本塊的左上角坐標(biāo),'width'
和'height'
表示文本塊的寬度和高度。 -
'conf'
:識別置信度。表示 Tesseract 對文本塊的識別置信度,通常是一個分?jǐn)?shù),值越高表示置信度越高。 -
'text'
:識別的文本內(nèi)容。這是文本塊中識別出的具體文本,通常包含單詞或字符的文本內(nèi)容。
在這個示例中,有多個文本塊級別的信息。最后一條記錄中的 'text'
包含了識別的文本內(nèi)容(‘2034’),而前面的記錄中 'text'
為空字符串,這可能表示Tesseract對這些文本塊沒有成功識別。并且你也可以根據(jù)置信度選取最好的結(jié)果,當(dāng)然這個結(jié)果不一定是正確的。
8. 參考博客
開源OCR識別庫-tesseract介紹-平凡的編程者-博客園(cnblogs.com)
【爬蟲】8.1. 使用OCR技術(shù)識別圖形驗證碼
借助Tesseract-OCR進(jìn)行文本檢測(1)
借助Tesseract-OCR進(jìn)行文本檢測(2)文章來源:http://www.zghlxwxcb.cn/news/detail-708182.html
pytesseract image_to_data檢測并定位圖片中的文字 - LiveZingy文章來源地址http://www.zghlxwxcb.cn/news/detail-708182.html
到了這里,關(guān)于【爬蟲】8.1. 深度使用tesseract-OCR技術(shù)識別圖形驗證碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!