摘要:在這裏我先把我整理的數據集放出來吧,完整 GitHub 鏈接爲:https://github.com/Python3WebSpider/DeepLearningSlideCaptcha,我標註了 200 多張圖片,然後處理了 xml 文件,變成訓練 YOLO 模型需要的數據格式,驗證碼圖片和標註結果見 data/captcha 文件夾。本篇文章我們介紹了使用深度學習識別滑動驗證碼缺口的方法,包括標註、訓練、測試等環節都進行了闡述。

作者:崔慶才

來源:公衆號「崔慶才丨靜覓」

我們使用華爲雲 ModelArts 輕鬆完成了滑動驗證碼缺口的識別。但是那種實現方案依賴於現有服務,是華爲雲提供的深度學習平臺所搭建的識別模型,其實其內部是用的深度學習的某種目標檢測算法實現的,如果利用平臺的話,我們無需去申請 GPU、無需去了解其內部的基本原理究竟是怎麼回事,它提供了一系列標註、訓練、部署的流程。

但用上述方法是有一定的弊端的,比如使用會一直收費,另外不好調優、不好更好地定製自己的一些需求等等。所以這裏再發一篇文章來介紹一下直接使用 Python 的深度學習模型來實現滑動驗證碼缺口識別的方法。

效果

目前可以做到只需要幾百張缺口標註圖片即可訓練出精度高的識別模型,並且可擴展修改爲其他任何樣式的缺口識別,識別效果樣例:

樣例

只需要給模型輸入一張帶缺口的驗證碼圖片,模型就能輸出缺口的輪廓和邊界信息。

感興趣的可以繼續向下看具體的實現流程。

基礎瞭解

缺口識別屬於目標檢測問題,關於什麼是目標檢測這裏就不再贅述了,可以參考之前寫的那篇文章。

當前做目標檢測的算法主要有兩種路子,有一階段式和兩階段式,英文叫做 One stage 和 Two stage,簡述如下:

•Two Stage:算法首先生成一系列目標所在位置的候選框,然後再對這些框選出來的結果進行樣本分類,即先找出來在哪,然後再分出來是啥,俗話說叫「看兩眼」,這種算法有 R-CNN、Fast R-CNN、Faster R-CNN 等,這些算法架構相對複雜,但準確率上有優勢。•One Stage:不需要產生候選框,直接將目標定位和分類的問題轉化爲迴歸問題,俗話說叫「看一眼」,這種算法有 YOLO、SSD,這些算法雖然準確率上不及 Two stage,但架構相對簡單,檢測速度更快。

所以這次我們選用 One Stage 的有代表性的目標檢測算法 YOLO 來實現滑動驗證碼缺口的識別。

YOLO,英文全稱叫做 You Only Look Once,取了它們的首字母就構成了算法名,

目前 YOLO 算法最新的版本是 V3 版本,這裏算法的具體流程我們就不過多介紹了,感興趣的可以搜一下相關資料瞭解下,另外也可以瞭解下 YOLO V1-V3 版本的不同和改進之處,這裏列幾個參考鏈接。

•YOLO V3 論文:https://pjreddie.com/media/files/papers/YOLOv3.pdf•YOLO V3 介紹:https://zhuanlan.zhihu.com/p/34997279•YOLO V1-V3 對比介紹:https://www.cnblogs.com/makefile/p/yolov3.html

數據準備

迴歸我們本節的主題,我們要做的是缺口的位置識別,那麼第一步應該做什麼呢?

我們的目標是要訓練深度學習模型,訓練模型,那我們總得需要讓模型知道要學點什麼東西吧,這次我們做缺口識別,那麼我們需要讓模型學的就是這個缺口在哪裏。由於一張驗證碼圖片只有一個缺口,要分類就是一類,所以我們只需要找到缺口位置就行了。

好,那模型要學缺口在哪裏,那我們就得提供點樣本數據讓模型來學習纔行。數據怎樣的呢?那數據就得有帶缺口的驗證碼圖片以及我們自己標註的缺口位置。只有把這兩部分都告訴模型,模型才能去學習。等模型學好了,等我們再給個新的驗證碼,那就能檢測出缺口在哪裏了,這就是一個成功的模型。

