python 验证码识别训练_Python爬虫笔记【一】模拟用户访问之Tesseract-ocr验证码训练(5)...

验证码处理之后就需要对处理的验证码进行识别训练,这里用Tesseract-ocr工具进行识别,用jTessBoxeditor进行训练生成模板。

一,对图片进行处理

利用上一篇代码对图片进行降噪处理,得到较为清晰地图片。

这里需要你在需要登入的网站中提取大量的验证码图片,在获取图片时,查看网站的登入框是否在iframe标签中,已经图片是否有需要点击输入框才会出现,若是如此,可以用selenium中driver来跳转iframe标签,用点击事件来显示验证码,然后再获取src属性进行下载。

二,生成tif文件

在获取一定数量验证码后(储存在images中),打开jTessBoxeditor,Tools>Merge TIFF

选择之前保存图片的文件,shift将文件全选,注意文件显示的格式

之后选择生成fift路径以及设置名称此处名称要设置为这样的格式[lang].[fontname].exp[num].tif

其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。

三,生成box文件

这样遍将多个jpg文件合成一个tif文件(可能显示的是一个验证码),然后我们需要利用tif文件来生成box文件。

再打开jTessBoxEditor(如果之前有其他好点的模板就选择其他的,这样自动识别的会多一点,省之后的人力)。

这一步之后就会在 tif 文件目录下生成一个box文件,在jTessBoxEditor中打开(如图 ↓ )

四,调整位置

如果模板较好的话会出现这样的文件(也许位置可能没有识别的这么准,那个就需要人工调节,记得保存,下面可以翻页)

也有可能是这样

如果是这样的话,你需要用文本方式打开box文件(六列分别对应,值,位置*4,页码值-1),我们需要创建的1~7页的那四行,随便找四行复制一下,然后改一下页码,没有框的几个验证码有了,然后再调整位置。(注意最后的一列为  页码数-1 )

在调整完所有验证码后,在tif文件目录下建立一个新建名为下xxx.font_properties的文本文件(xxx与自定义语言名称相同)内容为 font 0 0 0 0 0

之后再去txt后缀

五,训练

这样 tif,box,font_properties文件都有了,就可以生成模板了

训练完之后就在tif文件下生成了tessdata文件夹,里面便是训练完成模板mob.traineddata,将模板移动到Tesseract—ocr>tessdata目录下,这样便可以用Tesseract-ocr识别验证码

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矩阵点是反的

#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):"""点降噪

9邻域框,以当前点为中心的田字框,黑点个数

:param x:

:param y:

:return:"""

#todo 判断图片的长宽度下限

cur_pixel = img[x,y]#当前像素点的值

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: #左上顶点,4邻域

#中心点旁边3个点

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: #右上顶点

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: #最上非顶点,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: #左下顶点

#中心点旁边3个点

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: #右下顶点

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: #最下非顶点,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: #左边非顶点

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: #右边非顶点

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领域条件的

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):'''自适应阀值二值化'''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' #验证码路jing

for file inos.listdir(filedir):if fnmatch(file, '*.jpg'):

img_name=file#自适应阈值二值化

im =_get_dynamic_binary_image(filedir,img_name)#去除边框

im =clear_border(im,img_name)#对图片进行干扰线降噪

im =interference_line(im,img_name)#对图片进行点降噪

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矩阵点是反的

# 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

returnimg

def interference_point(img,img_name, x= 0, y = 0):"""点降噪

9邻域框,以当前点为中心的田字框,黑点个数

:param x:

:param y:

:return:"""# todo 判断图片的长宽度下限

cur_pixel=img[x,y]# 当前像素点的值

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: # 左上顶点,4邻域

# 中心点旁边3个点

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: # 右上顶点

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: # 最上非顶点,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: # 左下顶点

# 中心点旁边3个点

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: # 右下顶点

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: # 最下非顶点,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: # 左边非顶点

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: # 右边非顶点

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领域条件的

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):'''自适应阀值二值化''' 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'#验证码路jingfor file inos.listdir(filedir):if fnmatch(file, '*.jpg'):

img_name=file

# 自适应阈值二值化

im=_get_dynamic_binary_image(filedir,img_name)

# 去除边框

im=clear_border(im,img_name)

# 对图片进行干扰线降噪

im=interference_line(im,img_name)

# 对图片进行点降噪

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('

查阅过的博客:

你可能感兴趣的:(python,验证码识别训练)