zoukankan      html  css  js  c++  java
  • 一个简单的验证码识别教程

    一、起因

    前几天准备做一个自动计算gpa的网站,学校的教务登录时候需要输入验证码。本来想把验证码图片显示出来让用户手动输入,但是搞了半天没搞定。。。所以决定自己写一个识别的程序。

    直接说结果吧,最终写好的程序成功率100%(连续测试了200次)。

    二、原理

    我们先来看一看验证码是什么样的。

    如上如,就是这样的一个四位数字。

    这样的验证码已经可以算是验证码界最简单的了,没有任何扭曲、变形、干扰线,长着一张“快来识别我!”的脸。那我们就来识别一下吧。

    原理很简单,就是通过计算图片相似度来判断。

    三、准备工作

    准备工作主要做两点,截取数字和计算坐标。

    截取数字就是把0~9这十个数字从验证码图片中截取出来,方便后面对比用。需要注意的是,十个数字最好尺寸相同。我是用ps截的,因为这个网站已经做完一段时间了,我就不重新截图了。

    计算坐标主要是要确定第一个数字左上角的坐标。因为我们截的数字都是同样尺寸,所以只要确定了第一个数字左上角的坐标就可以算出后面三个数字的坐标了。坐标的计算也是用ps,放大图片之后数一数就行了。。别眼花就肯定能数对

    四、代码部分

    代码部分,我只给出最关键的相似度计算。我使用的是python。

    def hamming_dist(hash1, hash2):
        return sum(itertools.imap(operator.ne, hash1, hash2))
    
    
    def get_hash(img):
        image = img.resize((9, 13), Image.ANTIALIAS).convert("L")
        pixels = list(image.getdata())
        avg = sum(pixels) / len(pixels)
        return "".join(map(lambda p: "1" if p > avg else "0", pixels))
    

     get_hash()函数是计算图片的hash值。是把单个像素和平均像素比较,如果大就赋1,如果小就赋0。这样就把一个图片转换成一个二进制串了。

    hamming_dist()函数是计算两个二进制串的汉明距离。不明白的可以百度一下,很简单的。

    有了这两个函数,我们就可以进行识别了。首先从网页获取验证码图片,然后根据坐标以及尺寸从图片中截取出来四个未知数字,然后每个未知数字都和我们的十个标准数字进行对比,最后取相似度最大,也就是汉明距离最小的那个标准数字。这样就可以判断出来四个数字了。

    五、意外之外

    实际操作中,我发现识别成功率很低。为什么呢?我保存识别失败的图片进行查看,发现这个验证码有一个特点,就是如果里面出现1的时候,两个数字间的距离就会缩短。这也就意味着我们之前计算的坐标是错的。怎么办呢?我想了一会,发现有1的时候一般坐标会向后移动2~3格,那就好办了,我们先按照默认坐标算一次,然后给他+1再算一次,然后+2.。。最后我们取相似度最大的就行了。

    虽然不是最好的解决办法,但是很实用,毕竟是计算机,多算个几次完全没有问题。

    最后我决定把最大偏移设置为3,并且考虑到1的位置不固定,我每次计算的时候都会尝试偏移0~3,也就是一个图片计算次数为4(4个数字)*4(0~3一共4次尝试)*10(10个标准数字)。大概就是这样。

    六、结论

    这次的验证码识别可以说简单当中有一点不简单,解决问题的能力还是很重要的。

  • 相关阅读:
    JEECG SSO kisso
    高级进程间通信之基于STREAMS的管道
    网络IPC:套接字之非阻塞和异步I/O
    网络IPC:套接字之带外数据
    网络IPC:套接字之套接字选项
    网络IPC:套接字之数据传输
    网络IPC:套接字之建立连接
    网络IPC:套接字之寻址
    网络IPC:套接字之套接字描述符
    网络IPC:套接字
  • 原文地址:https://www.cnblogs.com/numbbbbb/p/3230523.html
Copyright © 2011-2022 走看看