Python驗證碼識別
阿新 • • 發佈:2020-06-02
**專案地址:https://github.com/kerlomz/captcha_trainer**
**編譯版下載地址:** https://github.com/kerlomz/captcha_trainer/releases/tag/v1.0
注意:若使用雲伺服器 (Windows Server版) 遇到閃退,請按照步驟:我的電腦——屬性——管理——新增角色和功能——勾選**桌面體驗**,點選安裝,安裝之後重啟即可。
### 2020/06/01編外:
想必各位只是偶然間搜到這篇文章,網上文章參差不齊,標題黨很多,能跑起來的開原始碼很少,對於能跑起來的程式碼,也經常遇到以下問題如:記憶體洩漏,網路引數寫死導致更換訓練集報錯,網路跑其他樣本識別率低,沒有呼叫示例等等。
**再往下看之前,我可以向你們保證,它絕對會是你所見過的所有驗證碼有關的文章中最實用,最接近生產水平的。**
1. **對小白:** 你可以不需要動手寫任何一行程式碼。
2. **對小企業:** 它的可用性和穩定性是經得起考驗的,在效能上也是同行領先的,可以放心入坑。
因為小編打算轉行了,離開這個行業之前總要留下點什麼證明自己來過,總有人和我說的這個部署不會呼叫,可能你們想要的是一行pip就搞定環境的,所以今天給你們安排了麻瓜OCR(MuggleOCR)。
[https://pypi.org/project/muggle-ocr](https://pypi.org/project/muggle-ocr)
它整合了簡單驗證碼識別通用模型+印刷文字通用識別,並且支援呼叫本文框架訓練的模型。呼叫只需要三行核心程式碼:
```
import time
# STEP 1
import muggle_ocr
import os
# STEP 2
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.OCR)
root_dir = r"./imgs"
for i in os.listdir(root_dir):
n = os.path.join(root_dir, i)
with open(n, "rb") as f:
b = f.read()
st = time.time()
# STEP 3
text = sdk.predict(image_bytes=b)
print(i, text, time.time() - st)
```
這真的很簡單,應付一般的文字識別和驗證碼都足夠了。(文字識別過幾天會更新一下新模型,畢竟0601模型就跑了半天。
## 1. 前言
本專案適用於Python3.7,GPU>=NVIDIA GTX1050Ti,原master分支新增了GUI配置介面以及編譯版本了,是時候寫一篇新的文章了。
**長話短說,開門見山,**網路上現有的程式碼以教學研究為主,本專案是為實用主義者定製的,只要基本的環境安裝常識,便可很好的訓練出期望的模型,重定義幾個簡單的引數任何人都能使用深度學習技術訓練一個商業化成品。
筆者選用的時下最為流行的CNN+BLSTM+CTC(CRNN)進行端到端的不定長驗證碼識別,程式碼中預留了CNNX(搜不到因為是小編自己拼湊的)/MobileNet/DenseNet121/ResNet50等選項,可以在配置介面中直接選用。首先,介紹個大概吧。
![main.png](https://upload-images.jianshu.io/upload_images/10905998-52b0df7590a8d304?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
| 網格結構 | predict-CPU | predict-GPU | 模型大小 |
| -------------------- | ----------- | ----------- | -------- |
| CNN5+Bi-LSTM+H64+CTC | 15ms | 8ms | 2mb |
| CNN5+CrossEntropy | 8ms | 2ms | 1.5mb |
H16/H64指的是Bi-LSTM的隱藏神經元個數UnitsNum,所以本專案使用GPU訓練,使用CPU進行預測。預測服務部署專案原始碼請移步此處:**https://github.com/kerlomz/captcha_platform**
部署專案的編譯版下載地址:**https://github.com/kerlomz/captcha_platform/releases**
## 2.環境依賴:
**花了超長篇幅介紹了訓練環境的基本搭建,主要是給尚未入門的讀者看的,老鳥們隨便跳過,若不希望在環境上面浪費時間的,歡迎使用編譯版,可在文章開頭找到下載地址。**
關於CUDA和cuDNN版本的問題,不少人很糾結,這裡就列出官方通過pip安裝的TensorFlow的版本對應表:
### Linux
| Version | Python version | Compiler | Build tools | cuDNN | CUDA |
| --------------------- | -------------- | -------- | ------------ | ----- | ---- |
| tensorflow_gpu-1.14.0 | **3.7** | GCC 4.8 | Bazel 0.15.0 | 7.6 | 9 |
### Windows
| Version | Python version | Compiler | Build tools | cuDNN | CUDA |
| --------------------- | -------------- | ------------------ | ------------ | ----- | ---- |
| tensorflow_gpu-1.14.0 | **3.7** | MSVC 2015 update 3 | Bazel 0.15.0 | 7.6 | 10 |
如果希望使用上面對應之外的搭配的CUDA和cuDNN,可以自行編譯TensorFlow,或者去Github上搜索```TensorFlow Wheel```找到第三方編譯的對應版本的whl安裝包。提前預警,若是自己編譯將會苦難重重,坑很多,這裡就不展開了。
### 2.1 本專案環境依賴
**目前在以下主流作業系統平臺均測試通過:**
| 作業系統 | 最低支援版本 |
| -------- | ------------ |
| Ubuntu | 16.04 |
| Windows | 7 SP1 |
| MacOS | N/A |
**本訓練專案主要的環境依賴清單如下**
| 依賴 | 最低支援版本 |
| -------------- | ------------ |
| Python | **3.7** |
| TensorFlow-GPU | 1.14.0 |
| Opencv-Python | 4.1.2.30 |
| Numpy | 1.16.0 |
| Pillow | 4.3.0 |
| PyYaml | 3.13 |
| tqdm | N/A |
#### 2.1.1 Ubuntu 16.04 下的 Python 3.7
**1)先安裝Python環境(有Python 3.7環境的可以忽略)**
```bash
sudo apt-get install openssl
sudo apt-get install libssl-dev
sudo apt-get install libc6-dev gcc
sudo apt-get install -y make build-essential zlib1g-dev libbz2-dev libreadline-dev $ libsqlite3-dev wget curl llvm tk-dev
wget https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz
tar -vxf Python-3.7.6.tar.xz
cd Python-3.7.6
./configure --prefix=/usr/local --enable-shared
make -j8
sudo make install -j8
```
經過上面指令就安裝好Python3.7環境了,如果提示找不到```libpython3.7m.so.1.0```就到/usr/local/lib路徑下將該檔案複製一份到/usr/lib和/usr/lib64路徑下。
**2)安裝相關依賴(這一步Windows和Linux通用)**
可以直接在專案路徑下執行```pip3 install -r requirements.txt```安裝所有依賴,注意這一步是安裝在全域性Python環境下的,強烈建議使用虛擬環境進行專案間的環境隔離,如**Virtualenv**或**Anaconda**等等。
我一般使用的是Virtualenv,有修改程式碼需要的,建議安裝PyCharm作為Python IDE
```bash
virtualenv -p /usr/bin/python3 venv # venv is the name of the virtual environment.
cd venv/ # venv is the name of the virtual environment.
source bin/activate # to activate the current virtual environment.
cd captcha_trainer # captcha_trainer is the project path.
pip3 install -r requirements.txt
```
#### 2.1.2 Ubuntu 16.04 下的 CUDA/cuDNN
網上看到過很多教程,我自己也部署過很多次,Ubuntu 16.04遇到的坑還是比較少的。14.04支援就沒那麼好,如果主機板不支援關閉SecureBoot的話千萬不要安裝Desktop版,因為安裝好之後一定會無限迴圈在登陸介面無法進入桌面。
網上教程說要加驅動黑名單什麼的我直接跳過了,親測沒那個必要。就簡單的幾步:
**1. 下載好安裝包**
注意下載runfile型別的安裝包,deb安裝會自動安裝預設驅動,極有可能導致登陸迴圈
NVIDIA 驅動下載:https://www.geforce.cn/drivers
CUDA 下載地址:https://developer.nvidia.com/cuda-downloads
cuDNN 下載地址:https://developer.nvidia.com/cudnn (需要註冊NVIDIA賬號且登陸,下載deb安裝包)
**2. 關閉圖形介面**
Ctrl+alt+F1進入字元介面,關閉圖形介面
```
sudo service lightdm stop
```
**3. 安裝Nvidia Driver**
命令中的版本自己對應下載的版本改,在上面的下載地址根據自己的顯示卡型號下載最新版,切記是runfile格式的安裝包。
```
sudo chmod a+x NVIDIA-Linux-x86_64-384.90.run //獲取執行許可權
sudo ./NVIDIA-Linux-x86_64-384.90.run –no-x-check –no-nouveau-check –no-opengl-files //安裝驅動
```
安裝成功以後使用以下命令驗證,如果顯示顯示卡資訊則表示安裝成功
```bash
nvidia-smi
```
**4. 安裝CUDA**
1)先安裝一些系統依賴庫
```
sudo apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev
```
2) 執行安裝程式,按指示無腦繼續就好了,**如果提示是否安裝驅動選不安裝。**
```
sudo sh cuda_9.0.176_384.81_linux.run
```
安裝完如果環境變數沒配上去,就寫到 ~/.bashrc 檔案的尾部
```
export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
```
然後在終端執行 ```sudo ldconfig```更新,安裝完畢就可以重啟機器重啟圖形介面了。
```
sudo service lightdm start
```
#### 2.1.3 Windows 系統
在Windows其實簡單很多,只要到官網下載安裝包無腦安裝就可以了,下載連線同Ubuntu,先安裝Python,顯示卡驅動,CUDA,然後下載對應的cuDNN替換到對應路徑即可。
## 3 使用
**在訓練之前,有不少群友經常問我“訓練4位數英文數字需要多少樣本?”諸如此類的問題,我這裡統一做個回覆,樣本數量主要是看樣本的特徵複雜度而定。**
**這裡可以提供幾個參考依據:** 是否變形?是否旋轉?是否有複雜背景干擾?是否多種字型?字符集(分類數)多大?位數(標籤數)多少?
1. 一般簡單的**幾百**個樣本(需要自行調整 **驗證集大小** 和 **驗證批次大小** )即可。
2. 稍微複雜的**幾千**個樣本一般都能搞定。
3. 特別複雜的**幾萬**樣本起。
4. 中文這種幾千個分類的一般**十萬**起。
**注:只准備一百個不到樣本的親們,千萬不要嘗試訓練測試,因為根本跑不起來。**
入手的第一步環境搭建好了,那就是準備跑程式碼了,還是有幾個必要的條件,巧婦難為無米之炊,首先,既然是訓練,要先有訓練集,有一個新手嚐鮮的訓練集,是mnist手寫識別的例子,可以在騰訊雲下載:https://share.weiyun.com/5pzGF4V
,現在萬事俱備,只欠東風。
### 3.1 定義一個模型
本專案基於引數化配置,不需要改動任何程式碼,可以通過視覺化介面操作訓練幾乎任何字元型圖片驗證碼。訓練框架介面可以大致劃分為幾個部分:
1. Neural Network - 神經網路區
![0.png](https://upload-images.jianshu.io/upload_images/10905998-ceffcc9d36b1adbd?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2. Project Configuration - 專案配置區
![1.png](https://upload-images.jianshu.io/upload_images/10905998-b2a7c8309c8190c3?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3. Sample Source - 樣本源配置區
![2.png](https://upload-images.jianshu.io/upload_images/10905998-e69de83e44688c04?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4. Training Configuration - 訓練配置區
![3.png](https://upload-images.jianshu.io/upload_images/10905998-e91f02cb88445001?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
5. Buttons - 功能控制區
![4.png](https://upload-images.jianshu.io/upload_images/10905998-90871a3946bb86e4?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**依此類推的訓練配置的步驟如下:**
1. **神經網路區** 的配置項看起來很多,對於新手來說,可以直接使用預設的配置:CNNX+GRU+CTC+C1組合(CNN前置網路+GRU+CTC+單通道)。
2. **專案配置區** 的配置項在網路選好之後配置專案名,按回車或者點選空白處確認。
3. **樣本源配置區** 的配置項用來配置樣本源的路徑,訓練樣本是根據此路徑進行打包成TFRecords格式,驗證樣本可以不指定,使用[Validation Set Num]引數隨機從訓練集總抽樣成驗證集。
4. **訓練配置區** 的配置項負責定義訓練完成的條件如:結束準確率,結束COST,結束Epochs,批次大小
5. **功能控制區** 的配置項,設定完上面步驟,先點選[Make Dataset] 打包樣本,再點選[Start Training]開始訓練。
#### 以下部分有基礎的讀者們可以瞭解一下:
如若使用CrossEntropy作為解碼器需要注意標籤數LabelNum和圖片尺寸需要滿足的關係,因為網路為多標籤而設計(一般的多標籤採用直接連線多個分類器),卷積層的輸出 outputs 經過了以下變換:
```python
Reshape([label_num, int(outputs_shape[1] / label_num)])
```
為了保證運算 int(outputs_shape[1] / label_num) 能夠取得正整數,也意味著他們之間存在某種關係,對於CNN5+Cross Entropy的網路結構,Conv2D層的步長皆為1,那麼需要保證以下關係成立:
$$
mod(\frac{輸入寬度\times輸入高度\times輸出層引數}{池化步長^{池化層數}\times標籤數})= 0
$$
所以有時候需要Resize網路輸入的Shape
| 網路 | 池化步長^池化層數 | 輸出層引數 |
| -------- | ----------------- | ---------- |
| CNN5 | 16 | 64 |
| CNNX | 8 | 64 |
| ResNet50 | 16 | 1024 |
| DenseNet | 32 | 2048 |
例如使用CNN5+CrossEntropy組合,則輸入寬度與輸入高度需要滿足:
$$
mod(\frac{輸入寬度\times輸入高度\times64}{16\times標籤數})= 0
$$
同理如果CNN5+RNN+CTC,卷積層之後的輸出經過以下變換:
```python
Reshape([-1, outputs_shape[2] * outputs_shape[3]])
```
原輸出(batch_size, outputs_shape[1], outputs_shape[2], outputs_shape[3]),RNN層的輸入輸出要求為(batch, timesteps, num_classes),為了接入RNN經過以上操作,那麼又引出一個Time Step的概念,所以timesteps的值也是 outputs_shape[1],而CTC Loss要求的輸入為 [batch_size, frames, num_labels],若是 timesteps 小於標籤數則無法計算損失,也就無法找損失函式中找到極小值,梯度何以下降。timesteps 最合理的值一般是標籤數的2倍,為了達到目的,也可以通過Resize網路輸入的Shape解決,一般情況timesteps直接關聯於圖片寬度,大多情況只要按比例放大寬度即可。
#### ExtractRegex 引數:
**注意:如果訓練集的命名格式和我提供的新手訓練集不一樣,請根據實際情況修改ExtractRegex的正則表示式。目前只支援在yaml配置檔案中直接修改,尚未提供GUI介面修改的支援。** DatasetPath 和SourcePath引數允許多個路徑,這種操作適用於需要將多種樣本訓練為一個模型,或者希望訓練一套通用泛化模型的人。
字符集Category其實大多數情況下不需要修改,一般的圖形驗證碼離不開數字和英文,而且一般來說是大小寫不敏感的,不區分大小寫,因為打碼平臺收集的訓練集質量參差不齊,有些大寫有些小寫,不如全部統一為小寫,預設ALPHANUMERIC_LOWER則會自動將大寫的轉為小寫,字符集可定製化很靈活,除了配置備註上提供的幾種型別,還可以訓練中文,自定義字符集用list表示,示例如下:
```
Category: ['常', '世', '寧', '慢', '南', '制', '根', '難']
```
如果是單標籤分類,可以配合LabelNum=1,例如:
```
Category: ["航母", "雨靴", "毛線", "安全帽", "調色盤", "海鷗", "日曆", "網球拍", ......]
```
其檔名示例:航母_1231290424123.png
如果是多標籤分類,可以配合LabelSplit=&,例如:
```
Category: ["航母", "雨靴", "毛線", "安全帽", "調色盤", "海鷗", "日曆", "網球拍", ......]
```
其檔名示例:航母&雨靴&毛線_1231290424123.png
可以自己根據收集訓練集的實際字符集使用率來定義,也可以無腦網上找3500常用字來訓練,**注意:中文字符集一般比數字英文大很多,剛開始收斂比較慢,需要更久的訓練時間,也需要更多的樣本量,請量力而行**
![QQ截圖20181204150924.png](https://upload-images.jianshu.io/upload_images/10905998-af1e97e4a4c75834?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**形如上圖的圖片能輕鬆訓練到95%以上的識別率。**
ImageWidth、ImageHeight只要和當前圖片尺寸匹配即可,其實這裡的配置主要是為了方便後面的部署智慧策略。
#### Pretreatment引數:
該引數是用來做圖片預處理的,例如形如以下的GIF動圖,
![2pc5uv_8989.gif](https://upload-images.jianshu.io/upload_images/10905998-546e39a222586a56?imageMogr2/auto-orient/strip)
可以使用ConcatFrames引數選取幀對兩幀進行水平拼接,適用於處理滾動型GIF,而閃爍型GIF可以使用BlendFrames引數進行融合。
### 3.2 開始訓練
1. 經過 採集標註樣本形如 xxx_隨機數.png
![QQ截圖20200531182034.png](https://upload-images.jianshu.io/upload_images/10905998-4424ab65cd2ea483?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2. 打包樣本
通過GUI介面的 [Make Dataset] 或者 make_dataset.py 直接打包。
**注意:使用原始碼執行本專案的功能模組需要具備一定的語言基礎,引數修改的部分和示例已預留好,儘量不修改核心類或函式的程式碼以免出現錯誤。**
按照上面的介紹,配置只要修改極少數的引數對應的值,就可以開啟正式的訓練之旅了,具體操作如下:
可以直接使用 PyCharm 的 Run,執行 trains.py,也可以在啟用Virtualenv下使用終端亦或在安裝依賴的全域性環境下執行,但本文建議全程使用GUI介面進行操作,使用GUI僅需啟動 app.py 即可。
```bash
python3 trains.py
```
剩下的就是等了,看過程,等結果。
正常開始訓練的模樣應該是這樣的:
訓練結束會在專案的out路徑下生成一個包含pb檔案的graph目錄和包含yaml檔案的model目錄,下面該到部署環節了。
### 3.3 部署
真的很有必要認真的介紹一下部署專案,比起訓練,這個部署專案傾注了筆者更多的心血,為什麼呢?
專案地址:https://github.com/kerlomz/captcha_platform
如希望將本系統集成於自己的專案中的可以參考python-sdk的使用:
[https://pypi.org/project/muggle-ocr/](https://pypi.org/project/muggle-ocr/)
該專案的核心基於 captcha_platform/sdk/pb/sdk.py 可以根據需要自行修改,抑或直接使用MuggleOCR 呼叫訓練框架生產的模型。(具體呼叫方法可點選上面連結有對應的文件介紹)
編譯版:https://github.com/kerlomz/captcha_platform/releases,使用編譯版無需安裝Python和TensorFlow環境。
#### 真的值得了解的幾點
1. 同時管理多個模型,支援模型熱拔插
2. 靈活的版本控制
3. 支援批量識別
4. 服務智慧路由策略
**首先筆者重寫了TensorFlow的Graph會話管理,設計會話池,允許同時管理多模型,實現多模型動態部署方案。**
**1)** 訓練好的 **pb模型只要放在部署專案的graph路徑下,yaml模型配置檔案放在model,** 即可被服務發現並載入。(用SDK呼叫時,兩者置於同一目錄下)
**2)** 如果需要解除安裝一個正在服務的模型,只需要在model中刪除該模型的yaml配置檔案,在graph中刪除對應的pb模型即可。
**3)** 如果需要更新一個已經服務中的模型,只需修改新版的模型yaml配置檔案的版本號高於原模型的版本號,按先放pb後放yaml的順序,服務便會自動發現新版的模型並載入使用,舊的模型將因版本低於新版模型不會被呼叫,可以按照上述的解除安裝方法解除安裝已被棄用的模型釋放記憶體。
上面的操作中無需重啟服務,完全的無縫切換
其次,一套服務想要服務於各式各樣的影象識別需求,可以定義一套策略,訓練時將所有尺寸一樣的圖片訓練成一個模型,服務根據圖片尺寸自動選擇使用哪個模型,這樣的設計使定製化和通用性共存,等積累到一定多樣的訓練集時可以將所有的訓練集合到一起訓練一個通用模型,亦可以彼此獨立,每個模型的疊加僅僅增加了少量的記憶體或視訊記憶體,網上的方案大多是不同的模型單獨部署一套服務,每個程序載入了一整套TensorFlow框架勢必是過於龐大和多餘的。
用到批量識別需求的人相對少很多這裡就不展開介紹了。但是這裡給出一個12306的例子:
```yaml
FieldParam:
CorpParams: [
{
"start_pos": [118, 0],
"interval_size": [0, 0],
"corp_num": [1, 1],
"corp_size": [60, 30]
},
{
"start_pos": [5, 40],
"interval_size": [5, 5],
"corp_num": [4, 2],
"corp_size": [66, 66]
}
]
OutputCoord: True
```
該引數可以用於大圖的裁剪組成一批小圖作為一個批次的輸入,改用法可以避免多次呼叫。
但是識別專案提供了多套可選的服務有:gRPC,Flask,Tornado,Sanic,其中Flask和Tornado提供了加密介面,類似於微信公眾號開發介面的SecretKey和AccessKey介面,感興趣的可以在demo.py中閱讀呼叫原始碼瞭解。
部署的使用可以經過package.py編譯為可執行檔案,這樣可以免去更換機器環境安裝的煩惱,部署專案安裝流程同訓練專案,專案中提供的requirements.txt已經將所需的依賴都列清楚了,強烈建議部署專案安裝cpu版TensorFlow。
**本專案部署推薦使用Tornado版,功能最齊全,效能最為穩定。**
**Linux:**
1. Tornado:
```bash
# 埠 19952
python3 tornado_server.py
```
2. Flask
```bash
# 方案1,裸啟動, 埠 19951
python flask_server.py
# 方案2,使用gunicorn,埠 5000
pip install gunicorn
gunicorn -c deploy.conf.py flask_server:app
```
3. Sanic:
```bash
# 埠 19953
python3 sanic_server.py
```
4. gRPC:
```bash
# 埠 50054
python3 grpc_server.py
```
5. 編譯版(基於Tornado)
```bash
# 前臺執行
./captcha_platform_tornado
#後臺執行
nohup ./captcha_platform_tornado &
```
**Windows:**
Windows平臺下都是通過```python3 xxx_server.py```啟動對應的服務,注意,Tornado、Flask、Sanic的效能在Windows平臺都大打折扣,gRPC是Google開源的RPC服務,有較為優越的效能。
編譯版直接執行編譯後的exe可執行檔案即可。
### 3.4 呼叫/測試
**1. Tornado服務:**
| 請求地址 | Content-Type | 引數形式 | 請求方法 |
| --------------------------------- | ---------------- | -------- | -------- |
| http://localhost:19952/captcha/v1 | application/json | JSON | POST |
**具體引數:**
| 引數名 | 必選 | 型別 | 說明 |
| ------------ | ---- | ------ | ------------------------------------------- |
| image | Yes | String | Base64 編碼 |
| model_name | No | String | 模型名,yaml配置中可繫結 |
| need_color | No | String | 顏色過濾,black/red/blue/yellow/green/white |
| output_split | No | String | 多標籤分割字元 |
請求為JSON格式,形如:{"image": "base64編碼後的影象二進位制流"}
**返回結果:**
| 引數名 | 型別 | 說明 |
| ------- | ------ | ------------------ |
| message | String | 識別結果或錯誤訊息 |
| code | String | 狀態碼 |
| success | String | 是否請求成功 |
該返回為JSON格式,形如:{"message": "xxxx", "code": 0, "success": true}
**2. Flask服務:**
| 請求地址 | Content-Type | 引數形式 | 請求方法 |
| --------------------------------- | ---------------- | -------- | -------- |
| http://localhost:19951/captcha/v1 | application/json | JSON | POST |
**請求引數和返回格式同上**
**3. Sanic服務:**
| 請求地址 | Content-Type | 引數形式 | 請求方法 |
| --------------------------------- | ---------------- | -------- | -------- |
| http://localhost:19953/captcha/v1 | application/json | JSON | POST |
**請求引數和返回格式同上**
**4. gRPC服務:**
需要安裝依賴,grpcio、grpcio_tools和對應的grpc.proto檔案,可以直接從專案中的示例程式碼demo.py中提取。
```cmd
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./grpc.proto
```
grpcio、grpcio_tools 是根據 grpc.proto 使用上述命令生成的。
```python
class GoogleRPC(object):
def __init__(self, host: str):
self._url = '{}:50054'.format(host)
self.true_count = 0
self.total_count = 0
def request(self, image, model_type=None, model_site=None):
import grpc
import grpc_pb2
import grpc_pb2_grpc
channel = grpc.insecure_channel(self._url)
stub = grpc_pb2_grpc.PredictStub(channel)
response = stub.predict(grpc_pb2.PredictRequest(
image=image, split_char=',', model_type=model_type, model_site=model_site
))
return {"message": response.result, "code": response.code, "success": response.success}
if __name__ == '__main__':
result = GoogleRPC().request("base64編碼後的圖片二進位制流")
print(result)
```
### 3.5 奇技淫巧
該專案還可以直接用於識別帶顏色的驗證碼,部署專案middleware/impl/color_extractor.py基於k-means實現了顏色分離模組,可用於處理如下形式的驗證碼:
![紅色.png](https://upload-images.jianshu.io/upload_images/10905998-6cf1497fcdfe7755?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
還有一種方案是同時預測驗證碼和每個字元對應的顏色,不過這需要修改現有的神經網路進行支援,在最後一層修改為雙輸出,一個輸出顏色,一個輸出對應字元,這對於樣本標註的要求較高,也提高的成本,所以如果能用無限生成樣本,那問題就迎刃而解了,比如上圖,筆者就寫了樣本生成程式碼,感興趣的可以移步:
https://www.jianshu.com/p/da1b972e24f2
其實還有很多很多技巧,例如,用生成的樣本代替訓練集,其實網上的圖片驗證碼大多是採用開源的,稍作修改而已,大多數情況都能被近似生成出來,上述展示的驗證碼圖片不代表任何實際的網站,如有雷同,純屬巧合,該專案只能用於學習和交流用途,不得用於非法用途。
### 後記
如果文章描述不夠詳盡或需要技術支援的,可以加群 **857149419** 諮詢,或在開源專案中提issue,很榮幸能為開源社群貢獻綿薄