驗證碼去除干擾線

在邦購登陸時,選擇了人工檢驗驗證碼,這次用機器檢測試試。
先說基本邏輯:載入圖像,轉(zhuǎn)灰度,二值化,連通域檢測,去除連通域小的,根據(jù)各連通域的范圍切割圖像。

先下載圖片。

def getcaptcha():
    for i in range(1,10):
        with open('test1-{}.png'.format(i),'wb') as f:
            url ='https://passport.banggo.com/CASServer//custom/loginCode.do'
            res = requests.get(url,stream =True)
            f.write(res.content)

得到的驗證碼長這樣:


可以看到驗證碼有干擾線,好在干擾線比較細(xì),而且驗證碼之間沒有粘連??纯磩e家怎么弄得,在python驗證碼識別
寫到了一些驗證碼識別的方法,但是幾乎都是針對像素級別,不過提供了一個思路叫連通域,就是一個筆畫里含有的像素較多,刪除那些小的聯(lián)通域就能去除干擾線了。

我看到的大多是自己寫的像素級別的函數(shù),既然這是降噪領(lǐng)域的主要思想,就會有現(xiàn)成的輪子啊,直到我發(fā)現(xiàn)了scikit-image,有自己的文檔,這篇文章進(jìn)行了少量總結(jié)api總結(jié),搬運如下

api

其中有專門針對連通域的api,
from skimage import measure
labels = measure.label(二值圖像,connectivity=None)
通過label_att = measure.regionprops(labels)得到各連通域的屬性如下。label_att是一個list,有幾個連通域就有幾項。


屬性

更好的是skimage還提供了剔除較小連通域的函數(shù),
from skimage import morphology
img1 = morphology.remove_small_objects(ar, min_size=要刪除的連通域大小閾值, connectivity=1,in_place=False)
怎么知道連通域的大小呢,就是label屬性里的area,第二個bbox用來切割圖像簡直不要太方便。
二者聯(lián)合起來就是現(xiàn)成的去掉干擾線+切割圖像的方法。

from skimage import io,filters,measure,morphology
import warnings
from matplotlib import pyplot as plt
def skim():
    img = io.imread('1.png',as_gray=True)  #變成灰度圖
    thresh = filters.threshold_otsu(img) #自動確定二值化的閾值
    bwimg =(img<=thresh) #留下小于閾值的部分,及黑的部分
    b = morphology.remove_small_objects(bwimg, 40) #去掉小于40的連通域,可以先全局看看連通域的大小和位置后決定去掉的閾值
    labels = measure.label(b)  
    label_att = measure.regionprops(labels)
    arr =[]
    for la in label_att:
        (x,y,w,h) =la.bbox
        #print((x,y,w,h))
        bei = round((h-y)/15)
        if bei >1: #寬度超過30像素的,說明有粘連,從中切開
            for i in range(bei):
                arr.append((x, y+round((h-y)/2)*i, w, y+round((h-y)/2)*(i+1)))
        elif (y>10) and (h<100) :
            arr.append((x, y, w, h))

    b =b*img
    b[np.where(b != 0)] = 1
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fig = plt.figure()
        for id, (x, y, w, h) in enumerate(arr):
            roi = b[x:w,y:h]
            thr = roi.copy()
            # io.imsave('seg1-{}.jpg',thr)
            ax = fig.add_subplot(1,4,id+1)
            ax.imshow(thr)
    plt.show()

反思:
1.這個驗證碼相對規(guī)整,可以發(fā)現(xiàn)他家的驗證碼多是驗證碼本身是有色彩的,而干擾線一直是黑色的,可以直接將小于15的像素變成255,效果也不錯,但是出現(xiàn)的問題是會把驗證碼本身連通域打斷,需要再次填充。

def ty():
    # for i in range(1,10):
    img = io.imread('{}.png'.format(4))
    img[np.where(img>235)] =255
    img[np.where(img < 15)] = 255
    imgray = color.rgb2gray(img)
    thresh = filters.threshold_otsu(imgray)
    # bwimg =(imgray <= thresh)
    bwimg = morphology.closing(imgray <= thresh, morphology.square(3))
    b = morphology.remove_small_objects(bwimg, 20)
    labels = measure.label(b)
    label_att = measure.regionprops(labels)
    arr =[]

    for la in label_att:
        (x, y, w, h) = la.bbox
        bei = round((h - y) / 15)
        if bei > 1:
            for i in range(bei):
                arr.append((x, y + round((h - y) / 2) * i, w, y + round((h - y) / 2) * (i + 1)))
        elif (y > 10) and (h < 100) :
            arr.append((x, y, w, h))
            if (len(arr)>1) and (h-y)<12 and (arr[-2][3]-arr[-2][1] <12): #干擾線去狠了導(dǎo)致斷開驗證碼斷開了要拼接一下
                arr[-1] = ((x, arr[-2][1], w, h))
                del arr[-2]

    b = b * imgray
    b[np.where(b != 0)] = 1
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fig = plt.figure()
        for id, (x, y, w, h) in enumerate(arr):
            roi = b[x:w, y:h]
            thr = roi.copy()
            # io.imsave('new{}-{}.png'.format(1,id+1), thr)
            ax = fig.add_subplot(1, len(arr), id + 1)
            ax.imshow(thr)
        plt.show()

2.驗證碼相對規(guī)整,而且放置位置也相對固定,可以直接用經(jīng)驗值切割,但是有些比較胖就比較麻煩了。

3.在使用skimage時,確是遇到二值圖直接轉(zhuǎn)rgb會變成的黑圖或者很灰的圖,像這樣。

b = b * imgray
b[np.where(b != 0)] = 1
就是把圖調(diào)亮,因為float類型,[0,1]0是黑色,1是白色,這樣存的圖就是黑白的了。
另在float轉(zhuǎn)rgb的時候會引發(fā)warnings說,向下保存會引起精度下降,用with就好了,官方文檔推薦。

4.驗證碼需觀察其特點對癥下藥比較快。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容