python实现简单验证码识别

python实现简单验证码识别,第1张

概述准备工作首先找到确定这次要识别的验证码  然后从某网站上下载大量同类型的验证码,人工标记上每个验证码的数值,由于此验证码识别容易就只标记了20个开始预处理图片图片是彩色的,我们要先让其变得简单变成灰度图像。“灰度图像上每个像素的颜色值又称为灰度,指黑白图像中 准备工作

首先找到确定这次要识别的验证码   

然后从某网站上下载大量同类型的验证码,人工标记上每个验证码的数值,由于此验证码识别容易就只标记了20个

开始预处理图片

图片是彩色的,我们要先让其变得简单变成灰度图像。

“灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度,范围一般从0到255,白色为255,黑色为0。所谓灰度值是指色彩的浓淡程度,灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰度值的象素数。”

这里就是用的是python的一个PIL的库 安装如下

pip install pillow

使用 from PIL import Image 加载我们下载好的图片 将图片灰度化

img=img.convert("L")

得到了数值范围为0-255的图片由于图片的白色和黄色难以分清 所以要卡一个阈值使得两种颜色可以分开来 多次尝试卡的是220。小于220的变成白色大于220的变成黑色,就完成了图片的二值化。

def ez_map(thresold):    res=[]    for i in range(256):        if i<thresold:            res.append(1)        else:            res.append(0)    return res def pre_hd_ez(path,out_path):    img=Image.open(path)    img=img.convert("L")    #二值    thresold=230    table=ez_map(thresold)    # img=img.convert("1")    img=img.point(table,'1')    img.save(out_path)    return img

接下来要把无关紧要的点处理了,如下图所示可以看下一个像素点周围的颜色,来对其颜色进行修正。如下图中间的黑色很可能白色更适合他。 可以通过一层来判断也可以通过多层来判断,我们管这个步骤叫做降噪。

代码存在硬编码不规范地方日后会进行更正

def get_jz_color(img,x,y,level,layer):    color_Now=img.getpixel((x,y))    zero=0    one=0    all_point=0    for i in range(0-layer,0+layer+1):        if x-i<0 or x+i>=img.size[0]:            continue        for j in range(0-layer,0+layer+1):            if y-j<0 or y+j>=img.size[1]:                continue            if i==0 and j==0:                continue            if img.getpixel((i,j))==0:                zero+=1            else:                one+=1            all_point+=1    # return color_Now    # print(color_Now)    # return 0    #  0 黑    # return color_Now    if color_Now==0:        if one/all_point>7/8:            return 1        else:            return 0    if color_Now==1:        if zero/all_point>4/8:            return 0        else:            return 1    print(color_Now)def pre_jz(img,out_path):    img_after_table=[]    for x in range(img.size[0]):        img_after_table.append([])        for y in range(img.size[1]):            num_color=get_jz_color(img,x,y,0,1)            img_after_table[x].append(num_color)    draw = ImageDraw.Draw(img)    for i in range(img.size[0]):        for j in range(img.size[1]):            draw.point((i,j),img_after_table[i][j])    img.save(out_path)    return img

此时我们得到了黑白分明的图片

分割

由于图片四个数字在图片上是等分的,我们可以直接对图片进行分割得到每个数字一个图片。

def pre_split_img(img,num,name,out_base_path):    imgs=[]    wIDe=img.size[0]    # print (wIDe)    high=img.size[1]    one=int(wIDe/4)    for i in range(num):        img1=img.crop((i*one,0,(i+1)*one,high))        imgs.append(img1)        if out_base_path:            name1=''.join(name)+str(name[i])            img1.save(out_base_path+'/'+name[i]+'/'+name1+'.png')    return imgs

将分割好的图片按照之前标记的结果分成0-9 存到0-9不同的文件夹里面

接下来我们有了各个数字图片的样本。

如何和新来的图片进行匹配?

我们要找到能代替某个数字图片的方法,比如把0这个图片分成6份每一份计算出 黑色像素点/总像素点的值然后 对多有0的图片都如此 *** 作,分别取 分割出来的6份中第一份的平均值,这样的到了能代表0这个图片的6份数值存起来后面用。

