python 验证码识别训练_Python爬虫笔记【一】模拟用户访问之Tesseract-ocr验证码训练(5)...
驗(yàn)證碼處理之后就需要對(duì)處理的驗(yàn)證碼進(jìn)行識(shí)別訓(xùn)練,這里用Tesseract-ocr工具進(jìn)行識(shí)別,用jTessBoxeditor進(jìn)行訓(xùn)練生成模板。
一,對(duì)圖片進(jìn)行處理
利用上一篇代碼對(duì)圖片進(jìn)行降噪處理,得到較為清晰地圖片。
這里需要你在需要登入的網(wǎng)站中提取大量的驗(yàn)證碼圖片,在獲取圖片時(shí),查看網(wǎng)站的登入框是否在iframe標(biāo)簽中,已經(jīng)圖片是否有需要點(diǎn)擊輸入框才會(huì)出現(xiàn),若是如此,可以用selenium中driver來(lái)跳轉(zhuǎn)iframe標(biāo)簽,用點(diǎn)擊事件來(lái)顯示驗(yàn)證碼,然后再獲取src屬性進(jìn)行下載。
二,生成tif文件
在獲取一定數(shù)量驗(yàn)證碼后(儲(chǔ)存在images中),打開jTessBoxeditor,Tools>Merge TIFF
選擇之前保存圖片的文件,shift將文件全選,注意文件顯示的格式
之后選擇生成fift路徑以及設(shè)置名稱此處名稱要設(shè)置為這樣的格式[lang].[fontname].exp[num].tif
其中l(wèi)ang為語(yǔ)言名稱,fontname為字體名稱,num為序號(hào),可以隨便定義。
三,生成box文件
這樣遍將多個(gè)jpg文件合成一個(gè)tif文件(可能顯示的是一個(gè)驗(yàn)證碼),然后我們需要利用tif文件來(lái)生成box文件。
再打開jTessBoxEditor(如果之前有其他好點(diǎn)的模板就選擇其他的,這樣自動(dòng)識(shí)別的會(huì)多一點(diǎn),省之后的人力)。
這一步之后就會(huì)在 tif 文件目錄下生成一個(gè)box文件,在jTessBoxEditor中打開(如圖 ↓ )
四,調(diào)整位置
如果模板較好的話會(huì)出現(xiàn)這樣的文件(也許位置可能沒有識(shí)別的這么準(zhǔn),那個(gè)就需要人工調(diào)節(jié),記得保存,下面可以翻頁(yè))
也有可能是這樣
如果是這樣的話,你需要用文本方式打開box文件(六列分別對(duì)應(yīng),值,位置*4,頁(yè)碼值-1),我們需要?jiǎng)?chuàng)建的1~7頁(yè)的那四行,隨便找四行復(fù)制一下,然后改一下頁(yè)碼,沒有框的幾個(gè)驗(yàn)證碼有了,然后再調(diào)整位置。(注意最后的一列為? 頁(yè)碼數(shù)-1 )
在調(diào)整完所有驗(yàn)證碼后,在tif文件目錄下建立一個(gè)新建名為下xxx.font_properties的文本文件(xxx與自定義語(yǔ)言名稱相同)內(nèi)容為 font 0 0 0 0 0
之后再去txt后綴
五,訓(xùn)練
這樣 tif,box,font_properties文件都有了,就可以生成模板了
訓(xùn)練完之后就在tif文件下生成了tessdata文件夾,里面便是訓(xùn)練完成模板mob.traineddata,將模板移動(dòng)到Tesseract—ocr>tessdata目錄下,這樣便可以用Tesseract-ocr識(shí)別驗(yàn)證碼
from PIL importImagefrom pytesseract import *
from fnmatch importfnmatchfrom queue importQueueimportmatplotlib.pyplot as pltimportcv2importtimeimportosdefclear_border(img,img_name):'''去除邊框'''h, w= img.shape[:2]for y inrange(0, w):for x inrange(0, h):#if y ==0 or y == w -1 or y == w - 2:
if y < 4 or y > w -4:
img[x, y]= 255
#if x == 0 or x == h - 1 or x == h - 2:
if x < 4 or x > h - 4:
img[x, y]= 255
returnimgdefinterference_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=0if 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
returnimgdef interference_point(img,img_name, x = 0, y =0):"""點(diǎn)降噪
9鄰域框,以當(dāng)前點(diǎn)為中心的田字框,黑點(diǎn)個(gè)數(shù)
:param x:
:param y:
:return:"""
#todo 判斷圖片的長(zhǎng)寬度下限
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個(gè)點(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]=0elif 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]=0else: #最上非頂點(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]=0elif y == width - 1: #最下面一行
if x == 0: #左下頂點(diǎn)
#中心點(diǎn)旁邊3個(gè)點(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]=0elif 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]=0else: #最下非頂點(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]=0else: #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]=0elif 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]=0else: #具備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]=0returnimgdef_get_dynamic_binary_image(filedir,img_name):'''自適應(yīng)閥值二值化'''filename= './easy_code/' + img_name.split('.')[0] + '-binary.jpg'img_name= filedir + '/' +img_name
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)returnth1defrecognize():
i=0
filedir= './images' #驗(yàn)證碼路jing
for file inos.listdir(filedir):if fnmatch(file, '*.jpg'):
img_name=file#自適應(yīng)閾值二值化
im =_get_dynamic_binary_image(filedir,img_name)#去除邊框
im =clear_border(im,img_name)#對(duì)圖片進(jìn)行干擾線降噪
im =interference_line(im,img_name)#對(duì)圖片進(jìn)行點(diǎn)降噪
im =interference_point(im,img_name)#easy_code為圖片清理后保存路徑
filename = './easy_code/' + img_name.split('.')[0] + '-interferencePoint.jpg'cv2.imwrite(filename,im)#'mob'為模板
str_img = pytesseract.image_to_string(im, lang='mob')
code= str_img.encode("GBK","ignore").decode('GBK')if code.replace(' ','') == img_name.split('.')[0]:
i= i + 1
print(code)print('---' +str(i))
recognize()
View Code
fromPIL import Imagefrom pytesseract import *
fromfnmatch import fnmatchfromqueue import Queue
import matplotlib.pyplotasplt
import cv2
import time
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 < 4 or y > w -4:
img[x, y]= 255#if x == 0 or x == h - 1 or x == h - 2:if x < 4 or x > h - 4:
img[x, y]= 255
returnimg
def interference_line(img, img_name):'''干擾線降噪'''h, w= img.shape[:2]
# !!!opencv矩陣點(diǎn)是反的
# img[1,2] 1:圖片的高度,2:圖片的寬度f(wàn)or 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
returnimg
def interference_point(img,img_name, x= 0, y = 0):"""點(diǎn)降噪
9鄰域框,以當(dāng)前點(diǎn)為中心的田字框,黑點(diǎn)個(gè)數(shù)
:param x:
:param y:
:return:"""# todo 判斷圖片的長(zhǎng)寬度下限
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個(gè)點(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]= 0elif 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]= 0elif y== width - 1: # 最下面一行if x == 0: # 左下頂點(diǎn)
# 中心點(diǎn)旁邊3個(gè)點(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]= 0elif 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]= 0elif 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
returnimg
def _get_dynamic_binary_image(filedir,img_name):'''自適應(yīng)閥值二值化''' filename = './easy_code/' + img_name.split('.')[0] + '-binary.jpg'img_name= filedir + '/' +img_name
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)returnth1
def recognize():
i= 0filedir= './images'#驗(yàn)證碼路jingfor file inos.listdir(filedir):if fnmatch(file, '*.jpg'):
img_name=file
# 自適應(yīng)閾值二值化
im=_get_dynamic_binary_image(filedir,img_name)
# 去除邊框
im=clear_border(im,img_name)
# 對(duì)圖片進(jìn)行干擾線降噪
im=interference_line(im,img_name)
# 對(duì)圖片進(jìn)行點(diǎn)降噪
im=interference_point(im,img_name)
# easy_code為圖片清理后保存路徑
filename= './easy_code/' + img_name.split('.')[0] + '-interferencePoint.jpg'cv2.imwrite(filename,im)
#'mob'為模板
str_img= pytesseract.image_to_string(im, lang='mob')
code= str_img.encode("GBK","ignore").decode('GBK')if code.replace('
查閱過(guò)的博客:
總結(jié)
以上是生活随笔為你收集整理的python 验证码识别训练_Python爬虫笔记【一】模拟用户访问之Tesseract-ocr验证码训练(5)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《燕云十六声》祁氏家驯任务完成攻略
- 下一篇: 分析师:微软 GPU 算力租赁业务毛利率