zoukankan      html  css  js  c++  java
  • 使用python识别验证码

      公司的登录注册等操作有验证码,测试环境可以让开发屏蔽掉验证码,但是如果到线上的话就要想办法识别验证码或必过验证码了。

      识别验证码主要分为三部分,一、对验证码进行二值化。二、将二值化后的图片分割。三、进行识别。理论上在识别之前有一个标准化的操作,是将图片进行旋转等操作,尽量将字符弄成一样的格式,方便识别,避免随进图片的差异。

      用这个验证码作为例子:。下面是代码:

      一、打开图片,将图片二值化。

      图片是由RGB三个通道组成的,图片的验证码和他的干扰,比如点或横线等,RGB的阙值有很大的区别,我们可以使用PS工具查看,选取一个大概的临界点,在代码中进行判断,判断属于验证码部分的阙值,赋值为(255,255,255,255)黑色。如果不是在这个阙值范围内的赋值为(0,0,0,255)白色。从而将噪点去掉。

    #coding=utf-8
    from PIL import Image
    from operator import itemgetter
    import os
    img=Image.open('code.jpg')
    print img.format,img.size,img.mode
    img=img.convert("RGBA")
    pixdata=img.load()
    for y in xrange(img.size[1]):
    for x in xrange(img.size[0]):
    if pixdata[x,y][0]<140 or pixdata[x,y][1]<140 or pixdata[x,y][2]<140:
    pixdata[x,y]=(0,0,0,255)
    else:
    pixdata[x,y]=(255,255,255,255)

    说明:对像素pixdata[x,y]的阙值判断,前文中说明过[0],[1],[2]分别代表了RGB,140是用PS看出来的,验证码位置的像素,RGB都比较低,而噪点的RGB值比较高。可以适当的调一下。

    下图是取验证码一点的像素点:

    下面是噪点的RGB:

     

    二、将二值化后的图片进行分割,分割成独立字符

     

    #存为字库
    j = 1
    for i in range(4):
    x = 0 + i*13
    y = 6
    img.crop((x, y, x+13, y+18)).save("%d.jpg" % j)
    j += 1

    分割后的结果如下图:

    说明:验证码图片的大小是固定的,一个验证码4个字符,将他分成等大小的四个图片,13为一个字符所占的宽度,18为一个字符所占的高度,但是这样截出来的图片不是很精确。

    三、识别验证码,这步也是最关键的。

     

    #识别
    fontMods = []#fontMods,图片库,文件名,带后缀
    mode=[]#mode,图片库,去掉后缀的文件名
    font=[]#font,分割后的四个图片
    s=os.sep
    root="C:Usersmin.sunDesktop"+s+"num"+s#文件路径,s区分在linux或windows系统下的分割符"/"或""
    sname=os.listdir("C:Usersmin.sunDesktop/num")#获取文件夹下文件或文件夹的名称,带后缀
    #fname,存储文件名区分名和后缀的元组,例(5,jpg)。mode存储文件名,不带后缀
    #分割文件名和后缀名

    #遍历文件,将库中的文件名存入

     

    for rt, dirs, files in os.walk(root):
    for f in files:
    fname = os.path.splitext(f)
    mode.append(fname[0])

    for i in range(0,4):
    fontMods.append(Image.open(root+s+sname[i]))
    result=[]
    for i in range(1,5):
    font.append(Image.open("%d.jpg" % i))
    for i in font:
    points ={}
    d=0
    for mod in fontMods:
    diffs = 0
    for yi in range(18):
    for xi in range(13):
    if i.getpixel((xi, yi))!=mod.getpixel((xi, yi)):
    diffs=diffs+1
    #print "diffs:" + str(diffs)
    #points[diffs]=mode
    points[diffs]=mode[d]
    d=d+1
    points=sorted(points.iteritems(), cmp=lambda x,y:cmp(x[0],y[0]), reverse = False )
    result.append(points[0][1])

    a="".join(result)
    print "The result is:",a
    print "over"

       说明:做识别首先要有一个库,来比对,这里做的方法是取像素点,判断和库中的图片是否一样,取不同个数最少的一个图片作为结果。

    以上步骤就是验证码识别的一个简单过程,不过识别率很低,只是作为一个学习,还是可以了考虑用其他方法来识别验证码。


  • 相关阅读:
    python连接字符串的几种方法--转子(香草拿铁的园子)
    winform属性
    C# Timer
    SQL基础
    SQL 基础
    File类 ReadAllBytes() ReadAllLines() ReadAllText()
    学习C#20天有感
    装箱和拆箱
    机器学习基础:朴素贝叶斯小结
    分类问题样本不均衡问题
  • 原文地址:https://www.cnblogs.com/meitian/p/3718545.html
Copyright © 2011-2022 走看看