验证码识别之二值化

前言

二值化顾名思义就是将数变成两种值,通常非0即1。而在验证码处理中,若是直接使用灰度图,那么每一个像素的值会在0-255,这样确定会增长计算时间,而二值化后每一个像素的值只是0和1。python

在前面的简单验证码识别中,个人二值化代码是这样写的:a = (a > 180) * 255,至于这里为何不乘1而乘255,由于我要显示图片看看效果。若是只是用于算法识别的话,乘1会更好。可是,这里的180也就是二值化的阈值是如何获得的,开始是经过一个一个试而后看效果哪一个好就选哪一个,由于咱们通常只识别某个网站的验证码,这样只要测试几回获得结果后即可用于这个网站其余的验证码。算法

这样测试有点浪费时间,虽然是一次性的,可是你手动测出的验证码不必定是最合适的。因此咱们须要算法去自动计算出验证码的阈值,算法有不少,这里咱们使用迭代法和最大类间方差法,经过这两个算法计算出来的阈值基本差很少。微信

迭代法

  1. 求出图像中的最小灰度值和最大灰度值,分别记为Gmin和Gmax,则阈值初值T0=(Gmin+Gmax)/2;app

  2. 根据阈值T0将图像分割成前景和背景两部分,求出两部分的平均灰度值m1和m2,平均灰度值=总灰度值/像素个数机器学习

  3. 求出新阈值T1=(m1+m2)/2学习

  4. 若是T0=T1,则结束,不然将T1的值赋予T0,从第2步从新计算。测试

算法实现以下:网站

import numpy as np
from PIL import Image

def iteration(img_path):
    img = Image.open(img_path).convert('L')
    a = np.array(img)
    a = a.ravel()
    k = int((int(a.max()) + int(a.min()))/2) # 即初始阈值T0
    m = -1
    while k != m:
        # C1和C2为前景和背景的像素
        C1 = a[a >= k]   
        C2 = a[a < k]
        k = m
        m1 = np.sum(C1)/len(C1) if len(C1) else 0
        m2 = np.sum(C2)/len(C2) if len(C2) else 0
        m = int((m1 + m2)/2)
    return k

最大类间方差法(OTSU)

原理参考:https://blog.csdn.net/weixin_40647819/article/details/90179953.net

这里我直接复制一遍:3d

存在阈值T将图像全部像素分为前景和背景,则这两类像素各自的均值就为m一、m2,图像全局均值为mG。同时像素被分为前景和背景的几率分别为p一、p2。所以就有:
p1*m1+p2*m2=mGp1+p2=1 则类间方差表达式为:

在这里插入图片描述
使得上式值最大时的阈值T就是最佳的阈值。

算法实现以下:

import numpy as np
from PIL import Image

def otsu(img_path):
    img = Image.open(img_path).convert('L')
    a = np.array(img)
    a = a.ravel()
    L = []
    for k in range(0, 256):
        C1 = a[a >= k]
        C2 = a[a < k]
        if not(len(C1) and  len(C2)):
            L.append(0)
            continue
        m1 = np.sum(C1)/len(C1)
        m2 = np.sum(C2)/len(C2)
        p1 = len(C1)/len(a)
        p2 = len(C2)/len(a)
        x = p1 * p2 * (m1 - m2) * (m1 - m2)
        L.append(x)
    return L.index(max(L))

看一下效果:
原图
原图
迭代法
迭代法
最大类间方差法
最大类间方差法

最后,我正在学习一些机器学习的算法,对于一些我须要记录的内容我都会分享到博客和微信公众号(python成长路),欢迎关注。平时的话通常分享一些爬虫或者Python的内容。
lUE1wd.jpg

相关文章
相关标签/搜索