首頁 >後端開發 >Python教學 >python驗證碼識別教程之灰階處理、二值化、降噪與tesserocr識別

python驗證碼識別教程之灰階處理、二值化、降噪與tesserocr識別

不言
不言原創
2018-06-04 11:30:016025瀏覽

這篇文章主要介紹了關於python驗證碼識別教程之灰度處理、二值化、降噪與tesserocr識別,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

前言

寫爬蟲有一個繞不過去的問題就是驗證碼,現在驗證碼分類大概有4種:

  1. 圖片類別

  2. #滑動類別

  3. #點擊類別

  4. 語音類

今天先來看看影像類,這類驗證碼大多是數字、字母的組合,國內也有使用漢字的。在這個基礎上增加雜訊、幹擾線、變形、重疊、不同字體顏色等方法來增加辨識難度。

對應的,驗證碼辨識大體可以分為下面幾個步驟:

  1. 灰階處理

  2. 增加對比(可選)

  3. 二值化

  4. #降噪

  5. 傾斜校正分割字元

  6. 建立訓練庫

#識別


由於是實驗性質的,文中用到的驗證碼都是為程式產生而不是大量下載真實的網站驗證碼,這樣做的好處就是可以有大量的知道明確結果的資料集。

當需要真實環境下需要取得資料時,可以使用結合各個大尺碼平台來建立資料集進行訓練。

產生驗證碼這裡我使用Claptcha (本地下載)這個庫,當然Captcha(本地下載)這個庫也是不錯的選擇。

為了產生最簡單的純數字、無幹擾的驗證碼,首先需要將claptcha.py的285行_drawLine做一些修改,我直接讓這個函數回傳None,然後開始產生驗證碼:

from claptcha import Claptcha

c = Claptcha("8069","/usr/share/fonts/truetype/freefont/FreeMono.ttf")
t,_ = c.write('1.png')

這裡要注意ubuntu的字型路徑,也可以在網路上下載其他字型使用。產生驗證碼如下:


可以看出,驗證碼有形變。對於這類最簡單的驗證碼,可以直接使用Google開源的tesserocr來識別。

先安裝:

apt-get install tesseract-ocr libtesseract-dev libleptonica-dev
pip install tesserocr
##然後開始識別:

from PIL import Image
import tesserocr

p1 = Image.open('1.png')
tesserocr.image_to_text(p1)

'8069\n\n'


#可以看出,對於這種簡單的驗證碼,基本什麼都不做識別率就已經很高了。有興趣的小夥伴可以用更多的數據來測試,這裡我就不展開了。

接下來,在驗證碼背景中加入雜訊來看看:

c = Claptcha("8069","/usr/share/fonts/truetype/freefont/FreeMono.ttf",noise=0.4)
t,_ = c.write('2.png')


產生驗證碼如下:


識別:

p2 = Image.open('2.png')
tesserocr.image_to_text(p2)
'8069\n\n'

效果還可以。接下來產生一個字母數字組合的:

c2 = Claptcha("A4oO0zZ2","/usr/share/fonts/truetype/freefont/FreeMono.ttf")
t,_ = c2.write('3.png')


產生驗證碼如下:

第3個為小寫字母o,第4個為大寫字母O,第5個為數字0,第6個為小寫字母z,第7個為大寫字母Z,最後一個是數字2。人眼已經跪了有木有!但現在一般驗證碼對大小寫是不做嚴格區分的,看自動識別什麼樣吧:

p3 = Image.open('3.png')
tesserocr.image_to_text(p3)
'AMOOZW\n\n'

人眼都跪的計算機當然也廢了。但是,對於一些幹擾小、形變不嚴重的,使用tesserocr還是十分簡單方便的。然後將修改後的claptcha.py的285行_drawLine還原,看加入乾擾線的狀況。

p4 = Image.open('4.png')
tesserocr.image_to_text(p4)
''


加上了條幹擾線就完全辨識不出來了,那麼有沒有辦法去掉幹擾線呢?

雖然圖片看起來是黑白的,但還需要進行灰階處理,否則使用load()函數得到的是某個像素點的RGB元組而不是單一值了。處理如下:

def binarizing(img,threshold):
 """传入image对象进行灰度、二值处理"""
 img = img.convert("L") # 转灰度
 pixdata = img.load()
 w, h = img.size
 # 遍历所有像素,大于阈值的为黑色
 for y in range(h):
  for x in range(w):
   if pixdata[x, y] < threshold:
    pixdata[x, y] = 0
   else:
    pixdata[x, y] = 255
 return img


處理後的圖片如下:

##可以看出處理後圖銳化了許多,接下來嘗試移除乾擾線,常見的4鄰域、8鄰域演算法。所謂的X鄰域演算法,可以參考手機九宮格輸入法,按鍵5為要判斷的像素點,4鄰域就是判斷上下左右,8鄰域就是判斷周圍8個像素點。如果這4或8個點中255的個數大於某個閾值則判斷這個點為噪音,閾值可以根據實際情況修改。

def depoint(img):
 """传入二值化后的图片进行降噪"""
 pixdata = img.load()
 w,h = img.size
 for y in range(1,h-1):
  for x in range(1,w-1):
   count = 0
   if pixdata[x,y-1] > 245:#上
    count = count + 1
   if pixdata[x,y+1] > 245:#下
    count = count + 1
   if pixdata[x-1,y] > 245:#左
    count = count + 1
   if pixdata[x+1,y] > 245:#右
    count = count + 1
   if pixdata[x-1,y-1] > 245:#左上
    count = count + 1
   if pixdata[x-1,y+1] > 245:#左下
    count = count + 1
   if pixdata[x+1,y-1] > 245:#右上
    count = count + 1
   if pixdata[x+1,y+1] > 245:#右下
    count = count + 1
   if count > 4:
    pixdata[x,y] = 255
 return img


處理後的圖片如下:

####


好像……根本没卵用啊?!确实是这样的,因为示例中的图片干扰线的宽度和数字是一样的。对于干扰线和数据像素不同的,比如Captcha生成的验证码:

从左到右依次是原图、二值化、去除干扰线的情况,总体降噪的效果还是比较明显的。另外降噪可以多次执行,比如我对上面的降噪后结果再进行依次降噪,可以得到下面的效果:


再进行识别得到了结果:

p7 = Image.open(&#39;7.png&#39;)
tesserocr.image_to_text(p7)
&#39;8069 ,,\n\n&#39;

另外,从图片来看,实际数据颜色明显和噪点干扰线不同,根据这一点可以直接把噪点全部去除,这里就不展开说了。
第一篇文章,先记录如何将图片进行灰度处理、二值化、降噪,并结合tesserocr来识别简单的验证码,剩下的部分在下一篇文章中和大家一起分享。

相关推荐:

Python验证码识别处理实例

以上是python驗證碼識別教程之灰階處理、二值化、降噪與tesserocr識別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn