二值化顧名思義就是將數變成兩種值,通常非0即1。而在驗證碼處理中,若是直接使用灰度圖,那麼每一個像素的值會在0-255,這樣確定會增長計算時間,而二值化後每一個像素的值只是0和1。python
在前面的簡單驗證碼識別中,個人二值化代碼是這樣寫的:a = (a > 180) * 255
,至於這裏爲何不乘1而乘255,由於我要顯示圖片看看效果。若是隻是用於算法識別的話,乘1會更好。可是,這裏的180也就是二值化的閾值是如何獲得的,開始是經過一個一個試而後看效果哪一個好就選哪一個,由於咱們通常只識別某個網站的驗證碼,這樣只要測試幾回獲得結果後即可用於這個網站其餘的驗證碼。算法
這樣測試有點浪費時間,雖然是一次性的,可是你手動測出的驗證碼不必定是最合適的。因此咱們須要算法去自動計算出驗證碼的閾值,算法有不少,這裏咱們使用迭代法和最大類間方差法,經過這兩個算法計算出來的閾值基本差很少。微信
求出圖像中的最小灰度值和最大灰度值,分別記爲Gmin和Gmax,則閾值初值T0=(Gmin+Gmax)/2;app
根據閾值T0將圖像分割成前景和背景兩部分,求出兩部分的平均灰度值m1和m2,平均灰度值=總灰度值/像素個數機器學習
求出新閾值T1=(m1+m2)/2學習
若是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
原理參考:https://blog.csdn.net/weixin_40647819/article/details/90179953.net
這裏我直接複製一遍:3d
存在閾值T將圖像全部像素分爲前景和背景,則這兩類像素各自的均值就爲m一、m2,圖像全局均值爲mG。同時像素被分爲前景和背景的機率分別爲p一、p2。所以就有:
p1*m1+p2*m2=mG
和 p1+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的內容。