基於SVM的python簡單實現驗證碼識別


 

驗證碼識別是一個適合入門機器學習的項目,之前用knn 做過一個很簡單的,這次用svm來實現。svm直接用了開源的庫libsvm。驗證碼選的比較簡單,代碼也寫得略亂,大家看看就好。

 

1. 爬取驗證碼圖片

 1 import urllib
 2 from urllib import request
 3 
 4 
 5 def download_pics(pic_name):
 6     url = 'http://smart.gzeis.edu.cn:8081/Content/AuthCode.aspx'
 7     res = request.urlopen(url)
 8     get_img = res.read()
 9 
10     with open( 'D:\python\驗證碼\%s.jpg'%(pic_name),'wb') as f:
11         f.write(get_img)
12 
13 if __name__ == '__main__':
14     for i in range(100):
15         pic_name = i
16         download_pics(pic_name)

 

 

2. 二值化

 接下來要做的工作就是二值化驗證碼,所謂二值化,就是將每一個像素點用0或1來表示,圖像的每個像素點都有rgb三個值,我們首先轉化成灰度圖,這樣每個像素點就只有一個灰度值了。接下來根據自己設定的閾值來確定每個像素點是該為0還是為1。

我的思路是首先將圖像轉化為array處理,當然完全可以直接圖像處理。

 1 def binarization(im):  #二值化
 2     imgry = im.convert('L')
 3     imgry = np.array(imgry)  #將圖像轉化為數組
 4     height, width = imgry.shape
 5     #f = open('s.txt','w')
 6     for i in range(height):
 7         for j in range(width):
 8             gray = imgry[i,j]
 9             if gray <= 220:  #閾值設為220
10                 imgry[i, j] = 0
11             else:
12                 imgry[i, j] = 1
13             #f.write(str(imgry[i,j]))  #輸出到txt查看
14         #f.write('\n')
15     '''
16     plt.figure('')
17     plt.imshow(imgry, cmap='gray')
18     plt.axis('off')
19     plt.show()
20     '''
21     return imgry

在二值化處理之后,處理結果如下所示:

                   

在txt的結果如下所示,可以很明顯的看到0413:

 

3. 去除噪點

在二值化之后,還存在一個問題就是圖像之中還有許多黑點,這成為噪點,是干擾項,去除噪點有很多不同的方法,由於我只是一個小菜鳥,所以我就用了最簡單的8-鄰域去除噪點法。依次檢查每個像素點周圍8個點的情況,如果黑點少於閾值時,那么就可以認為該點是噪點。其實這樣的處理效果是比較差的,只是適用於去除小點,但是對於干擾線條這種可能就沒什么作用了。

 1 def noiseReduction(imgry):  #去除噪點
 2     global dx, dy
 3     height, width = imgry.shape
 4     for i in range(height):
 5         for j in range(width):
 6             cnt = 0
 7             if imgry[i, j] == 1:  #白點不用管
 8                 continue
 9             else:
10                 for k in range(8):
11                     x = dx[k] + i
12                     y = dy[k] + j
13                     if x < 0 or x >= height or y < 0 or y >= width:
14                         continue
15                     if imgry[x, y] == 0:
16                         cnt += 1
17             if cnt < 4:  #周圍少於4點就算噪點
18                 imgry[i, j] = 1
19     return imgry

處理之后可以明顯的看到黑點基本上都被處理掉了。

 

4. 圖片分割

 接下來要做的就是將這四個數字分割開來形成訓練集,這個操作並不難。因為這些驗證碼的位置都是差不多的,如果驗證碼字符位置比較亂的話就會比較麻煩。。

 1 def cutImg(img):  #圖像切割
 2     s = 12
 3     w = 40
 4     h = 81
 5     t = 0
 6     cut_img = []
 7     for i in range(4):
 8         pic = img.crop((s + w * i, t, s + w * (i + 1), h))
 9         cut_img.append(pic)
10     return cut_img

 

5. 圖片分類

這個步驟的目的就是人為的給訓練集打上標簽。 將相同的數字放在同一個文件夾下面。

             

 

6.  訓練模型

 訓練模型很簡單,因為直接就是使用libsvm庫,我們只需要按照數據格式生成一些特征值即可。在切割完圖片並保存之后,我發現我圖片的像素值有略微的改變,可能是重新保存了的原因,所有我這里又進行了一次二值化。。。

這里說明依稀libsvm數據格式的要求:

[label]   [index:value]   [index:value]   [index:value].....

每一個數據都是這樣的格式,label是標簽,[index:value]是數據的特征值,index就是從0開始的編號,value是特征值。

在這里對於每一張圖片,我就把特征值設為每行每列的黑點個數了。如第一個特征值就是第一行黑點個數。。。

 1 import os
 2 from PIL import *
 3 from PIL import Image
 4 import numpy as np
 5 from libsvm.python.svmutil import *
 6 from libsvm.python.svm import *
 7 
 8 
 9 address = 'D:\python\驗證碼-sort\\'
10 f = open('train.txt', 'w')
11 
12 def get_feature(dir, file):
13     f.write(dir)
14     im = Image.open(address + dir +'\\' + file)
15     imarr = np.array(im)
16     height, width = imarr.shape
17     for i in range(height):
18         for j in range(width):
19             gray = imarr[i,j]
20             if gray <= 150:
21                 imarr[i, j] = 0
22             else:
23                 imarr[i, j] = 255
24     im = Image.fromarray(imarr)
25     count = 0
26     width, height = im.size
27     for i in range(height):
28         c = 0
29         for j in range(width):
30             if im.getpixel((j, i)) == 0: c += 1
31         f.write(' %d:%d'%(count, c))
32         count += 1
33     for i in range(width):
34         c = 0
35         for j in range(height):
36             if im.getpixel((i, j)) == 0: c += 1
37         f.write(' %d:%d'%(count, c))
38         count += 1
39     f.write('\n')
40 
41 def train_svm_model():
42     y, x = svm_read_problem('train.txt')
43     model = svm_train(y, x)
44     svm_save_model('model_file', model)
45 
46 if __name__ == '__main__':
47     dirs = os.listdir(address)
48     for dir in dirs:
49         files = os.listdir(address + dir)
50         for file in files:
51             get_feature(dir, file)
52     train_svm_model()

 

7.  測試模型

 用測試數據對模型進行測試。

1 from libsvm.python.svmutil import *
2 from libsvm.python.svm import *
3 import image_slove
4 
5 if __name__ == '__main__':
6     model = svm_load_model('model_file')
7     yt, xt = svm_read_problem('test.txt')
8     p_label, p_acc, p_val = svm_predict(yt, xt, model)

還是不錯的,畢竟驗證碼很簡單。。。

 

8.  預測驗證碼

終於走到最后一步了,得到一張驗證碼后先按照之前的操作根據該圖片生成特征值,這里標簽還是需要的,可以隨便填一個,反正這個不重要。或許有別的方法,反正我暫時還不知道。

 1 from libsvm.python.svmutil import *
 2 from libsvm.python.svm import *
 3 from PIL import Image
 4 import image_slove
 5 
 6 if __name__ == '__main__':
 7     '''
 8       在這里處理圖片生成特征值
 9     '''
10     model = svm_load_model('model_file')
11     yt, xt = svm_read_problem('predict.txt')
12     p_label, p_acc, p_val = svm_predict(yt, xt, model)
13     print('該驗證碼為:', end='')
14     for label in p_label:
15         print(int(label), end='')

最后成功的驗證出來了。

 

9.  總結

通過這個實驗對於驗證碼識別流程有了一定的了解,這次也是直接使用了支持向量機,后續需要稍微學習一下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM