參考GitHub源碼:https://github.com/YoungMiao/crnn
應demo大師文章要求,我再補充下,推薦下,這個平台挺好
1.環境搭建
1.1 基礎環境
- Ubuntu14.04 + CUDA
- opencv2.4 + pytorch + lmdb +wrap_ctc
安裝lmdb apt-get install lmdb
1.2 安裝pytorch
pip,linux,cuda8.0,python2.7:pip install http://download.pytorch.org/whl/cu80/torch-0.1.12.post2-cp27-none-linux_x86_64.whl
參考:http://pytorch.org/
1.3 安裝wrap_ctc
git clone https://github.com/baidu-research/warp-ctc.git`
cd warp-ctc
mkdir build; cd build
cmake ..
make
GPU版在環境變量中添加
export CUDA_HOME="/usr/local/cuda"
cd pytorch_binding
python setup.py install
參考:https://github.com/SeanNaren/warp-ctc/tree/pytorch_bindings/pytorch_binding
1.4 注意問題
- 缺少cffi庫文件 使用
pip install cffi
安裝 - 安裝pytorch_binding前,確認設置CUDA_HOME,雖然編譯安裝不會報錯,但是在調用gpu時,會出現wrap_ctc沒有gpu屬性的錯誤
2. crnn預測(以21類中英文為例)
模型地址:鏈接:https://eyun.baidu.com/s/3dEUJJg9 密碼:vKeD
運行/contrib/crnn/demo.py
原始圖片為:
識別結果為:
# 加載模型
model_path = './samples/netCRNN_9_112580.pth'
# 需識別的圖片
img_path = './data/demo.png'
# 識別的類別
alphabet = 'ACIMRey萬下依口哺攝次狀璐癌草血運重'
# 設置模型參數 圖片高度imgH=32, nc, 分類數目nclass=len(alphabet)+1 一個預留位, LSTM設置隱藏層數nh=128, 使用GPU個數ngpu=1
model = crnn.CRNN(32, 1, 22, 128, 1).cuda()
替換模型時,注意模型分類的類別數目
3、程序實現(crnn 訓練(以21類中英文為例))
注意:--------------------------------------
請補充完整個實現過程,以下實現,沒有說到具體的實現過程,應該把具體的代碼說清楚,思路說清楚。數據怎樣清洗的,怎樣建模的等等
1. 數據預處理
運行/contrib/crnn/tool/tolmdb.py
# 生成的lmdb輸出路徑
outputPath = "./train_lmdb"
# 圖片及對應的label
imgdata = open("./train.txt")
2. 訓練模型
運行/contrib/crnn/crnn_main.py
python crnn_main.py [--param val]
--trainroot 訓練集路徑
--valroot 驗證集路徑
--workers CPU工作核數, default=2
--batchSize 設置batchSize大小, default=64
--imgH 圖片高度, default=32
--nh LSTM隱藏層數, default=256
--niter 訓練回合數, default=25
--lr 學習率, default=0.01
--beta1
--cuda 使用GPU, action='store_true'
--ngpu 使用GPU的個數, default=1
--crnn 選擇預訓練模型
--alphabet 設置分類
--Diters
--experiment 模型保存目錄
--displayInterval 設置多少次迭代顯示一次, default=500
--n_test_disp 每次驗證顯示的個數, default=10
--valInterval 設置多少次迭代驗證一次, default=500
--saveInterval 設置多少次迭代保存一次模型, default=500
--adam 使用adma優化器, action='store_true'
--adadelta 使用adadelta優化器, action='store_true'
--keep_ratio 設置圖片保持橫縱比縮放, action='store_true'
--random_sample 是否使用隨機采樣器對數據集進行采樣, action='store_true'
示例:python /contrib/crnn/crnn_main.py --tainroot [訓練集路徑] --valroot [驗證集路徑] --nh 128 --cuda --crnn [預訓練模型路徑]
修改/contrib/crnn/keys.py
中alphabet = 'ACIMRey萬下依口哺攝次狀璐癌草血運重'
增加或者減少類別
- 注意事項
訓練和預測采用的類別數和LSTM隱藏層數需保持一致
4、項目結構
從上往下大概說明下
1.crnn.py是crnn網絡結構模塊
#雙向的LSTM
class BidirectionalLSTM(nn.Module)
#CRNN網絡
class CRNN(nn.Module)
crnn網絡設計:
CRNN由CNN+BiLSTM+CTC構成:
網絡結構:
-
input: 輸入文字塊,歸一化到
32*w
即height縮放到32,寬度按高度的比率縮放,也可以縮放到自己想要的寬度,訓練時為批次訓練,縮放到[32,Wmax]),示例為(32,128) -
經過兩個conv層和兩個poling層,conv3層時數據大小為256*8*32,兩個pooling層步長為2
-
pooling2層步長為(2,1),(個人看法:作者使用的英文訓練,英文字符的特征是高大於寬的特征,倘若使用中文訓練,建議使用(2,2),我的代碼中默認為(2,2),示例以(2,1)為例,所以此時輸出為256*4*33
-
bn層不改變輸出的大小(就是做個歸一化,加速訓練收斂),p3層時,w+1,所以pooling3層時,輸出為512*2*34
-
conv7層時,kernel 為22,stride(1,1) padding(0,0)
Wnew = (2 + 2 * padW - kernel ) / strideW + 1 = 1
Hnew = 33
所以conv7層輸出為5121*33 -
后面跟兩個雙向Lstm,隱藏節點都是256
Blstm1輸出33*1256
Blstm2輸出 33*1*5530 5530 = 字符個數 + 非字符 = 5529 + 1
最終的輸出結果直觀上可以想象成將128分為33份,每一份對應5530個類別的概率
2.tolmdb.py生成訓練lmdb數據模塊
- 輸入圖片list的文檔,大概格式如下
3.crnn_main.py主程序模塊
- 增加了對類別增刪的增量訓練,line104~line117
4.dataset.py數據加載模塊 - class alignCollate:按照比例縮放w
- class randomSequentialSampler:隨機采樣batch
5.utils.py編解碼模塊
5、數據部分
數據獲取方法有兩種:
- 生成自然場景文本
GitHub:https://github.com/ankush-me/SynthText - 生成常規文本:
GitHub:https://github.com/YoungMiao/synthdata-zh
有時間在記錄兩種方法
CRNN中英文字符識別
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權