Steven5538

CAPTCHA OCR 前置處理 - 去噪、補點

Word count: 680Reading time: 2 min
2014/06/22 Share

OCR 在網路上已經有相當多的 module 可以直接使用,以我來說,我是用 tesseract,也有人寫好了 python-tesseract 可以直接調用,相當方便。
但以正常情況來說,如果要對驗證碼做 OCR 的話,驗證碼本身會有許多雜訊干擾,導致 OCR 失敗。
以我現在手上這個例子來說,沒處理的情況是這樣的:

可以看到有相當多雜亂的線條,這些線條會影響 OCR 的判斷。
所以在 OCR 之前需要做一些影像的前置處理,而第一步,就是去噪。

而去噪這件事其實很看影像本身的雜訊特性,以我這張來說,由於是人工加上去的噪音,畫頻域的解法顯然是不太準確。
但可以觀察出除了字和框以外的地方,其雜訊顏色是較為黯淡的,遂我們可用透過亮度與對比的調整將比較黯淡的部份淡化掉。

1
2
3
4
enhancer = ImageEnhance.Contrast(im)
im = enhancer.enhance(3.0)
enhancer = ImageEnhance.Brightness(im)
im = enhancer.enhance(10.0)

結果滿顯著的。

可以看到明顯有顏色的部份只剩下字體和框線,而且根據 pixel value 的觀察由於圖像是 RGBA,字體的部份 B = 255,邊緣部分則有些為的 Alpha。透過下面程式碼簡單取點並且轉化為黑白兩色。

1
2
3
4
5
6
for x in xrange(w):
for y in xrange(h):
if pix[x , y][1] != 255 and pix[x , y][2] == 255 and pix[x , y][3] == 255:
pix[x , y] = (0 , 0 , 0 , 255)
else:
pix[x , y] = (255 , 255 , 255 , 255)

可以看到結果相當不錯。

基本上到此去噪步驟已經完成。
但我們也可以觀察出,儘管沒有雜訊,但由於字本身缺少太多點,有時會影響辨識率,此時便是第二步,補點。
在補點上我們可以用到 Opening 的方式將點補上 (如果黑白反轉的話要用 Closing),至於 Opening 跟 Closing 是什麼 OpenCV 有詳細介紹
以我們的例子來說,由於圖片大小相當小,kernel 我設定為 2 x 2,其他與官網所寫無異。

1
2
3
img = cv2.imread('tmp.png' , 0)
kernel = np.ones((2 , 2) , np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

所得到的結果如圖:

可以看到後面的字補的相當好,唯有 6 黏起來了,但是 tesseract 辨識結果還是為 6。
以這樣的處理方式,本例子的驗證碼利用 tesseract 的話辨識率為五成,辨識錯誤通常在於有些字如 6、5、S、Z,在補點後有些情況下會黏在一起,或許這不是最好的補點方式,不過暫時還想不到別的方法就是了。

CATALOG