項目源地址:github.com/nickliqian/… 歡迎你們star和fork~html
use CNN recognize captcha by tensorflow.
本項目針對字符型圖片驗證碼,使用tensorflow實現卷積神經網絡,進行驗證碼識別。
項目封裝了比較通用的校驗、訓練、驗證、識別、API模塊,極大的減小了識別字符型驗證碼花費的時間和精力。python
項目已經幫助不少同窗高效完成了驗證碼識別任務。 若是你在使用過程當中出現了bug和作了良好的改進,歡迎提出issue和PR,做者會盡快回復,但願能和你共同完善項目。nginx
若是你須要識別點選、拖拽類驗證碼,或者有目標檢測需求,也能夠參考這個項目nickliqian/darknet_captcha。git
2018.11.12 - 第一版Readme.md
2018.11.21 - 加入關於驗證碼識別的一些說明
2018.11.24 - 優化校驗數據集圖片的規則
2018.11.26 - 新增train_model_v2.py
文件,訓練過程當中同時輸出訓練集和驗證集的準確率
2018.12.06 - 新增多模型部署支持,修復若干bug
2018.12.08 - 優化模型識別速度,支持api壓力測試和統計耗時
2018.02.19 - 新增一種準確率計算方式github
1 項目介紹web
2 如何使用算法
3 說明json
4 已知BUGflask
驗證碼識別大可能是爬蟲會遇到的問題,也能夠做爲圖像識別的入門案例。目前一般使用以下幾種方法:api
方法名稱 | 相關要點 |
---|---|
tesseract | 僅適合識別沒有干擾和扭曲的圖片,訓練起來很麻煩 |
其餘開源識別庫 | 不夠通用,識別率未知 |
付費OCR API | 需求量大的情造成本很高 |
圖像處理+機器學習分類算法 | 涉及多種技術,學習成本高,且不通用 |
卷積神經網絡 | 必定的學習成本,算法適用於多類驗證碼 |
這裏說一下使用傳統的圖像處理和機器學習算法,涉及多種技術:
使用這類方法對使用者的要求較高,且因爲圖片的變化類型較多,處理的方法不夠通用,常常花費不少時間去調整處理步驟和相關算法。
而使用卷積神經網絡,只須要經過簡單的前處理,就能夠實現大部分靜態字符型驗證碼的端到端識別,效果很好,通用性很高。
這裏列出目前經常使用的驗證碼生成庫:
參考:Java驗證全家桶
序號 | 文件名稱 | 說明 |
---|---|---|
1 | sample.py | 配置文件 |
2 | sample文件夾 | 存放數據集 |
3 | model文件夾 | 存放模型文件 |
序號 | 文件名稱 | 說明 |
---|---|---|
1 | verify_and_split_data.py | 驗證數據集和拆分數據爲訓練集和測試集 |
2 | train_model.py | 訓練模型 |
3 | train_model_v2.py | 訓練模型,訓練過程當中同時輸出訓練集和驗證集的準確率,推薦使用此種方式訓練 |
4 | test_batch.py | 批量驗證 |
5 | gen_image/gen_sample_by_captcha.py | 生成驗證碼的腳本 |
6 | gen_image/collect_labels.py | 用於統計驗證碼標籤(經常使用於中文驗證碼) |
序號 | 文件名稱 | 說明 |
---|---|---|
1 | recognition_object.py | 封裝好的識別類 |
2 | recognize_api.py | 使用flask寫的提供在線識別功能的接口 |
3 | recognize_online.py | 使用接口識別的例子 |
4 | recognize_local.py | 測試本地圖片的例子 |
5 | recognize_time_test.py | 壓力測試識別耗時和請求響應耗時 |
pip3 install tensorflow==1.7.0 flask==1.0.2 requests==2.19.1 Pillow==4.3.0 matplotlib==2.1.0 easydict==1.8
複製代碼
序號 | 層級 |
---|---|
輸入 | input |
1 | 卷積層 + 池化層 + 降採樣層 + ReLU |
2 | 卷積層 + 池化層 + 降採樣層 + ReLU |
3 | 卷積層 + 池化層 + 降採樣層 + ReLU |
4 | 全鏈接 + 降採樣層 + Relu |
5 | 全鏈接 + softmax |
輸出 | output |
原始數據集能夠存放在./sample/origin
目錄中
爲了便於處理,圖片最好以2e8j_17322d3d4226f0b5c5a71d797d2ba7f7.jpg
格式命名(標籤_序列號.後綴)
若是你沒有訓練集,你可使用gen_sample_by_captcha.py
文件生成訓練集文件。 生成以前你須要修改相關配置(路徑、文件後綴、字符集等)。
建立一個新項目前,須要自行修改相關配置文件
圖片文件夾
sample_conf.origin_image_dir = "./sample/origin/" # 原始文件
sample_conf.train_image_dir = "./sample/train/" # 訓練集
sample_conf.test_image_dir = "./sample/test/" # 測試集
sample_conf.api_image_dir = "./sample/api/" # api接收的圖片儲存路徑
sample_conf.online_image_dir = "./sample/online/" # 從驗證碼url獲取的圖片的儲存路徑
# 模型文件夾
sample_conf.model_save_dir = "./model/" # 訓練好的模型儲存路徑
# 圖片相關參數
sample_conf.image_width = 80 # 圖片寬度
sample_conf.image_height = 40 # 圖片高度
sample_conf.max_captcha = 4 # 驗證碼字符個數
sample_conf.image_suffix = "jpg" # 圖片文件後綴
# 驗證碼字符相關參數
# 驗證碼識別結果類別
sample_conf.char_set = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# 驗證碼遠程連接
sample_conf.remote_url = "https://www.xxxxx.com/getImg"
複製代碼
具體配置的做用會在使用相關腳本的過程當中提到 關於驗證碼識別結果類別
,假設你的樣本是中文驗證碼,你可使用gen_image/collect_labels.py
腳本進行標籤的統計。 會生成文件gen_image/labels.json
存放全部標籤,在配置文件中設置use_labels_json_file = True
開啓讀取labels.json
內容做爲結果類別
。
此功能會校驗原始圖片集的尺寸和測試圖片是否能打開,並按照19:1的比例拆分出訓練集和測試集。
因此須要分別建立和指定三個文件夾:origin,train,test用於存放相關文件。
也能夠修改成不一樣的目錄,可是最好修改成絕對路徑。
文件夾建立好以後,執行如下命令便可:
python3 verify_and_split_data.py
複製代碼
通常會有相似下面的提示
Total image count: 10094
====如下4張圖片有異常====
[第2123張圖片] [325.txt] [文件後綴不正確]
[第3515張圖片] [_15355300508855503.gif] [圖片標籤異常]
[第6413張圖片] [qwer_15355300721958663.gif] [圖片尺寸異常爲:(50, 50)]
[第9437張圖片] [abcd_15355300466073782.gif] [圖片沒法正常打開]
========end
開始分離原始圖片集爲:測試集(5%)和訓練集(95%)
共分配10090張圖片到訓練集和測試集,其中4張爲異常留在原始目錄
測試集數量爲:504
訓練集數量爲:9586
複製代碼
建立好訓練集和測試集以後,就能夠開始訓練模型了。
訓練的過程當中會輸出日誌,日誌展現當前的訓練輪數、準確率和loss。
此時的準確率是訓練集圖片的準確率,表明訓練集的圖片識別狀況
例如:
第10次訓練 >>> 準確率爲 1.0 >>> loss 0.0019966468680649996
複製代碼
這裏不具體介紹tensorflow安裝相關問題,直奔主題。
確保圖片相關參數和目錄設置正確後,執行如下命令開始訓練:
python3 train_model.py
複製代碼
也能夠調用類開始訓練或執行一次簡單的識別演示
from train_model import TrainModel
from sample import sample_conf
# 導入配置
train_image_dir = sample_conf["train_image_dir"]
char_set = sample_conf["char_set"]
model_save_dir = sample_conf["model_save_dir"]
# verify參數默認爲False,當verify=True則會在訓練前校驗全部圖片格式時候爲指定的後綴
tm = TrainModel(train_image_dir, char_set, model_save_dir, verify=False)
tm.train_cnn() # 執行訓練
tm.recognize_captcha() # 識別演示
複製代碼
2018.11.26 新增train_model_v2.py
文件
一樣是訓練模型的腳本,在訓練過程當中增長了識別測試集的並輸出準確率的過程,例如:
第480次訓練 >>> [訓練集] 準確率爲 1.0 >>> loss 0.0017373242881149054
>>> [驗證集] 準確率爲 0.9500000095367432 >>> loss 0.0017373242881149054
驗證集準確率達到99%,保存模型成功
複製代碼
因爲訓練集中經常不包含全部的樣本特徵,因此會出現訓練集準確率是100%而測試集準確率不足100%的狀況,此時提高準確率的一個解決方案是增長正確標記後的負樣本。
使用測試集的圖片進行驗證,輸出準確率。
python3 test_batch.py
複製代碼
也能夠調用類進行驗證
from test_batch import TestBatch
from sample import sample_conf
# 導入配置
test_image_dir = sample_conf["test_image_dir"]
model_save_dir = sample_conf["model_save_dir"]
char_set = sample_conf["char_set"]
total = 100 # 驗證的圖片總量
tb = TestBatch(test_image_dir, char_set, model_save_dir, total)
tb.test_batch() # 開始驗證
複製代碼
項目已經封裝好加載模型和識別圖片的類,啓動web server後調用接口就可使用識別服務。
啓動web server
python3 recognize_api.py
複製代碼
接口url爲http://127.0.0.1:6000/b
使用requests調用接口:
url = "http://127.0.0.1:6000/b"
files = {'image_file': (image_file_name, open('captcha.jpg', 'rb'), 'application')}
r = requests.post(url=url, files=files)
複製代碼
返回的結果是一個json:
{
'time': '1542017705.9152594',
'value': 'jsp1',
}
複製代碼
文件recognize_online.py
是使用接口在線識別的例子
部署的時候,把recognize_api.py
文件的最後一行修改成以下內容:
app.run(host='0.0.0.0',port=5000,debug=False)
複製代碼
而後開啓端口訪問權限,就能夠經過外網訪問了。
另外爲了開啓多進程處理請求,可使用uwsgi+nginx組合進行部署。
這部分能夠參考:Flask部署選擇
部署多個模型: 在recognize_api.py
文件彙總,新建一個Recognizer對象;
並參照原有up_image
函數編寫的路由和識別邏輯。
Q = Recognizer(image_height, image_width, max_captcha, char_set, model_save_dir)
複製代碼
注意修改這一行:
value = Q.rec_image(img)
複製代碼
提供了一個簡易的壓力測試腳本,能夠統計api運行過程當中識別耗時和請求耗時的相關數據,不過圖須要本身用Excel拉出來。
打開文件recognize_time_test.py
,修改main
函數下的test_file
路徑,這裏會重複使用一張圖片來訪問是被接口。
最後數據會儲存在test.csv文件中。
使用以下命令運行:
python3 recognize_time_test.py
----輸出以下
2938,5150,13:30:25,總耗時:29ms,識別:15ms,請求:14ms
2939,5150,13:30:25,總耗時:41ms,識別:21ms,請求:20ms
2940,5150,13:30:25,總耗時:47ms,識別:16ms,請求:31ms
複製代碼
這裏對一個模型進行了兩萬次測試後,一組數據test.csv。 把test.csv使用箱線圖進行分析後能夠看到:
2018-12-01 00:35:15.106333: W T:\src\github\tensorflow\tensorflow\core\framework\op_kernel.cc:1273] OP_REQUIRES failed at save_restore_tensor.cc:170 : Invalid argument: Unsuccessful TensorSliceReader constructor: Failed to get matching files on ./model/: Not found: FindFirstFile failed for: ./model : ϵͳ�Ҳ���ָ����·����
; No such process
......
tensorflow.python.framework.errors_impl.InvalidArgumentError: Unsuccessful TensorSliceReader constructor: Failed to get matching files on ./model/: Not found: FindFirstFile failed for: ./model : ϵͳ\udcd5Ҳ\udcbb\udcb5\udcbdָ\udcb6\udca8\udcb5\udcc4·\udcbe\udcb6\udca1\udca3
; No such process
[[Node: save/RestoreV2 = RestoreV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save/Const_0_0, save/RestoreV2/tensor_names, save/RestoreV2/shape_and_slices)]]
複製代碼
由pycharm默認設置了工做空間,致使讀取相對路徑的model文件夾出錯。 解決辦法:編輯運行配置,設置工做空間爲項目目錄便可。
FileNotFoundError: [Errno 2] No such file or directory: 'xxxxxx'
目錄下有文件夾不存在,在指定目錄建立好文件夾便可。
api程序在運行過程當中內存越佔越大
結果查閱資料:連接
在迭代循環時,不能再包含任何張量的計算表達式,否在會內存溢出。 將張量的計算表達式放到init初始化執行後,識別速度獲得極大的提高。
加載多個模型報錯 緣由是兩個Recognizer對象都使用了默認的Graph。 解決辦法是在建立對象的時候不使用默認Graph,新建graph,這樣每一個Recognizer都使用不一樣的graph,就不會衝突了。
Flask程序的併發運行 暫缺,可使用flask+uwsgi實現