天天看點

[56]利用pytesser識别圖形驗證碼

簡單識别

1.一般思路

驗證碼識别的一般思路為:

  • 圖檔降噪
  • 圖檔切割
  • 圖像文本輸出

1.1 圖檔降噪

所謂降噪就是把不需要的資訊通通去除,比如背景,幹擾線,幹擾像素等等,隻剩下需要識别的文字,讓圖檔變成2進制點陣最好。

對于彩色背景的驗證碼:每個像素都可以放在一個5維的空間裡,這5個次元分别是,X,Y,R,G,B,也就是像素的坐标和顔色,在計算機圖形學中,有很多種色彩空間,最常用的比如RGB,印刷用的CYMK,還有比較少見的HSL或者HSV,每種色彩空間的次元都不一樣,但是可以通過公式互相轉換。在RGB空間中不好區分顔色,可以把色彩空間轉換為HSV或HSL。色彩空間參見 http://baike.baidu.com/view/3427413.htm

驗證碼圖檔

7039.jpg

[56]利用pytesser識别圖形驗證碼

1、導入Image包,打開圖檔:

from PIL import Image
im = Image.open('7039.jpg')
           

2、把彩色圖像轉化為灰階圖像。RBG轉化到HSI彩色空間,采用I分量:

imgry = im.convert('L')
imgry.show()
           

灰階看起來是這樣的:

[56]利用pytesser識别圖形驗證碼

3、二值化處理

二值化是圖像分割的一種常用方法。在二值化圖象的時候把大于某個臨界灰階值的像素灰階設為灰階極大值,把小于這個值的像素灰階設為灰階極小值,進而實作二值化(一般設定為0-1)。根據門檻值選取的不同,二值化的算法分為固定門檻值和自适應門檻值,這裡選用比較簡單的固定門檻值。

把像素點大于門檻值的設定,1,小于門檻值的設定為0。生成一張查找表,再調用point()進行映射。

threshold = 140
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)
out = imgry.point(table, '1')
out.show()
           

或者用匿名函數

from PIL import Image

im = Image.open("7364.jpg")

im_gary = im.point(lambda x: 0 if x<143 else 255) #二值化處理

im_gary.show()
           

處理結果看起來是這樣的:

[56]利用pytesser識别圖形驗證碼

2. 圖檔切割

識别驗證碼的重點和難點就在于能否成功分割字元,對于顔色相同又完全粘連的字元,比如google的驗證碼,目前是沒法做到5%以上的識别率的。不過google的驗證碼基本上人類也隻有30%的識别率。本文使用的驗證碼例子比較容易識别。可以不用切割,有關圖檔切割的方法參見這篇部落格:http://www.cnblogs.com/apexchu/p/4231041.html

3.利用pytesser子產品實作識别

pytesser是谷歌OCR開源項目的一個子產品,在python中導入這個子產品即可将圖檔中的文字轉換成文本。

連結:https://code.google.com/p/pytesser/

pytesser 調用了 tesseract。在python中調用pytesser子產品,pytesser又用tesseract識别圖檔中的文字。

3.1 pytesser安裝

簡單識别安裝

  • 把下載下傳下來的

    pytesser

    包解壓到python目錄的

    Lib/site_packages

    裡面,名字取為

    pytesser

    ,
  • 然後再在這個目錄下面建立一個

    pytesser.pth

    檔案,内容為

    pytesser

    或者建立一個

    __init__.py

    空白檔案,
  • 然後修改

    pytesser.py

    ,把第一句的

    import Image

    修改為

    from PIL import Image

    ,這一步的原因是這裡我們用的是pillow而不是用的原生PIL。
  • pytesser裡包含了

    tesseract.exe

    和英語的資料包(預設隻識别英文),還有一些示例圖檔,是以解壓縮後即可使用。

這樣做好以後記得把**

pytesser

這個目錄放入到系統環境變量**,因為程式會調用這個目錄裡面的

tesseract.exe

,如果不放到環境變量會因為找不到這個檔案而抛出異常。

簡單識别代碼

# -*- coding:utf-8 -*-

from PIL import Image
from pytesser import pytesser

im = Image.open(r'C:\Users\Administrator\Desktop\1.png')

imgry = im.convert('L')
# imgry.show()

threshold = 140
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)
out = imgry.point(table, '1')
out.show()
text = pytesser.image_to_string(out)  # 将圖檔轉成字元串
print text.replace(' ', '').replace('\n', '') #這裡因為識别出來的文字可能會有空格和回車
           

複雜識别安裝

  • 如果沒有安裝PIL,請到這裡下載下傳安裝:http://www.pythonware.com/products/pil/
  • 安裝pytesser,下載下傳位址:http://code.google.com/p/pytesser/ ,下載下傳後直接将其解壓到項目代碼下,或者解壓到python安裝目錄的

    Libsite-packages

    下,并将其添加到

    path

    環境變量中,不然在導入子產品時會出錯。
  • 下載下傳Tesseract OCR engine:http://code.google.com/p/tesseract-ocr/ ,下載下傳後解壓,找到tessdata檔案夾,用其替換掉pytesser解壓後的tessdata檔案夾即可。

另外如果現在都是從PIL庫中運入Image,沒有使用Image子產品,是以需要把

pytesser.py

中的

import Image

改為

from PIL import Image

, 其次還需要在

pytesser

檔案夾中建立一個

__init__.py