def get_block_score(img):    sum=0    black=0    for i in range(img.size[0]):        for j in range(img.size[1]):            if img.getpixel((i,j))==0:                black+=1            sum+=1    return black,sum#  计算特征值def get_features_vaule_by_img(img):    wIDe=img.size[0]    one_wIDe = int(wIDe/2)    high=img.size[1]    one_high=int(high/3)    score_lsit=[]    for i in range(3):        for j in range(2):            img_one=img.crop((j*one_wIDe,i*one_high,(j+1)*one_wIDe,(i+1)*one_high))            black,sum=get_block_score(img_one)            score_lsit.append(black*1.0/sum)    return score_lsitdef get_features_vaule(dir_path):    arry_size=6    score_lsit_res=[]    for i in range(arry_size):        score_lsit_res.append(0)    sum_file=0    for root, dirs, files in os.walk(dir_path):        for f in files:            if not '.png' in f:                continue            img=Image.open(os.path.join(root, f))            sum_file+=1            score_lsit=get_features_vaule_by_img(img)            for i in range(arry_size):                score_lsit_res[i]=score_lsit[i]+score_lsit_res[i]    # 求平均值    for i in range(arry_size):        score_lsit_res[i]=str(score_lsit_res[i]/sum_file)    value='\n'.join(score_lsit_res)    fs=open(dir_path+'feture.txt','w')    fs.write(value)    fs.close()            
识别图片

此时我们拿来一个新的验证码

让这个新的验证码经过 灰度化,二值化,分割,在每个数字分割6份计算黑点/总点的占比,将计算好的 6个值与我们之前给0-9计算的这个值分别进行比较 找出和0-9最相似的数字 这个数字就是我们想要的结果

完整代码如下 获取二维码的网站已经特殊处理

