一个简单的验证码识别教程
一、起因
前幾天準(zhǔn)備做一個(gè)自動(dòng)計(jì)算gpa的網(wǎng)站,學(xué)校的教務(wù)登錄時(shí)候需要輸入驗(yàn)證碼。本來(lái)想把驗(yàn)證碼圖片顯示出來(lái)讓用戶手動(dòng)輸入,但是搞了半天沒(méi)搞定。。。所以決定自己寫(xiě)一個(gè)識(shí)別的程序。
直接說(shuō)結(jié)果吧,最終寫(xiě)好的程序成功率100%(連續(xù)測(cè)試了200次)。
二、原理
我們先來(lái)看一看驗(yàn)證碼是什么樣的。
如上如,就是這樣的一個(gè)四位數(shù)字。
這樣的驗(yàn)證碼已經(jīng)可以算是驗(yàn)證碼界最簡(jiǎn)單的了,沒(méi)有任何扭曲、變形、干擾線,長(zhǎng)著一張“快來(lái)識(shí)別我!”的臉。那我們就來(lái)識(shí)別一下吧。
原理很簡(jiǎn)單,就是通過(guò)計(jì)算圖片相似度來(lái)判斷。
三、準(zhǔn)備工作
準(zhǔn)備工作主要做兩點(diǎn),截取數(shù)字和計(jì)算坐標(biāo)。
截取數(shù)字就是把0~9這十個(gè)數(shù)字從驗(yàn)證碼圖片中截取出來(lái),方便后面對(duì)比用。需要注意的是,十個(gè)數(shù)字最好尺寸相同。我是用ps截的,因?yàn)檫@個(gè)網(wǎng)站已經(jīng)做完一段時(shí)間了,我就不重新截圖了。
計(jì)算坐標(biāo)主要是要確定第一個(gè)數(shù)字左上角的坐標(biāo)。因?yàn)槲覀兘氐臄?shù)字都是同樣尺寸,所以只要確定了第一個(gè)數(shù)字左上角的坐標(biāo)就可以算出后面三個(gè)數(shù)字的坐標(biāo)了。坐標(biāo)的計(jì)算也是用ps,放大圖片之后數(shù)一數(shù)就行了。。別眼花就肯定能數(shù)對(duì)
四、代碼部分
代碼部分,我只給出最關(guān)鍵的相似度計(jì)算。我使用的是python。
def hamming_dist(hash1, hash2):return sum(itertools.imap(operator.ne, hash1, hash2))def get_hash(img):image = img.resize((9, 13), Image.ANTIALIAS).convert("L")pixels = list(image.getdata())avg = sum(pixels) / len(pixels)return "".join(map(lambda p: "1" if p > avg else "0", pixels))?get_hash()函數(shù)是計(jì)算圖片的hash值。是把單個(gè)像素和平均像素比較,如果大就賦1,如果小就賦0。這樣就把一個(gè)圖片轉(zhuǎn)換成一個(gè)二進(jìn)制串了。
hamming_dist()函數(shù)是計(jì)算兩個(gè)二進(jìn)制串的漢明距離。不明白的可以百度一下,很簡(jiǎn)單的。
有了這兩個(gè)函數(shù),我們就可以進(jìn)行識(shí)別了。首先從網(wǎng)頁(yè)獲取驗(yàn)證碼圖片,然后根據(jù)坐標(biāo)以及尺寸從圖片中截取出來(lái)四個(gè)未知數(shù)字,然后每個(gè)未知數(shù)字都和我們的十個(gè)標(biāo)準(zhǔn)數(shù)字進(jìn)行對(duì)比,最后取相似度最大,也就是漢明距離最小的那個(gè)標(biāo)準(zhǔn)數(shù)字。這樣就可以判斷出來(lái)四個(gè)數(shù)字了。
五、意外之外
實(shí)際操作中,我發(fā)現(xiàn)識(shí)別成功率很低。為什么呢?我保存識(shí)別失敗的圖片進(jìn)行查看,發(fā)現(xiàn)這個(gè)驗(yàn)證碼有一個(gè)特點(diǎn),就是如果里面出現(xiàn)1的時(shí)候,兩個(gè)數(shù)字間的距離就會(huì)縮短。這也就意味著我們之前計(jì)算的坐標(biāo)是錯(cuò)的。怎么辦呢?我想了一會(huì),發(fā)現(xiàn)有1的時(shí)候一般坐標(biāo)會(huì)向后移動(dòng)2~3格,那就好辦了,我們先按照默認(rèn)坐標(biāo)算一次,然后給他+1再算一次,然后+2.。。最后我們?nèi)∠嗨贫茸畲蟮木托辛恕?/span>
雖然不是最好的解決辦法,但是很實(shí)用,畢竟是計(jì)算機(jī),多算個(gè)幾次完全沒(méi)有問(wèn)題。
最后我決定把最大偏移設(shè)置為3,并且考慮到1的位置不固定,我每次計(jì)算的時(shí)候都會(huì)嘗試偏移0~3,也就是一個(gè)圖片計(jì)算次數(shù)為4(4個(gè)數(shù)字)*4(0~3一共4次嘗試)*10(10個(gè)標(biāo)準(zhǔn)數(shù)字)。大概就是這樣。
六、結(jié)論
這次的驗(yàn)證碼識(shí)別可以說(shuō)簡(jiǎn)單當(dāng)中有一點(diǎn)不簡(jiǎn)單,解決問(wèn)題的能力還是很重要的。
轉(zhuǎn)載于:https://www.cnblogs.com/numbbbbb/p/3230523.html
總結(jié)
以上是生活随笔為你收集整理的一个简单的验证码识别教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用msm文件创建msi
- 下一篇: first Day