knn算法,識別簡單驗證碼圖片
- 2019 年 11 月 27 日
- 筆記
引言:為什麼學習這個呢?
這個算是機器學習,最入門的一點東東
這裡介紹兩種方法:
1.直接調用第三方庫進行識別,缺點:存在部分圖片無法識別
2.使用knn算法進行對圖片的處理,以及運算進行識別
聲明:本文均在pycharm上進行編輯操作,並本文所寫代碼均是python3進行編寫,如果不能正常運行本文內的代碼,請自己調試環境
另本文所識別的驗證碼類型為如下圖片:

先介紹第一種比較簡單的操作:
1.環境準備:
安裝如下第三方庫
from selenium import webdriver from PIL import Image import pytesseract
2.環境介紹
selenium 環境模仿鼠標點動,以及賬號密碼傳遞,等等
pytesseract 識別圖片中字符借用的第三方庫
PIL 對圖片的一些處理的第三方庫
3.具體實現
driver.find_element_by_xpath('地址').click()
點擊網頁中xpath為括號內的位置
driver.find_element_by_xpath('地址').send_keys(傳遞信息)
傳遞相應數據到xpath為括號內的相應位置
ele=driver.find_element_by_xpath('地址') ele.screenshot('圖片名,以及格式')
找到xpath為括號內的地址,並截取相應位置圖片
4.圖片處理
在獲取相應驗證碼圖片後,往往圖片為彩圖,或者存在噪點,為了減少模型的複雜度,以及減少模型的訓練強度,同時增加識別率,很有必要對圖片進行預處理,使其對機器識別更友好。
具體步驟如下:
1.讀取原始素材
2.將彩圖轉化為黑白圖
3.去噪點
4.1二值化圖片
圖像二值化( Image Binarization)就是將圖像上的像素點的灰度值設置為0或255,也就是將整個圖像呈現出明顯的黑白效果的過程。——來自百度百科
1.RGB彩圖轉為灰度圖
2.將灰度圖轉化為二值圖,即設定二值化閾值,轉化為01圖
image = Image.open('a.png') image = image.convert('L') #轉化為灰度圖 threshold = 127 #設定的二值化閾值 table = [] #table是設定的一個表,下面的for循環可以理解為一個規則,小於閾值的,就設定為0,大於閾值的,就設定為1 for i in range(256): if i < threshold: table.append(0) else: table.append(1) image = image.point(table,'1') #對灰度圖進行二值化處理,按照table的規則(也就是上面的for循環)
如下圖:

2.去除噪點
在轉化為二值圖片後,就需要清除噪點。本文選擇的素材比較簡單,大部分噪點也是最簡單的那種 孤立點,所以可以通過檢測這些孤立點就能移除大量的噪點。
關於如何去除更複雜的噪點甚至干擾線和色塊,有比較成熟的算法: 洪水填充法 Flood Fill ,後面有興趣的時間可以繼續研究一下。
轉載自 https://www.cnblogs.com/beer/p/5672678.htm
5.直接藉助selenium和pytesseract實現
result = pytesseract.image_to_string(image) # 讀取裏面的內容
輸出result,就是圖片的結果.
上述方法的精確度,嗯……..
我沒經過專業的測試,但是點着試試,試了二三十次,有那麼五六次是錯誤的
所以呢為了提高模型的精確度,下面介紹knn算法
knn:從訓練樣本集中選擇k個與測試樣本「距離」最近的樣本,這k個樣本中出現頻率最高的類別即作為測試樣本的類別。
- KNN是屬於有監督學習(因為訓練集中每個數據都存在人工設置的標籤——即類別)
- 那是如何進行分類的呢?其實是用數據之間的歐氏距離來衡量它們的相似程度,距離越短,表示兩個數據越相似。
5.建立樣本集—圖片分割
既然是樣本集,那麼肯定要有樣本呀,找相應網站,提交請求,爬取完事,在這不寫這個了
而樣本集的建立,可以數格子,沒錯就是數格子
打開ps,圖片放大到最大,然後數格子,額,這個方法有點low,在線ps:https://www.uupoop.com/
找到左上點,右下點,間距,然後循環切割,保存
from PIL import Image def cut_image(image): box_list = [] # (left, upper, right, lower) for i in range(0, 4): box = (5+i*12+1,5,14+i*12,19+1) box_list.append(box) image_list = [image.crop(box) for box in box_list] return image_list # 保存 def save_images(image_list): index = 1 for image in image_list: image.save(str(index) + '.png', 'PNG') index += 1 if __name__ == '__main__': file_path = "地址" # 圖片保存的地址 image = Image.open(file_path) image_list = cut_image(image) save_images(image_list)
效果圖:

上面方法有點low
所以可以,通過圖片黑色或白色的圖片的連續性,來進行尋找左上點和右下點來確定一個矩形範圍,即切割的圖片的位置,循環切割保存
def cut_image(image): """ 字符切割,根據黑色的連續性,當某一列出現黑色為標誌,當黑色消失為結束點 :param image: 完整的驗證碼圖片 :return images: 切割好的圖片列表 """ # inletter代表當前列是否出現黑點 inletter = False # foundletter為False時,未找到字符開始位置;否則,已找到字符開始位置 foundletter = False # 記錄所有字符的開始點和結束點 letters = [] start = 0 end = 0 for x in range(image.size[0]): for y in range(image.size[1]): # 當前像素點的狀態(0黑色或1白色) pix = image.getpixel((x,y)) # 出現黑色點時證明有字符出現 if pix == 0: inletter = True # 當前列出現黑色點,且未找到字符開始位置,則找當前列為字符開始位置 if foundletter == False and inletter ==True: foundletter = True start = x # 當前列為全白,且已有字符開始位置,則該字符結束,記錄字符的範圍 if foundletter == True and inletter == False: end = x letters.append((start,end)) foundletter = False inletter = False images = [] # 利用letter的信息切割驗證碼,得到單個字符 for letter in letters: img = image.crop((letter[0],0,letter[1],image.size[1])) #img.save(str(letter[0])+'.jpeg')#展示切割效果 images.append(img) return images
上面代碼只寫出連續黑的情況,所以在部分要進行修改
6.建立樣本集—分組
將爬取的樣本重複上述操作進行圖片處理和切割
將切割好的圖片,建立文件夾進行分組
7.識別
具體操作步驟如下: 1.預處理圖片
2.將圖片轉化
3.cos求解相似度
1.預處理圖片
上面的樣本切割出是單獨的數字,那麼在識別的時候,要對圖片進行處理以及切割,具體操作參考上面的介紹.
2.將圖片轉換
在將圖片切割後,是一個圖片的形式顯示,這樣不便於計算,所以將其轉化為矢量,將二維形式轉化為一維形式
def buildvector(image): """ 圖片轉換成矢量,將二維的圖片轉為一維 :param image: :return: """ result = {} count = 0 for i in image.getdata(): result[count] = i count += 1 return result
3.cos值求解相似度
求解方程:

即目標值與其中一個樣本值的相似度.
m表示該樣本組的數量,數組c表示目標圖片,數組d表示樣本組中的每一張圖片
另外在此所用的目標圖片和樣本圖片,均已經一維化處理
計算完目標圖片與所有樣本集後進行排序,去相似度最高即為目標圖片所示數字
class CaptchaRecognize: def __init__(self): self.letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] self.loadSet() def loadSet(self): """ 將icon中預先準備好的圖片,以向量的形式讀出 ps: icon中圖片為驗證碼切割完成後,人工標記的訓練集 如果需要增加,只需把切割後的圖片放到其所表示的文件夾下即可 :return: """ self.imgset = [] for letter in self.letters: temp = [] # 打開icon下的各個文件,icon文件下是一些已切割的字符圖片 for img in os.listdir('./icon/%s'%(letter)): # 將圖片轉成一維向量,放入temp列表中 temp.append(buildvector(Image.open('./icon/%s/%s'%(letter,img)))) # 標籤與對應圖片轉換成的向量,以字典形式存到imgset 如:letter為1,temp就是1文件夾下圖片的向量 self.imgset.append({letter:temp}) def magnitude(self,concordance): """ 利用公式求計算矢量大小,詳細公式見README.md :param concordance: :return: """ total = 0 for word, count in concordance.items(): # count 為向量各個單位的值 total += count ** 2 return math.sqrt(total) def relation(self, concordance1, concordance2): """ 計算矢量之間的 cos 值,詳細公式見README.md :param concordance1: :param concordance2: :return: """ relevance = 0 topvalue = 0 # 遍歷concordance1向量,word 當前位置的索引,count為值 for word, count in concordance1.items(): # 當concordance2有word才繼續,防止索引超限 if word in concordance2: #print(type(topvalue), topvalue, count, concordance2[word]) topvalue += count * concordance2[word] #time.sleep(10) return topvalue / (self.magnitude(concordance1) * self.magnitude(concordance2)) def recognise(self,image): """ 識別驗證碼 :param image: 驗證碼圖片 :return result: 返回驗證碼的值 """ # 二值化,將圖片按灰度轉為01矩陣 image = convert_image(image) # 對完整的驗證碼進行切割,得到字符圖片 images = cut_image(image) vectors = [] for img in images: vectors.append(buildvector(img)) # 將字符圖片轉一維向量,如[0,1,0,1,1,....] result = [] for vector in vectors: guess=[] # 讓字符圖片和訓練集中的 0-9 逐一比對 for image in self.imgset: for letter,temp in image.items(): relevance=0 num=0 # 遍歷一個標籤下的所有圖片 for img in temp: # 計算相似度 relevance+=self.relation(vector,img) print (vector,img) num+=1 # 求出相似度平均值 relevance=relevance/num guess.append((relevance,letter)) # 對cos值進行排序,cos值代表相識度 guess.sort(reverse=True) result.append(guess[0]) #取最相似的letter,作為該字符圖片的值 return result
8.主函數調用
if __name__ == '__main__': imageRecognize=CaptchaRecognize() # 設置圖片路徑 image = Image.open('3.png') # print(image.mode) result = imageRecognize.recognise(image) string = [''.join(item[1]) for item in result] print(result)
9.總結
本文主要是識別簡單的驗證碼圖片,要根據具體情況進行修改,主要提供一個框架,如果所給圖片呈不規則顯示,可能無法識別,這個算是機器學習簡單的入門,對於以上僅為個人看法,如果有別的看法,歡迎私聊!!!
原創文章,轉載請註明: 轉載自URl-team
本文鏈接地址: knn算法,識別簡單驗證碼圖片
No related posts.