import requests,osfrom PIL import Imagefrom PIL import ImageDrawimport mathdef download_image():    url='xxx'    for i in range(0,20):        import time        time.sleep(1)        res=requests.get(url).content        f=open('D:\project/ocr/image/'+str(i)+'test.png','wb')        f.write(res)        f.close()# download_image()def makefile():    for i in range(0,10):        os.makedirs('D:\project/ocr/yangben/'+str(i))def ez_map(thresold):    res=[]    for i in range(256):        if i<thresold:            res.append(1)        else:            res.append(0)    return res def pre_hd_ez(path,out_path):    img=Image.open(path)    img=img.convert("L")    #二值    thresold=230    table=ez_map(thresold)    # img=img.convert("1")    img=img.point(table,'1')    img.save(out_path)    return imgdef get_jz_color(img,x,y,level,layer):    color_Now=img.getpixel((x,y))    zero=0    one=0    all_point=0    for i in range(0-layer,0+layer+1):        if x-i<0 or x+i>=img.size[0]:            continue        for j in range(0-layer,0+layer+1):            if y-j<0 or y+j>=img.size[1]:                continue            if i==0 and j==0:                continue            if img.getpixel((i,j))==0:                zero+=1            else:                one+=1            all_point+=1    # return color_Now    # print(color_Now)    # return 0    #  0 黑    # return color_Now    if color_Now==0:        if one/all_point>7/8:            return 1        else:            return 0    if color_Now==1:        if zero/all_point>4/8:            return 0        else:            return 1    print(color_Now)def pre_jz(img,out_path):    img_after_table=[]    for x in range(img.size[0]):        img_after_table.append([])        for y in range(img.size[1]):            num_color=get_jz_color(img,x,y,0,1)            img_after_table[x].append(num_color)    draw = ImageDraw.Draw(img)    for i in range(img.size[0]):        for j in range(img.size[1]):            draw.point((i,j),img_after_table[i][j])    img.save(out_path)    return imgdef pre_split_img(img,num,name,out_base_path):    imgs=[]    wIDe=img.size[0]    # print (wIDe)    high=img.size[1]    one=int(wIDe/4)    for i in range(num):        img1=img.crop((i*one,0,(i+1)*one,high))        imgs.append(img1)        if out_base_path:            name1=''.join(name)+str(name[i])            img1.save(out_base_path+'/'+name[i]+'/'+name1+'.png')    return imgs# img=pre_hd_ez('D:\project/ocr/image/0/6809.png','D:\project/ocr/image/0/res.png')# pre_jz(img,'D:\project/ocr/image/0/res1.png')# makefile()def get_block_score(img):    sum=0    black=0    for i in range(img.size[0]):        for j in range(img.size[1]):            if img.getpixel((i,j))==0:                black+=1            sum+=1    return black,sum#  计算特征值def get_features_vaule_by_img(img):    wIDe=img.size[0]    one_wIDe = int(wIDe/2)    high=img.size[1]    one_high=int(high/3)    score_lsit=[]    for i in range(3):        for j in range(2):            img_one=img.crop((j*one_wIDe,i*one_high,(j+1)*one_wIDe,(i+1)*one_high))            black,sum=get_block_score(img_one)            score_lsit.append(black*1.0/sum)    return score_lsitdef get_features_vaule(dir_path):    arry_size=6    score_lsit_res=[]    for i in range(arry_size):        score_lsit_res.append(0)    sum_file=0    for root, dirs, files in os.walk(dir_path):        for f in files:            if not '.png' in f:                continue            img=Image.open(os.path.join(root, f))            sum_file+=1            score_lsit=get_features_vaule_by_img(img)            for i in range(arry_size):                score_lsit_res[i]=score_lsit[i]+score_lsit_res[i]    # 求平均值    for i in range(arry_size):        score_lsit_res[i]=str(score_lsit_res[i]/sum_file)    value='\n'.join(score_lsit_res)    fs=open(dir_path+'feture.txt','w')    fs.write(value)    fs.close()            def pre_img_pipeline():    for root, dirs, files in os.walk('D:\project/ocr/image'):        # 遍历文件        for f in files:            img=pre_hd_ez(os.path.join(root, f),'D:\project/ocr/image1/'+f)            img=pre_jz(img,'D:\project/ocr/image2/'+f)            pre_split_img(img,4,f.replace('.png',''),'D:\project/ocr/yangben')    for i in range(10):        get_features_vaule('D:\project/ocr/yangben/'+str(i)+'/')# pre_img_pipeline()# 获取0-9的特征值def get_base_features_vaules(path):    res={}    for i in range(10):        fs=open(path+str(i)+'/feture.txt','r')        value=fs.read()        values=value.split('\n')        values=[float(feature_value) for feature_value in values]        res[i]=values        fs.close()    return res# 拉去待识别数据def download_pending_image():    url='xxx'    for i in range(1):        import time        time.sleep(1)        res=requests.get(url).content        path='D:\project/ocr/pending/'+str(i)+'test.png'        f=open(path,'wb')        f.write(res)        f.close()        img=Image.open(path)        return path,img# 关联性计算# 求向量点积def add_vectors(a,b):    res = 0    for i in range(len(a)):        res += float(a[i])*float(b[i])    return res# 求向量的模def module_vectors(a):    return math.sqrt(sum([float(x)**2 for x in a]))# 求向量夹角余弦值def get_cos(a,b):    add_a, add_b = module_vectors(a),module_vectors(b)    if add_a!=0 and add_b!=0:        return add_vectors(a,b)/(add_a*add_b)    return 0#  # 计算一个数字的值def sb_vaule(pending_score_List,base_features_map):    res=[]    max_score=-10.0    max_key=None    for key,values in base_features_map.items():        IDx=0        scores=0        scores=get_cos(pending_score_List,values)        if scores>max_score:            max_score=scores            max_key=key        IDx+=1    return max_keydef run():    #取基础信息     base_features_map=get_base_features_vaules('D:\project/ocr/yangben/')    path,img=download_pending_image()    img=pre_hd_ez(path,'D:\project/ocr/pending/deal/first_step.png')    img=pre_jz(img,'D:\project/ocr/pending/deal/second_step.png')    imgs=pre_split_img(img,4,'','')    res=''    for img_one in imgs:        pending_score_List=get_features_vaule_by_img(img_one)        # 计算一个数字的值        res_one=sb_vaule(pending_score_List,base_features_map)        res+=str(res_one)    print(res)    run()

总结

以上是内存溢出为你收集整理的python实现简单验证码识别全部内容,希望文章能够帮你解决python实现简单验证码识别所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/1159054.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存