Python+Selenium+Pytesseract實(shí)現(xiàn)圖片驗(yàn)證碼識別
一、selenium截取驗(yàn)證碼
import json
from io import BytesIO
import time
from test.testBefore.testDriver import driver
from test.util.test_pytesseract import recognize
from PIL import Image
import allure
import unittest
'''
/處理驗(yàn)證碼
'''
# 要截圖的元素
element = driver.find_element_by_xpath('//*[@id="imgVerifyCode"]')
# 坐標(biāo)
x, y = element.location.values()
# 寬高
h, w = element.size.values()
# 把截圖以二進(jìn)制形式的數(shù)據(jù)返回
image_data = driver.get_screenshot_as_png()
# 以新圖片打開返回的數(shù)據(jù)
screenshot = Image.open(BytesIO(image_data))
# 對截圖進(jìn)行裁剪
result = screenshot.crop((x, y, x + w, y + h))
# 顯示圖片
# result.show()
# 保存驗(yàn)證碼圖片
result.save('VerifyCode.png')
# 調(diào)用recognize方法識別驗(yàn)證碼
code = recognize('VerifyCode.png')
# 輸入驗(yàn)證碼
driver.find_element_by_xpath('//*[@id="txtcode"]').send_keys(code)
'''
處理驗(yàn)證碼/
'''注意:driver是引用我自己寫的文件,可以自己隨便寫一個。識別圖片的代碼單獨(dú)放在util文件夾下面的,參考標(biāo)題三的代碼,需要時引用。以上代碼定位元素都需要根據(jù)自己的項(xiàng)目定位元素修改。
二、安裝識別環(huán)境pytesseract+Tesseract-OCR
如果沒有輸出,又不確定你的pytesseract環(huán)境是否安裝好,可以用一張沒有干擾的圖片識別看看能不能有輸出結(jié)果,以下樣例在我的環(huán)境中可以直接輸出識別結(jié)果8fnp
驗(yàn)證識別環(huán)境是否正常
直接使用pytesseract識別圖片
001.png

text = pytesseract.image_to_string('./001.png')
print(text)
三、處理驗(yàn)證碼圖片
直接截圖的驗(yàn)證碼圖片存在噪點(diǎn)或者干擾線等,直接使用pytesseract識別可能會沒有輸出結(jié)果,如果環(huán)境正常,但沒有輸出結(jié)果,那多半是因?yàn)閳D片沒有處理好,識別不出來,可以多嘗試一些處理圖片的方式,以下代碼處理我截圖這種類似的圖片效果比較好。
圖片處理識別
對圖片處理的過程:
圖片處理過程中可以多用im.show()看看每一步處理后的圖片是不是符合預(yù)期,如果效果不好調(diào)一下參數(shù)。另外在學(xué)習(xí)過程中發(fā)現(xiàn)有童鞋說識別不出來把圖片使用cv2.resize()這個方法放大就能識別,可以參考Python中圖像的縮放 resize()函數(shù)的應(yīng)用
實(shí)際截取的圖片

處理后的圖片

test_pytesseract.py
import pytesseract
from fnmatch import fnmatch
import cv2
import os
def clear_border(img, img_name):
'''
去除邊框
'''
h, w = img.shape[:2]
for y in range(0, w):
for x in range(0, h):
# if y ==0 or y == w -1 or y == w - 2:
if y < 2 or y > w - 2:
img[x, y] = 255
# if x == 0 or x == h - 1 or x == h - 2:
if x < 1 or x > h - 1:
img[x, y] = 255
return img
def interference_line(img, img_name):
'''
干擾線降噪
'''
h, w = img.shape[:2]
# ?。?!opencv矩陣點(diǎn)是反的
# img[1,2] 1:圖片的高度,2:圖片的寬度
for r in range(0, 2):
for y in range(1, w - 1):
for x in range(1, h - 1):
count = 0
if img[x, y - 1] > 245:
count = count + 1
if img[x, y + 1] > 245:
count = count + 1
if img[x - 1, y] > 245:
count = count + 1
if img[x + 1, y] > 245:
count = count + 1
if count > 2:
img[x, y] = 255
return img
def interference_point(img, img_name, x=0, y=0):
"""點(diǎn)降噪
9鄰域框,以當(dāng)前點(diǎn)為中心的田字框,黑點(diǎn)個數(shù)
:param x:
:param y:
:return:
"""
# todo 判斷圖片的長寬度下限
cur_pixel = img[x, y] # 當(dāng)前像素點(diǎn)的值
height, width = img.shape[:2]
for y in range(0, width - 1):
for x in range(0, height - 1):
if y == 0: # 第一行
if x == 0: # 左上頂點(diǎn),4鄰域
# 中心點(diǎn)旁邊3個點(diǎn)
sum = int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 2 * 245:
img[x, y] = 0
elif x == height - 1: # 右上頂點(diǎn)
sum = int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1])
if sum <= 2 * 245:
img[x, y] = 0
else: # 最上非頂點(diǎn),6鄰域
sum = int(img[x - 1, y]) \
+ int(img[x - 1, y + 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
elif y == width - 1: # 最下面一行
if x == 0: # 左下頂點(diǎn)
# 中心點(diǎn)旁邊3個點(diǎn)
sum = int(cur_pixel) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x, y - 1])
if sum <= 2 * 245:
img[x, y] = 0
elif x == height - 1: # 右下頂點(diǎn)
sum = int(cur_pixel) \
+ int(img[x, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y - 1])
if sum <= 2 * 245:
img[x, y] = 0
else: # 最下非頂點(diǎn),6鄰域
sum = int(cur_pixel) \
+ int(img[x - 1, y]) \
+ int(img[x + 1, y]) \
+ int(img[x, y - 1]) \
+ int(img[x - 1, y - 1]) \
+ int(img[x + 1, y - 1])
if sum <= 3 * 245:
img[x, y] = 0
else: # y不在邊界
if x == 0: # 左邊非頂點(diǎn)
sum = int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
elif x == height - 1: # 右邊非頂點(diǎn)
sum = int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x - 1, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
else: # 具備9領(lǐng)域條件的
sum = int(img[x - 1, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1]) \
+ int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 4 * 245:
img[x, y] = 0
return img
def _get_dynamic_binary_image(filedir, img_name):
'''
自適應(yīng)閥值二值化
'''
filename = './' + img_name.split('.')[0] + '-binary.png'
img_name = filedir + '/' + filename
im = cv2.imread(img_name)
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)
return th1
def recognize(image):
filedir = './' # 驗(yàn)證碼路徑
for file in os.listdir(filedir):
if fnmatch(file, image):
img_name = file
# 自適應(yīng)閾值二值化
im = _get_dynamic_binary_image(filedir, img_name)
# # 去除邊框
im = clear_border(im, img_name)
# 對圖片進(jìn)行干擾線降噪
im = interference_line(im, img_name)
# 對圖片進(jìn)行點(diǎn)降噪
im = interference_point(im, img_name)
filename = './' + img_name.split('.')[0] + '-interferencePoint.png' # easy_code為保存路徑
cv2.imwrite(filename, im) # 保存圖片
text = pytesseract.image_to_string(im, lang="eng",
config='--psm 6 digits') # config=digits只識別數(shù)字
return text
'''
--psm 參數(shù)含義
0:定向腳本監(jiān)測(OSD)
1: 使用OSD自動分頁
2 :自動分頁,但是不使用OSD或OCR(Optical Character Recognition,光學(xué)字符識別)
3 :全自動分頁,但是沒有使用OSD(默認(rèn))
4 :假設(shè)可變大小的一個文本列。
5 :假設(shè)垂直對齊文本的單個統(tǒng)一塊。
6 :假設(shè)一個統(tǒng)一的文本塊。
7 :將圖像視為單個文本行。
8 :將圖像視為單個詞。
9 :將圖像視為圓中的單個詞。
10 :將圖像視為單個字符。
'''到此這篇關(guān)于Python+Selenium+Pytesseract實(shí)現(xiàn)圖片驗(yàn)證碼識別的文章就介紹到這了,更多相關(guān)Python圖片驗(yàn)證碼識別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- python中的斷言(assert語句)
- python assert斷言的實(shí)例用法
- Python中優(yōu)雅使用assert斷言的方法實(shí)例
- Python實(shí)現(xiàn)OCR識別之pytesseract案例詳解
- python pytesseract庫的實(shí)例用法
- 解決Python3.8運(yùn)行tornado項(xiàng)目報NotImplementedError錯誤
- Python Tornado核心及相關(guān)原理詳解
- Python Tornado之跨域請求與Options請求方式
- Python Tornado 實(shí)現(xiàn)SSE服務(wù)端主動推送方案
相關(guān)文章
python openpyxl提取Excel圖片實(shí)現(xiàn)原理技巧
在這篇文章中,將介紹如何使用openpyxl來提取Excel中的圖片,以及它的原理和技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
python各種語言間時間的轉(zhuǎn)化實(shí)現(xiàn)代碼
這篇文章主要介紹了python各種語言間時間的轉(zhuǎn)化,需要的朋友可以參考下2016-03-03
利用標(biāo)準(zhǔn)庫fractions模塊讓Python支持分?jǐn)?shù)類型的方法詳解
最近在工作中遇到了分?jǐn)?shù)處理,查找相關(guān)的資料發(fā)現(xiàn)可以利用Fraction類來實(shí)現(xiàn),所以下面這篇文章主要給大家介紹了關(guān)于利用標(biāo)準(zhǔn)庫fractions模塊讓Python支持分?jǐn)?shù)類型的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-08-08
釘釘群自定義機(jī)器人消息Python封裝的實(shí)例
今天小編就為大家分享一篇釘釘群自定義機(jī)器人消息Python封裝的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-02-02
Pytorch中關(guān)于F.normalize計(jì)算理解
這篇文章主要介紹了Pytorch中關(guān)于F.normalize計(jì)算理解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
python 根據(jù)excel中顏色區(qū)分讀取的操作
這篇文章主要介紹了python 根據(jù)excel中顏色區(qū)分讀取的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03