OK,那我們就開始準備數據和缺口標註結果吧。

數據這裏用的是網易盾的驗證碼,驗證碼圖片可以自行收集,寫個腳本批量保存下來就行。標註的工具可以使用 LabelImg,GitHub 鏈接爲:https://github.com/tzutalin/labelImg,利用它我們可以方便地進行檢測目標位置的標註和類別的標註,如這裏驗證碼和標註示例如下:

標註效果

標註完了會生成一系列 xml 文件,你需要解析 xml 文件把位置的座標和類別等處理一下,轉成訓練模型需要的數據。

在這裏我先把我整理的數據集放出來吧,完整 GitHub 鏈接爲:https://github.com/Python3WebSpider/DeepLearningSlideCaptcha,我標註了 200 多張圖片,然後處理了 xml 文件,變成訓練 YOLO 模型需要的數據格式,驗證碼圖片和標註結果見 data/captcha 文件夾。

如果要訓練自己的數據,數據格式準備見:https://github.com/eriklindernoren/PyTorch-YOLOv3#train-on-custom-dataset。

初始化

上一步我已經把標註好的數據處理好了,可以直接拿來訓練了。

由於 YOLO 模型相對比較複雜,所以這個項目我就直接基於開源的 PyTorch-YOLOV3 項目來修改了,模型使用的深度學習框架爲 PyTorch,具體的 YOLO V3 模型的實現這裏不再闡述了。

另外推薦使用 GPU 訓練,不然拿 CPU 直接訓練速度很慢。我的 GPU 是 P100,幾乎十幾秒就訓練完一輪。

下面就直接把代碼克隆下來吧。

由於本項目我把訓練好的模型也放上去了,使用了 Git LFS,所以克隆時間較長,克隆命令如下:

git clone https://github.com/Python3WebSpider/DeepLearningSlideCaptcha.git

如果想加速克隆,暫時先跳過大文件模型下載,可以執行命令:

GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/Python3WebSpider/DeepLearningSlideCaptcha.git

環境安裝

代碼克隆下載之後,我們還需要下載一些預訓練模型。

YOLOV3 的訓練要加載預訓練模型纔能有不錯的訓練效果,預訓練模型下載命令如下:

bash prepare.sh

執行這個腳本,就能下載 YOLO V3 模型的一些權重文件,包括 yolov3 和 weights 還有 darknet 的 weights,在訓練之前我們需要用這些權重文件初始化 YOLO V3 模型。

注意:Windows 下建議使用 Git Bash 來運行上述命令。

另外還需要安裝一些必須的庫,如 PyTorch、TensorBoard 等,建議使用 Python 虛擬環境,運行命令如下:

pip3 install -r requirements.txt

這些庫都安裝好了之後,就可以開始訓練了。

訓練

本項目已經提供了標註好的數據集,在 data/captcha,可以直接使用。

當前數據訓練腳本:

bash train.sh

實測 P100 訓練時長約 15 秒一個 epoch,大約幾分鐘即可訓練出較好效果。

訓練差不多了,我們可以使用 TensorBoard 來看看 loss 和 mAP 的變化,運行 TensorBoard:

tensorboard --logdir='logs' --port=6006 --host 0.0.0.0

loss_1 變化如下:

loss 變化

val_mAP 變化如下:

mAP 變化

可以看到 loss 從最初的非常高下降到了很低,準確率也逐漸接近 100%。

另外訓練過程中還能看到如下的輸出結果:

---- [Epoch 99/100, Batch 27/29] ----

+------------+--------------+--------------+--------------+

| Metrics | YOLO Layer 0 | YOLO Layer 1 | YOLO Layer 2 |

+------------+--------------+--------------+--------------+

| grid_size | 14 | 28 | 56 |

| loss | 0.028268 | 0.046053 | 0.043745 |

| x | 0.002108 | 0.005267 | 0.008111 |

