驗證碼識別之二值化

前言

二值化顧名思義就是將數變成兩種值,通常非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

相關文章
相關標籤/搜索