针对验证码,做一个简单的自动网上签到程序(三)

本文介绍了一种使用Otsu阈值法改进验证码图像二值化的方法,并结合边界增强处理来提高识别准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

针对验证码,做一个简单的自动网上签到程序(二) 中已经进行了图像二值化、降噪等处理,也得到了非常好的验证码的二值化字符串。但是在进行的试验中发现出现一些错误,尤其是在二值化之后7变成1 的情况经常出现,其原因在于前面二值化的时候选取的阈值为200,而不是根据图像动态选取的阈值,阈值的选取并不能够包括全部字符信息。

为此查阅了文献,发现设定阈值有相当多的方法,我们选取较为常见的otsu法计算图像阈值。

#! /usr/bin/env python
#coding=utf-8
import Image,ImageEnhance,ImageFilter,ImageDraw
import ImageTk

def OtsuGray(image):
    # 创建Hist
    #image = Image.open("4.f")
    image.convert('L')
    hist = image.histogram()
    print  len(hist)
    print hist
    '''大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,
    前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。
    图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,
    当t使得值g=w0*(u0-u)2+w1* (u1-u)2 最大时t即为分割的最佳阈值。
     直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0-u1)2。
    部分计算过程如下'''
    # 开始计算
    # 计算总亮度
    totalH = 0
    for h in range(0,256):
        v =hist[h]
        if v == 0 : continue
        totalH += v*h
        print h,totalH,v*h
        

    width  = image.size[0]
    height = image.size[1]
    total  = width*height
    print width
    print height
    
    print "总像素:%d;总亮度:%d平均亮度:%0.2f"%(total,totalH,totalH/total)

    # t=0和t=255的时候无法构成分割,所以从t=1开始计算一致到t=255
    # 初始化v值
    v = 0

    gMax = 0.0
    tIndex = 0
    
    # temp
    n0Acc = 0.0
    n1Acc = 0.0
    n0H   = 0.0
    n1H   = 0.0
    for t in range(1,255):
        v = hist[t-1]
        if v == 0: continue
        
        n0Acc += v          #灰度小于t的像素的数目
        n1Acc = total - n0Acc #灰度大于等于t的像素的数目
        n0H += (t-1)*v          #灰度小于t的像素的总亮度
        n1H = totalH - n0H  #灰度大于等于t的像素的总亮度

        if n0Acc > 0 and n1Acc > 0:
            u0 = n0H/n0Acc # 灰阶小于t的平均灰度
            u1 = n1H/n1Acc # 灰阶大于等于t的平均灰度
            w0 = n0Acc/total # 灰阶小于t的像素比例
            w1 = 1.0-w0      # 灰阶大于等于t的像素的比例
            uD = u0-u1
            g = w0 * w1 * uD * uD
            print 'g=',g
            #if debug > 2: print "t=%3d; u0=%.2f,u1=%.2f,%.2f;n0H=%d,n1H=%d; g=%.2f"\
            #   %(t,u0,u1,u0*w0+u1*w1,n0H,n1H,g)
            print t,u0,u1,w0,w1,g
            if gMax < g:
                gMax   = g
                tIndex = t
        
#    if debug >0 : print "gMaxValue=%.2f; t = %d ; t_inv = %d"\
#               %(gMax,tIndex,255-tIndex)            
    print tIndex 
    return tIndex
#a=OtsuGray()
#print a
 

 上述计算方法也是从javaeye摘抄来的,算法很简单。

这样计算了每幅图片的阈值之后发现仍然存在着图像缺失的问题等。因此需要考虑对图像再做进一步的处理,以便二值化后基本反映数字的轮廓又能够不丢失信息。

因此我们在二值化之前对图像进行二值化和边界增强处理。后面降噪的步骤可以去掉。

相应的部分代码改为

    image = image.filter(ImageFilter.EDGE_ENHANCE())
    image = image.filter(ImageFilter.MedianFilter())
    image.show()
    #enhancer = ImageEnhance.Contrast(im)
    otsu1=otsu.OtsuGray(image)
    #twoValue(image,200)
    print otsu1
    twoValue(image,otsu1)
 

 

这样我们的字模提取已经基本上全部完成,可以开始制作字模库。验证码的识别仅仅剩下最后一步,模板与验证码的对照步骤。现在处理的效果是这样的。

原图



 

处理后



 

虽然现在的处理效果没有前面的处理办法边缘平滑,数字清晰,但是对于每个验证码,反映的基本特征均比较清晰,稳定性也大大增强。

 


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值