| y | 0.004561 | 0.002016 | 0.009047 |

| w | 0.001284 | 0.004618 | 0.000207 |

| h | 0.000594 | 0.000528 | 0.000946 |

| conf | 0.019700 | 0.033624 | 0.025432 |

| cls | 0.000022 | 0.000001 | 0.000002 |

| cls_acc | 100.00% | 100.00% | 100.00% |

| recall50 | 1.000000 | 1.000000 | 1.000000 |

| recall75 | 1.000000 | 1.000000 | 1.000000 |

| precision | 1.000000 | 0.800000 | 0.666667 |

| conf_obj | 0.994271 | 0.999249 | 0.997762 |

| conf_noobj | 0.000126 | 0.000158 | 0.000140 |

+------------+--------------+--------------+--------------+

Total loss 0.11806630343198776

這裏顯示了訓練過程中各個指標的變化情況,如 loss、recall、precision、confidence 等,分別代表訓練過程的損失(越小越好)、召回率(能識別出的結果佔應該識別出結果的比例,越高越好)、精確率(識別出的結果中正確的比率,越高越好)、置信度(模型有把握識別對的概率,越高越好),可以作爲參考。

測試

訓練完畢之後會在 checkpoints 文件夾生成 pth 文件,可直接使用模型來預測生成標註結果。

如果你沒有訓練自己的模型的話,這裏我已經把訓練好的模型放上去了,可以直接使用我訓練好的模型來測試。如之前跳過了 Git LFS 文件下載,則可以使用如下命令下載 Git LFS 文件:

git lfs pull

此時 checkpoints 文件夾會生成訓練好的 pth 文件。

測試腳本:

sh detect.sh

該腳本會讀取 captcha 下的 test 文件夾所有圖片,並將處理後的結果輸出到 result 文件夾。

運行結果樣例:

Performing object detection:

+ Batch 0, Inference Time: 0:00:00.044223

+ Batch 1, Inference Time: 0:00:00.028566

+ Batch 2, Inference Time: 0:00:00.029764

+ Batch 3, Inference Time: 0:00:00.032430

+ Batch 4, Inference Time: 0:00:00.033373

+ Batch 5, Inference Time: 0:00:00.027861

+ Batch 6, Inference Time: 0:00:00.031444

+ Batch 7, Inference Time: 0:00:00.032110

+ Batch 8, Inference Time: 0:00:00.029131


Saving images:

(0) Image: 'data/captcha/test/captcha_4497.png'

+ Label: target, Conf: 0.99999

(1) Image: 'data/captcha/test/captcha_4498.png'

+ Label: target, Conf: 0.99999

(2) Image: 'data/captcha/test/captcha_4499.png'

+ Label: target, Conf: 0.99997

(3) Image: 'data/captcha/test/captcha_4500.png'

+ Label: target, Conf: 0.99999

(4) Image: 'data/captcha/test/captcha_4501.png'

+ Label: target, Conf: 0.99997

(5) Image: 'data/captcha/test/captcha_4502.png'

+ Label: target, Conf: 0.99999

(6) Image: 'data/captcha/test/captcha_4503.png'

+ Label: target, Conf: 0.99997

(7) Image: 'data/captcha/test/captcha_4504.png'

+ Label: target, Conf: 0.99998

(8) Image: 'data/captcha/test/captcha_4505.png'

+ Label: target, Conf: 0.99998

拿幾個樣例結果看下:

這裏我們可以看到,利用訓練好的模型我們就成功識別出缺口的位置了,另外程序還會打印輸出這個邊框的中心點和寬高信息。

有了這個邊界信息,我們再利用某些手段拖動滑塊即可通過驗證了。本節不再展開講解。

總結

本篇文章我們介紹了使用深度學習識別滑動驗證碼缺口的方法,包括標註、訓練、測試等環節都進行了闡述。

GitHub 代碼:https://github.com/Python3WebSpider/DeepLearningSlideCaptcha。

歡迎 Star、Folk,如果遇到問題,可以在 GitHub Issue 留言。

好文和朋友一起看~

相關文章