的空檔案。

3.2 調用pytesser識别

pytesser提供了兩種識别圖檔方法,通過image對象和圖檔位址,代碼判斷如下:

from PIL import Image
from pytesser import pytesser
image = Image.open('7039.jpg')
#通過打開的檔案識别
print pytesser.image_to_string(image)
#通過檔案路徑直接識别
print pytesser.image_file_to_string('7039.jpg')

           

同時pytesser還支援其他語言的識别,比如中文。具體參見:http://www.tuicool.com/articles/amQJR3

3.3解決識别率低的問題

可以增強圖檔的顯示效果,或者将其轉換為黑白的,這樣可以使其識别率提升不少:

from PIL import ImageEnhance
image = Image.open(r'C:\Users\Administrator\Desktop\1.png')
enhancer = ImageEnhance.Contrast(image)
image2 = enhancer.enhance(4)
           

可以再對image2調用

image_to_string

識别

3.4識别其他語言

tesseract

是一個指令行下運作的程式,參數如下:

tesseract imagename outbase [-l lang] [-psm N] [configfile...]

imagename

是輸入的

image

的名字

outbase

是輸出的文本的名字,預設為

outbase.txt

-l lang

是定義要識别的的語言,預設為英文

  • 通過以下步驟可以識别其他語言:

(1)、下載下傳其他語言資料包:

https://code.google.com/p/tesseract-ocr/downloads/list

将語言包放入pytesser的tessdata檔案夾下

要識别其他語言隻要添加一個

language

參數就行了,下面是我的例子:

"""OCR in Python using the Tesseract engine from Google
http://code.google.com/p/pytesser/
by Michael J.T. O'Kelly
V 0.0.1, 3/10/07"""

from PIL import Image
import subprocess
import util
import errors

tesseract_exe_name = 'D:\\Python2.7\\Lib\\site-packges\\pytesser\\tesseract' # Name of executable to be called at command line
scratch_image_name = "temp.bmp" # This file must be .bmp or other Tesseract-compatible format
scratch_text_name_root = "temp" # Leave out the .txt extension
cleanup_scratch_flag = True  # Temporary files cleaned up after OCR operation

def call_tesseract(input_filename, output_filename, language):
	"""Calls external tesseract.exe on input file (restrictions on types),
	outputting output_filename+'txt'"""
	args = [tesseract_exe_name, input_filename, output_filename, "-l", language]
	proc = subprocess.Popen(args)
	retcode = proc.wait()
	if retcode!=0:
		errors.check_for_errors()

def image_to_string(im, cleanup = cleanup_scratch_flag, language = "eng"):
	"""Converts im to file, applies tesseract, and fetches resulting text.
	If cleanup=True, delete scratch files after operation."""
	try:
		util.image_to_scratch(im, scratch_image_name)
		call_tesseract(scratch_image_name, scratch_text_name_root,language)
		text = util.retrieve_text(scratch_text_name_root)
	finally:
		if cleanup:
			util.perform_cleanup(scratch_image_name, scratch_text_name_root)
	return text

def image_file_to_string(filename, cleanup = cleanup_scratch_flag, graceful_errors=True, language = "eng"):
	"""Applies tesseract to filename; or, if image is incompatible and graceful_errors=True,
	converts to compatible format and then applies tesseract.  Fetches resulting text.
	If cleanup=True, delete scratch files after operation."""
	try:
		try:
			call_tesseract(filename, scratch_text_name_root, language)
			text = util.retrieve_text(scratch_text_name_root)
		except errors.Tesser_General_Exception:
			if graceful_errors:
				im = Image.open(filename)
				text = image_to_string(im, cleanup)
			else:
				raise
	finally:
		if cleanup:
			util.perform_cleanup(scratch_image_name, scratch_text_name_root)
	return text
	

if __name__=='__main__':
	im = Image.open('phototest.tif')
	text = image_to_string(im)
	print text
	try:
		text = image_file_to_string('fnord.tif', graceful_errors=False)
	except errors.Tesser_General_Exception, value:
		print "fnord.tif is incompatible filetype.  Try graceful_errors=True"
		print value
	text = image_file_to_string('fnord.tif', graceful_errors=True)
	print "fnord.tif contents:", text
	text = image_file_to_string('fonts_test.png', graceful_errors=True)
	print text
           

在調用

image_to_string

函數時,隻要加上相應的

language

參數就可以了,如簡體中文最後一個參數即為

chi_sim

, 繁體中文

chi_tra

,

也就是下載下傳的語言包的

XXX.traineddata

檔案的名字

XXX

,如下載下傳的中文包是

chi_sim.traineddata

, 參數就是

chi_sim

:

text = image_to_string(self.im, language = 'chi_sim')
           

至此,圖檔識别就完成了。

額外附加一句:有可能中文識别出來了,但是亂碼,需要相應地将text轉換為你所用的中文編碼方式,如:

text.decode("utf8")

就可以了

參考:

1.http://www.tuicool.com/articles/amQJR3

2.https://mp.weixin.qq.com/s?__biz=MzA4MjEyNTA5Mw==&mid=404976285&idx=2&sn=3f3468cbcde49e7b905fb959b12d9781&scene=1&srcid=0331HhwonQhoinOiEDfXPEzE&from=singlemessage&isappinstalled=0#wechat_redirect

3.http://blog.csdn.net/fu_shuwu/article/details/53365132