国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

太囂張了!他竟用Python繞過了“驗證碼”

開發(fā) 后端 開發(fā)工具
很多網(wǎng)站登錄都需要輸入驗證碼,如果要實現(xiàn)自動登錄就不可避免的要識別驗證碼。本文以一個真實網(wǎng)站的驗證碼為例,實現(xiàn)了基于 KNN 的驗證碼識別。

 [[250250]]

 

 

準(zhǔn)備工作

 

 


這里我們使用 OpenCV 做圖像處理,所以需要安裝下面兩個庫:

  1. pip3 install opencv-python  
  2. pip3 install numpy  

 

識別原理

 

 

我們采取一種有監(jiān)督式學(xué)習(xí)的方法來識別驗證碼,包含以下幾個步驟:

  • 圖片處理:對圖片進行降噪、二值化處理。

  • 切割圖片:將圖片切割成單個字符并保存。

  • 人工標(biāo)注:對切割的字符圖片進行人工標(biāo)注,作為訓(xùn)練集。

  • 訓(xùn)練數(shù)據(jù):用 KNN 算法訓(xùn)練數(shù)據(jù)。

  • 檢測結(jié)果:用上一步的訓(xùn)練結(jié)果識別新的驗證碼。

 

下面我們來逐一介紹每一步的過程,并給出具體的代碼實現(xiàn)。

 

 

圖片處理

 


先來看一下我們要識別的驗證碼是長什么樣的:

上圖可以看到,字符做了一些扭曲變換。仔細觀察,還可以發(fā)現(xiàn)圖片中間的部分添加了一些顆粒化的噪聲。

 

我們先讀入圖片,并將圖片轉(zhuǎn)成灰度圖,代碼如下:

  1. import cv2 
  2.  
  3. im = cv2.imread(filepath) 
  4. im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) 

經(jīng)過上面的處理,我們的彩色圖片變成了下面這樣:

將圖片做二值化處理,代碼如下:

  1. ret, im_inv = cv2.threshold(im_gray,127,255,cv2.THRESH_BINARY_INV) 

127 是我們設(shè)定的閾值,像素值大于 127 被置成了 0,小于 127 的被置成了 255。處理后的圖片變成了這樣:

接下來,我們應(yīng)用高斯模糊對圖片進行降噪。高斯模糊的本質(zhì)是用高斯核和圖像做卷積,代碼如下:

  1. kernel = 1/16*np.array([[1,2,1], [2,4,2], [1,2,1]]) 
  2. im_blur = cv2.filter2D(im_inv,-1,kernel) 

降噪后的圖片如下:

上圖可以看到一些顆粒化的噪聲被平滑掉了。降噪后,我們對圖片再做一輪二值化處理:

  1. ret, im_res = cv2.threshold(im_blur,127,255,cv2.THRESH_BINARY) 

現(xiàn)在圖片變成了這樣:

好了,接下來,我們要開始切割圖片了。

 

 

切割圖片

 


這一步是所有步驟里最復(fù)雜的一步。我們的目標(biāo)是把最開始的圖片切割成單個字符,并把每個字符保存成如下的灰度圖:

首先我們用 OpenCV 的 findContours 來提取輪廓:

  1. im2, contours, hierarchy = cv2.findContours(im_res, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 

我們把提取的輪廓用矩形框起來,畫出來是這樣的:

可以看到,每個字符都被檢測出來了。但這只是理想情況,很多時候,相鄰字符有粘連的會被識別成同一個字符,比如像下面的情況:

要處理這種情況,我們就要對上面的圖片做進一步的分割。字符粘連會有下面幾種情況,我們逐一來看下該怎么處理。

 

①4 個字符被識別成 3 個字符

這種情況,對粘連的字符輪廓,從中間進行分割,代碼如下:

  1. result = [] 
  2. for contour in contours: 
  3.     x, y, w, h = cv2.boundingRect(contour) 
  4.     if w == w_max: # w_max是所有contonur的寬度中最寬的值 
  5.         box_left = np.int0([[x,y], [x+w/2,y], [x+w/2,y+h], [x,y+h]]) 
  6.         box_right = np.int0([[x+w/2,y], [x+w,y], [x+w,y+h], [x+w/2,y+h]]) 
  7.         result.append(box_left) 
  8.         result.append(box_right) 
  9.     else
  10.         box = np.int0([[x,y], [x+w,y], [x+w,y+h], [x,y+h]]) 
  11.         result.append(box) 

分割后,圖片變成了這樣:

②4 個字符被識別成 2 個字符

 

4 個字符被識別成 2 個字符有下面兩種情況:

對第一種情況,對于左右兩個輪廓,從中間分割即可。對第二種情況,將包含了 3 個字符的輪廓在水平方向上三等分。

 

具體代碼如下:

  1. result = [] 
  2. for contour in contours: 
  3.     x, y, w, h = cv2.boundingRect(contour) 
  4.     if w == w_max and w_max >= w_min * 2: 
  5.         # 如果兩個輪廓一個是另一個的寬度的2倍以上,我們認(rèn)為這個輪廓就是包含3個字符的輪廓 
  6.         box_left = np.int0([[x,y], [x+w/3,y], [x+w/3,y+h], [x,y+h]]) 
  7.         box_mid = np.int0([[x+w/3,y], [x+w*2/3,y], [x+w*2/3,y+h], [x+w/3,y+h]]) 
  8.         box_right = np.int0([[x+w*2/3,y], [x+w,y], [x+w,y+h], [x+w*2/3,y+h]]) 
  9.         result.append(box_left) 
  10.         result.append(box_mid) 
  11.         result.append(box_right) 
  12.     elif w_max < w_min * 2: 
  13.         # 如果兩個輪廓,較寬的寬度小于較窄的2倍,我們認(rèn)為這是兩個包含2個字符的輪廓 
  14.         box_left = np.int0([[x,y], [x+w/2,y], [x+w/2,y+h], [x,y+h]]) 
  15.         box_right = np.int0([[x+w/2,y], [x+w,y], [x+w,y+h], [x+w/2,y+h]]) 
  16.         result.append(box_left) 
  17.         result.append(box_right) 
  18.     else
  19.         box = np.int0([[x,y], [x+w,y], [x+w,y+h], [x,y+h]]) 
  20.         result.append(box) 

分割后的圖片如下:

③4 個字符被識別成 1 個字符

這種情況對輪廓在水平方向上做四等分即可,代碼如下:

  1. result = [] 
  2. contour = contours[0] 
  3. x, y, w, h = cv2.boundingRect(contour) 
  4. box0 = np.int0([[x,y], [x+w/4,y], [x+w/4,y+h], [x,y+h]]) 
  5. box1 = np.int0([[x+w/4,y], [x+w*2/4,y], [x+w*2/4,y+h], [x+w/4,y+h]]) 
  6. box2 = np.int0([[x+w*2/4,y], [x+w*3/4,y], [x+w*3/4,y+h], [x+w*2/4,y+h]]) 
  7. box3 = np.int0([[x+w*3/4,y], [x+w,y], [x+w,y+h], [x+w*3/4,y+h]]) 
  8. result.extend([box0, box1, box2, box3]) 

分割后的圖片如下:

對圖片分割完成后,我們將分割后的單個字符的圖片存成不同的圖片文件,以便下一步做人工標(biāo)注。

 

存取字符圖片的代碼如下:

  1. for box in result: 
  2.     cv2.drawContours(im, [box], 0, (0,0,255),2) 
  3.     roi = im_res[box[0][1]:box[3][1], box[0][0]:box[1][0]] 
  4.     roistd = cv2.resize(roi, (30, 30)) # 將字符圖片統(tǒng)一調(diào)整為30x30的圖片大小 
  5.     timestamp = int(time.time() * 1e6) # 為防止文件重名,使用時間戳命名文件名 
  6.     filename = "{}.jpg".format(timestamp
  7.     filepath = os.path.join("char", filename) 
  8.     cv2.imwrite(filepath, roistd) 

字符圖片保存在名為 char 的目錄下面,這個目錄里的文件大致是長這樣的(文件名用時間戳命名,確保不會重名):

接下來,我們開始標(biāo)注數(shù)據(jù)。

 

 

人工標(biāo)注

 


這一步是所有步驟里最耗費體力的一步了。為節(jié)省時間,我們在程序里依次打開 char 目錄中的每張圖片,鍵盤輸入字符名,程序讀取鍵盤輸入并將字符名保存在文件名里。

 

代碼如下:

  1. files = os.listdir("char"
  2. for filename in files: 
  3.     filename_ts = filename.split(".")[0] 
  4.     patt = "label/{}_*".format(filename_ts) 
  5.     saved_num = len(glob.glob(patt)) 
  6.     if saved_num == 1: 
  7.         print("{} done".format(patt)) 
  8.         continue 
  9.     filepath = os.path.join("char", filename) 
  10.     im = cv2.imread(filepath) 
  11.     cv2.imshow("image", im) 
  12.     key = cv2.waitKey(0) 
  13.     if key == 27: 
  14.         sys.exit() 
  15.     if key == 13: 
  16.         continue 
  17.     char = chr(key
  18.     filename_ts = filename.split(".")[0] 
  19.     outfile = "{}_{}.jpg".format(filename_ts, char
  20.     outpath = os.path.join("label", outfile) 
  21.     cv2.imwrite(outpath, im) 

這里一共標(biāo)注了大概 800 張字符圖片,標(biāo)注的結(jié)果存在名為 label 的目錄下,目錄下的文件是這樣的(文件名由原文件名+標(biāo)注名組成):

接下來,我們開始訓(xùn)練數(shù)據(jù)。

 

 

訓(xùn)練數(shù)據(jù)

 


首先,我們從 label 目錄中加載已標(biāo)注的數(shù)據(jù):

  1. filenames = os.listdir("label"
  2. samples = np.empty((0, 900)) 
  3. labels = [] 
  4. for filename in filenames: 
  5.     filepath = os.path.join("label", filename) 
  6.     label = filename.split(".")[0].split("_")[-1] 
  7.     labels.append(label) 
  8.     im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE) 
  9.     sample = im.reshape((1, 900)).astype(np.float32) 
  10.     samples = np.append(samples, sample, 0) 
  11. samples = samples.astype(np.float32) 
  12. unique_labels = list(set(labels)) 
  13. unique_ids = list(range(len(unique_labels))) 
  14. label_id_map = dict(zip(unique_labels, unique_ids)) 
  15. id_label_map = dict(zip(unique_ids, unique_labels)) 
  16. label_ids = list(map(lambda x: label_id_map[x], labels)) 
  17. label_ids = np.array(label_ids).reshape((-1, 1)).astype(np.float32) 

接下來,訓(xùn)練我們的模型:

  1. model = cv2.ml.KNearest_create() 
  2. model.train(samples, cv2.ml.ROW_SAMPLE, label_ids) 

訓(xùn)練完,我們用這個模型來識別一下新的驗證碼。

 

 

檢測結(jié)果

 


下面是我們要識別的驗證碼:

對于每一個要識別的驗證碼,我們都需要對圖片做降噪、二值化、分割的處理(代碼和上面的一樣,這里不再重復(fù))。

 

假設(shè)處理后的圖片存在變量 im_res 中,分割后的字符的輪廓信息存在變量 boxes 中,識別驗證碼的代碼如下:

  1. for box in boxes: 
  2.     roi = im_res[box[0][1]:box[3][1], box[0][0]:box[1][0]] 
  3.     roistd = cv2.resize(roi, (30, 30)) 
  4.     sample = roistd.reshape((1, 900)).astype(np.float32) 
  5.     ret, results, neighbours, distances = model.findNearest(sample, k = 3) 
  6.     label_id = int(results[0,0]) 
  7.     label = id_label_map[label_id] 
  8.     print(label) 

運行上面的代碼,可以看到程序輸出:

圖片中的驗證碼被成功地識別出來。我們測試了下識別的準(zhǔn)確率,取 100 張驗證碼圖片(存在 test 目錄下)進行識別,識別的準(zhǔn)確率約為 82%。

 

看到有人說用神經(jīng)網(wǎng)絡(luò)識別驗證碼,準(zhǔn)確率可以達到 90% 以上,下次有機會可以嘗試一下。

 

完整代碼已上傳 GitHub,所有訓(xùn)練數(shù)據(jù)、測試數(shù)據(jù)、已標(biāo)注圖片都已上傳百度網(wǎng)盤,后臺回復(fù)“驗證碼”可獲取地址。

 

責(zé)任編輯:武曉燕 來源: Python與數(shù)據(jù)分析
相關(guān)推薦

2022-05-11 07:41:31

Python驗證碼

2017-05-16 14:18:08

2017-05-18 09:36:11

大數(shù)據(jù)爬蟲驗證碼

2013-06-19 10:19:59

2020-11-16 07:28:53

驗證碼

2009-02-09 14:17:36

2009-08-11 14:05:28

JSP驗證碼

2015-03-23 17:58:04

驗證碼倒計時并行

2015-09-21 15:31:05

php實現(xiàn)驗證碼

2022-02-11 07:10:15

驗證碼

2021-01-19 10:29:34

短信驗證碼密碼

2017-12-21 07:38:19

2021-08-02 12:29:15

Python爬蟲網(wǎng)站

2024-01-29 08:32:10

Python驗證碼識別

2015-03-17 09:28:04

2011-11-02 12:43:33

2011-11-02 16:46:41

2019-06-18 07:12:25

驗證碼漏洞加密

2020-07-31 07:56:47

驗證碼
點贊
收藏

51CTO技術(shù)棧公眾號

久久精品影视大全| 欧美日韩黄网站| 国产日韩欧美制服另类| 日韩一区二区三区资源| 99re6这里只有精品| 色综合视频网站| 日韩精品三区| 国产午夜精品麻豆| av免费不卡| 日韩精品一区二区在线观看| www在线播放| 91搞黄在线观看| 九一在线视频| 欧美日韩不卡一区| 岛国成人毛片| 精品国产3级a| 午夜伦理福利在线| 亚洲色图17p| 88xx成人网| 久久久91精品国产一区不卡| 激情久久一区二区| 久久综合久久88| 亚洲精品观看| 97超碰国产精品女人人人爽 | a级国产乱理论片在线观看99| 精品产国自在拍| 日本久久久a级免费| 中国av在线播放| 欧美精品精品精品精品免费| 99re6在线精品视频免费播放| 欧美独立站高清久久| 97视频在线观看视频免费视频| 国产精品一区二区三区av| 最近2019年日本中文免费字幕| 精品123区| 久久精品这里热有精品| 日本免费精品| 国产精品成人va在线观看| 自拍欧美日韩| 亚洲精品中文综合第一页| 国产精品888| 亚洲欧美日韩一级| 欧美日韩一区二区免费在线观看| 国产资源在线播放| 亚洲第一精品自拍| 国产95亚洲| 国产精品久久久久久久久久| 18成人免费观看视频| 97se亚洲综合| 色综合久久天天| 又黄又爽在线观看| 亚洲国产免费| 最新国产精品久久| 91免费在线播放| 日本免费看黄色| 欧美午夜影院一区| av午夜在线观看| 欧美国产日韩一区二区三区| 成人影院在线| 亚洲高清不卡一区| 91在线一区二区三区| 伊大人久久香线焦宗合一75大| 欧美色图天堂网| av在线一区不卡| 国产精品久久久久久久久久久不卡 | 国产香蕉一区二区三区| 色综合男人天堂| 999精品视频| 亚洲国产精品999| 亚洲国产中文在线| 国产精品毛片va一区二区三区| 六月丁香婷婷色狠狠久久| 91在线视频观看免费| 色哟哟一区二区三区| 在线成人视屏| 91久久国产综合久久蜜月精品| 国产成人免费视频网站 | 婷婷亚洲五月| 超碰10000| 五月天国产精品| 欧美aaa视频| 91免费在线观看网站| 91香蕉视频黄| 久久夜色精品| 亚洲xxxx2d动漫1| 色综合久久中文字幕综合网| 99精品在免费线中文字幕网站一区| 国产青草视频在线观看| 亚洲欧美日韩国产综合| 色婷婷成人网| 日韩三级视频在线观看| 欧美理伦片在线播放| 欧美少妇一级片| 91国内精品野花午夜精品 | 欧美成人精品一级| 久久久影院一区二区三区| 国产精品萝li| 欧美理论影院| 欧美日韩在线不卡一区| 人在线成免费视频| 欧美这里只有精品| 国产精品88久久久久久| 亚洲人成在线观看| 国产精品扒开腿做爽爽爽软件| 99久久激情视频| 亚洲第一网站免费视频| 国自产拍偷拍福利精品免费一| 15—17女人毛片| 亚洲小视频在线观看| 老司机亚洲精品| 黄色片免费在线| 国产91精品最新在线播放| 成人三级伦理片| 国产伦精品一区二区三毛| 男人的天堂在线视频免费观看| 日韩精品中文字幕有码专区| 不卡的av在线| 欧美va在线| 日日摸天天爽天天爽视频| 每日在线更新av| www.日日操| 久久精品国产一区二区三区日韩| 亚洲风情亚aⅴ在线发布| 一区二区在线电影| 婷婷综合一区| 免费观看性欧美大片无片| av综合电影网站| 欧美日韩国产免费观看视频| 成人免费观看49www在线观看| 欧美美女被草| 天天射天天综合网| 九色精品91| 成人在线视频免费观看| 国产va免费精品观看精品| 都市激情久久综合| 超碰在线电影| 超碰人人爱人人| 日本中文字幕网址| 欧美丝袜一区二区| 成人精品福利视频| 亚洲欧美激情另类校园| 亚洲精品菠萝久久久久久久| 国产一区二区三区综合| 精品久久久亚洲| 自产国语精品视频| 久久久亚洲人| 国产综合色视频| 麻豆成人在线| 欧美一区综合| 激情图片小说一区| 亚洲综合精品伊人久久| 制服丝袜亚洲网站| 日韩av电影国产| aa日韩免费精品视频一| 日产精品久久久久久久蜜臀| 一区二区三区四区视频在线| 国产精品亚发布| 亚洲福利影片在线| 精品久久久久久最新网址| 欧美日产在线观看| 欧美精品在线一区二区三区| 亚洲成av人片在www色猫咪| 日本中文字幕一区二区视频 | 日韩大片免费观看视频播放| 欧美一级在线视频| 91精品国产91久久久久久最新 | 欧美日韩视频免费播放| 亚洲女成人图区| 欧美激情中文字幕乱码免费| 色婷婷av一区二区三区在线观看| 亚洲国产黄色片| 在线电影中文日韩| 欧美性受xxxx黑人猛交| 正在播放国产精品| 黄色毛片av| 免费看的国产视频网站| 米奇777四色精品人人爽| av中文在线资源库| 羞羞答答一区二区| 在线成人av| 国产成人一区二区精品非洲| 中文字幕制服丝袜成人av| 欧美日韩美少妇| 中文字幕在线看视频国产欧美在线看完整| 91亚洲精品久久久| 亚洲一区精彩视频| 亚洲黄色中文字幕| 国产免费拔擦拔擦8x在线播放| 黄色精品在线看| 久久久噜噜噜| 国产精品极品国产中出| 色网站免费在线观看| 日本精品www| 99久久久久国产精品免费| 伊人久久久久久久久久久| 亚洲成av人片在线观看| 国产91精品一区二区麻豆网站 | 国产成人调教视频在线观看 | 欧美老肥妇做.爰bbww| 97久久超碰国产精品电影|