1. 程式人生 > >卷積神經網路(CNN)學習演算法之----基於LeNet網路的中文驗證碼識別

卷積神經網路(CNN)學習演算法之----基於LeNet網路的中文驗證碼識別

  由於公司需要進行了中文驗證碼的圖片識別開發,最近一段時間剛忙完上線,好不容易閒下來就繼上篇《基於Windows10 x64+visual Studio2013+Python2.7.12環境下的Caffe配置學習 》文章,記錄下利用caffe進行中文驗證碼圖片識別的開發過程。由於這裡主要介紹開發和實現過程,CNN理論性的東西這裡不作為介紹的重點,遇到相關的概念和術語請自行研究。目前從我們訓練出來的模型來看,單字識別率接近96%,所以一個四字驗證碼的準確率大概80%,效果還不錯,完全能滿足使用,如果每張圖片的樣本繼續加大應該能取得更高的準確率,當然隨著樣本的加大,訓練時間也隨之增大,對硬體裝置要求也越高,還有就是優化LeNet網路結構,目前這裡只使用了三層卷積。

(一)開發準備

(1)開發環境

     軟體環境:visual Studio2013+Python2.7.12+caffe

     硬體環境:Intel Core i7-4790+GTX1080+RAM32G

(2)訓練圖片

  可以用於驗證碼的中文常用字大概3666個,每個字的訓練大於等於50個,所以總共訓練樣本大概20萬,其中80%用於訓練集,20%用於測試集。樣本收集是一個非常麻煩和耗時的過程,需要手工標註結果,我這裡利用手工打碼平臺收集,最便宜一個驗證碼要4分錢,可以大概算一下,光為了收集這麼多樣本就將近花費1萬RMB,還有配置一個GTX1080的顯示卡大概6千RMB,這點成本對一個公司還好,如果是對於個人投入還是不少,所以對於實驗室的學生黨玩深度學習成本還是蠻高的!

  訓練集:26萬樣本圖片

  測試集:13萬樣本圖片

(二)圖片樣本處理

   目前驗證碼種類無極繁多,有數字、字母、中文、圖片等等,不過本文主要介紹中文驗證碼的識別。中文驗證碼設計干擾的方式主要圍繞:

  (1)背景色干擾

  (2)文字傾斜扭曲

  (3)干擾線

  (4)中文拼音並存(百度九宮格)

  (5)疊字

  針對不同型別的驗證碼需要分別處理,這些處理過程統稱圖片預處理,目前並沒有統一的預處理方式,需要針對不同的驗證碼做特殊處理,但是大體過程無外乎:灰度化、二值化、去幹擾線、分割切圖、標準化,這些過程用python實現都非常的簡單,這裡就不詳細介紹了,直接上程式碼,需要import cv2:

 1 class PreProcess(object):
 2     """description of class"""
 3     def ConvertToGray(self,Image,filename):
 4         GrayImage=cv2.cvtColor(Image,cv2.COLOR_BGR2GRAY)
 5         return GrayImage
 6        
 7     def ConvertTo1Bpp(self,GrayImage,filename):
 8       Bpp=cv2.threshold(GrayImage,127,255,cv2.THRESH_BINARY)
 9         cv2.imwrite('D://'+'1.jpg',Bpp[1])
10         return Bpp
11 
12     def InterferLine(self,Bpp,filename):
13         for i in range(0,76):
14             for j in range(0,Bpp.shape[0]):
15                 Bpp[j][i]=255
16         for i in range(161,Bpp.shape[1]):
17             for j in range(0,Bpp.shape[0]):
18                 Bpp[j][i]=255        
19         m=1
20         n=1
21         for i in range(76,161):
22             while(m<Bpp.shape[0]-1):
23                 if Bpp[m][i]==0:
24                     if Bpp[m+1][i]==0:
25                         n=m+1
26                     elif m>0 and Bpp[m-1][i]==0:
27                         n=m
28                         m=n-1
29                     else:
30                         n=m+1
31                     break
32                 elif m!=Bpp.shape[0]:
33                     l=0
34                     k=0
35                     ll=m
36                     kk=m
37                     while(ll>0):
38                         if Bpp[ll][i]==0:
39                             ll=11-1
40                             l=l+1
41                         else:
42                             break
43                     while(kk>0):
44                         if Bpp[kk][i]==0:
45                             kk=kk-1
46                             k=k+1
47                         else:
48                             break
49                     if (l<=k and l!=0) or (k==0 and l!=0):
50                         m=m-1
51                     else:
52                         m=m+1
53                 else:
54                     break
55                 #endif
56             #endwhile
57             if m>0 and Bpp[m-1][i]==0 and Bpp[n-1][i]==0:
58                 continue
59             else:
60                 Bpp[m][i]=255
61                 Bpp[n][i]=255
62             #endif
63         #endfor
64         return Bpp
65 
66     def CutImage(self,Bpp,filename):
67         b1=np.zeros((Bpp.shape[0],20))
68         for i in range(78,98):
69             for j in range(0,Bpp.shape[0]):
70                 b1[j][i-78]=Bpp[j][i]
71         cv2.imwrite(outpath+filename.decode('gbk')[0].encode('gbk')+'_'+'%d' %(time.time()*1000)+str(random.randint(1000,9999))+'.png',b1)
72 
73         b2=np.zeros((Bpp.shape[0],19))
74         for i in range(99,118):
75             for j in range(0,Bpp.shape[0]):
76                 b2[j][i-99]=Bpp[j][i]
77         cv2.imwrite(outpath+filename.decode('gbk')[1].encode('gbk')+'_'+'%d' %(time.time()*1000)+str(random.randint(1000,9999))+'.png',b2)
78 
79         b3=np.zeros((Bpp.shape[0],19))
80         for i in range(119,138):
81             for j in range(0,Bpp.shape[0]):
82                 b3[j][i-119]=Bpp[j][i]
83         cv2.imwrite(outpath+filename.decode('gbk')[2].encode('gbk')+'_'+'%d' %(time.time()*1000)+str(random.randint(1000,9999))+'.png',b3)
84 
85         b4=np.zeros((Bpp.shape[0],19))
86         for i in range(139,158):
87             for j in range(0,Bpp.shape[0]):
88                 b4[j][i-139]=Bpp[j][i]
89         cv2.imwrite(outpath+filename.decode('gbk')[3].encode('gbk')+'_'+'%d' %(time.time()*1000)+str(random.randint(1000,9999))+'.png',b4)
90         #return (b1,b2,b3,b4)
預處理

 呼叫預處理方法的程式碼:

1 import cv2
2 PP=PreProcess()
3 for root,dirs,files in os.walk(inpath):
4     for filename in files:
5         Img=cv2.imread(root+'/'+filename)#太坑,此處inpath不能包含中文路徑
6         GrayImage=PP.ConvertToGray(Img,filename)
7         Bpp=PP.ConvertTo1Bpp(GrayImage,filename)
8         Bpp_new=PP.InterferLine(Bpp,filename)
9         b=PP.CutImage(Bpp_new,filename)
批量處理圖片

 處理前的圖片:

預處理後的圖片:

 

(三)caffe模型配置

   模型配置階段,需要進行caffe所需資料格式準備、訓練集和測試集準備、Lenet網路結構配置等三步

  (1)訓練集和測試集準備

    預處理階段將驗證碼切割成四個圖片後,需要將每個圖片進行標準化為32*32畫素大小的圖片,不然caffe模型無法訓練。標準化完成以後就需要把每個字的圖片分拆到訓練集和測試集中去,這裡程式碼就不貼了,根據個人喜好我設定一個字的訓練集佔80%,測試集佔20%,然後把所有字用一個字典進行對映為數字編號,方便模型給出結果時我們能找到對應的漢字。

  (2)caffe格式資料

    為了生成caffe所需資料格式需要用到convert_imageset專案,在第一篇配置中已經編譯好了這個專案,可以直接拿過來用,python呼叫程式碼如下:

    path=os.getcwd()#儲存當前路徑
    os.chdir("./caffe-master/caffe-master/Build/x64/Debug")#改變路徑到caffe.exe資料夾
    os.system('SET GLOG_logtostderr=1')
    #生成訓練集
    os.system('convert_imageset.exe --shuffle ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/train  ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/train.txt  ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/trainldb 0')
    #生成測試集
    os.system('convert_imageset.exe --shuffle ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/val  ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/val.txt  ./caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/testldb 0')
呼叫convert_imageset生成caffe資料格式

     生成成功過後可以分別在訓練集和測試集資料夾看到如下兩個檔案:data.mdb和lock.mdb,都是caffe標準mdb格式的資料

  (3)Lenet網路模型

    目前Lenet模型已經非常成熟,最常用的是Lenet-5(5層),對於層數不需要太多的CNN網路用它完全足夠了,當然現在更強大的模型還有:Alexnet、googlenet,VGG,resnet。resnet是今年剛出的,據benchmark的測試,對於人臉識別它可以完爆其他網路,層數更是可以多達200,有興趣的可以看看:GitHub測評專案。對於Lenet有一個視覺化的配置網站:

    模型總共包含三個卷積層,兩個池化層,模型中最重要的幾個設定引數:num_output、kernel_size、stride需要分別配置,模型的好壞除了層數結構的設計外,就看這幾個引數是否配置的合理,具體的配置這裡不詳細講解,相關講解文章非常的多,也有很多優秀的論文可以借鑑,模型的結構程式碼如下:

name: "LeNet"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "E:/work/meb/Deeplearning/caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/trainldb"
    batch_size: 64
    backend: LMDB
  }
}
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "E:/work/meb/Deeplearning/caffe-master/caffe-master/windows/CaptchaTest/dpsample/data/testldb"
    batch_size: 100
    backend: LMDB
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 64
    kernel_size: 7
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}

layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 256
    pad:1
    kernel_size: 6
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}

layer {
  name: "conv3"
  type: "Convolution"
  bottom: "conv2"
  top: "conv3"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 1024
    pad:1
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu3"
  type: "ReLU"
  bottom: "conv3"
  top: "conv3"
}

layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv3"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 3666
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu4"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 3666
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}
View Code

(四)訓練模型

   到目前為止,準備工作都做完了,現在就可以利用python import caffe進行模型訓練了,模型訓練速度快慢主要看你GPU的配置如何,我開始用的GTX650,訓練5000輪下來,就得消耗半天時間,實在無法忍受這個速度,就向公司申請買了一個GTX1080,那速度簡直沒法比,訓練5000輪半個小時就能完成。呼叫模型的程式碼如下:

    cmd='caffe.exe train -solver=./caffe-master/caffe-master/windows/CaptchaTest/dpsample/solver/lenet_solver.prototxt'#訓練語句
    os.system(cmd)
    os.chdir(path)

  模型訓練中主要的輸出引數有:loss,accuracy,如果你看到loss一直在收斂,每500輪輸出一次的準確率也在提高,那麼說明你的模型設計沒什麼問題,不然就得重新設計。訓練完成後就能得到如下模型:

  

(五)使用模型

  模型訓練完成後,我們就可以簡單的用測試圖片進行測試,測試程式碼如下:

    #呼叫模型
    deploy='.\dpsample\solver\lenet_deploy.prototxt'    #deploy檔案
    caffe_model='.\dpsample\iterate_iter_5000.caffemodel'   #訓練好的 caffemodel
    imgtest='./dpsample/data/val/685_363.png'    #隨機找的一張待測圖片

    net = caffe.Net(deploy, caffe_model, caffe.TEST)
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})  #設定圖片的shape格式(1,3,32,32)
    transformer.set_transpose('data', (2,0,1))    #改變維度的順序,由原始圖片(28,28,3)變為(3,28,28)
    #transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))    #減去均值,前面訓練模型時沒有減均值,這兒就不用
    #transformer.set_raw_scale('data', 1)    # 縮放到【0,1】之間    已經在網路裡設定scale,這裡可以不用
    transformer.set_channel_swap('data', (2,1,0))   #交換通道,將圖片由RGB變為BGR
    im=caffe.io.load_image(imgtest)                   #載入圖片
    net.blobs['data'].data[...] = transformer.preprocess('data',im)       #執行上面設定的圖片預處理操作,並將圖片載入到blob中
    out = net.forward()
    prob= net.blobs['prob'].data[0].flatten() #取出最後一層(Softmax)屬於某個類別的概率值,並列印
    print prob
    order=prob.argsort()[-1]
    print(order)

  最後輸出的order就是模型預測出最有可能文字的序號,再到文字和序號對應的字典中去檢視就知道這裡的識別對不對了!

#寫在最後# 我是一個忠實的VS使用者,所有程式碼都在VS編輯器實現的,它要能用python需要安裝一個PTVS外掛,在這裡編輯python程式碼需要非常注意中文編碼的處理,否則你會吃大苦頭,不過相信我,其他編輯器能搞定的VS也一定沒問題,只是你要有足夠的耐心,遇到問題的時候多思考多搜搜問題的本質所在。

原創性宣告:

作品及其衍生品不得未經許可而用於商業用途。個人使用無需許可,但必須在引用部分(程式碼,基本思想或實現方案等)標示出原作者資訊,釋出時需附帶本宣告。(對於GPLv3下發布的作品,引用本人作品不需要許可,也不需要標示出引用部分或附帶宣告。)

關於“原創”的說明:文章釋出前我會進行初步的相關搜尋,如未發現有別人發表過類似內容的作品我才會發表。但是因為可能有遺漏,所以不能保證我的部落格內容一定為“首創”,但一定可以保證“原創”。

歡迎轉載,並請註明以下內容:

轉載自部落格園marso的Blog, 部落格地址為http://%部落格URL%,採用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議 進行許可。其中“%部落格URL%”替換為被轉載部落格的實際URL。

相關推薦

神經網路CNN學習演算法----基於LeNet網路中文驗證識別

  由於公司需要進行了中文驗證碼的圖片識別開發,最近一段時間剛忙完上線,好不容易閒下來就繼上篇《基於Windows10 x64+visual Studio2013+Python2.7.12環境下的Caffe配置學習 》文章,記錄下利用caffe進行中文驗證碼圖片識別的開發過程。由於這裡主要介紹開發和實現過程,

神經網路cnn學習筆記1:入門

卷積神經網路       卷積神經網路(Convolutional Neural Network,CNN)是深度學習技術中極具代表的網路結構之一,在影象處理領域取得了很大的成功,在國際標準的ImageNet資料集上,許多成功的模型都是基於CNN 的。CNN相較於傳統的影象

神經網絡CNN

進行 參數 一個 目的 下一步 方便 logs 很多 好的 最近可能會用到CNN,今天回顧一下,並找到了一些大神的精華帖,順便做個總結。 CNN是時下非常火的一種深度學習算法,它是一種前饋神經網絡,即神經元只與前後層有聯系,在同一層的神經元無聯系。筆者用下面這張圖用來說明卷

大話神經網絡CNN

相關性 圖形 圖像識別 src 應用 data str one 便是 這幾年深度學習快速發展,在圖像識別、語音識別、物體識別等各種場景上取得了巨大的成功,例如AlphaGo擊敗世界圍棋冠軍,iPhone X內置了人臉識別解鎖功能等等,很多AI產品在

神經網絡CNN的訓練過程

假設 特征向量 left 傳遞 方法 輸出 1.3 組成 初始化 卷積神經網絡的訓練過程 卷積神經網絡的訓練過程分為兩個階段。第一個階段是數據由低層次向高層次傳播的階段,即前向傳播階段。另外一個階段是,當前向傳播得出的結果與預期不相符時,將誤差從高層次向底層次進行傳播訓練的

神經網絡CNN在語音識別中的應用

現狀 each htm 介紹 產品 都在 color pcnn tmp 卷積神經網絡(CNN)在語音識別中的應用作者:侯藝馨前言總結目前語音識別的發展現狀,dnn、rnn/lstm和cnn算是語音識別中幾個比較主流的方向。2012年,微軟鄧力和俞棟老師將前饋神經網絡FFDN

吳恩達深度學習筆記deeplearning.ai神經網路CNN

1. Padding 在卷積操作中,過濾器(又稱核)的大小通常為奇數,如3x3,5x5。這樣的好處有兩點: 在特徵圖(二維卷積)中就會存在一箇中心畫素點。有一箇中心畫素點會十分方便,便於指出過濾器的位置。 在沒有padding的情況下,經過卷積操作,輸出的資

深入學習神經網路CNN的原理知識

  網上關於卷積神經網路的相關知識以及數不勝數,所以本文在學習了前人的部落格和知乎,在別人部落格的基礎上整理的知識點,便於自己理解,以後複習也可以常看看,但是如果侵犯到哪位大神的權利,請聯絡小編,謝謝。好了下面言歸正傳:   在深度學習領域中,已經經過驗證的成熟演算法,目前主要有深度卷積網路(DNN)和遞迴網

機器學習13:神經網路CNN

一、Why CNN for Image? 1、對於一幅影象來說,用DNN全連線的話,引數會很多,而影象實際上是有很多冗餘的,有些地方的特徵可能不需要。而CNN其實是拿掉了DNN的一些引數。 2、識別工作中,有時候並不需要看整張圖,而只需要看部分位置如鳥嘴。不管鳥嘴出現在影象的哪個位置,

tensorflow 學習專欄:使用神經網路CNN在mnist資料集上實現分類

卷積神經網路(Convolutional Neural Network, CNN)是一種前饋神經網路,它的人工神經元可以響應一部分覆蓋範圍內的周圍單元,對於大型影象處理有出色表現。卷積神經網路CNN的結構一般包含這幾個層:輸入層:用於資料的輸入卷積層:使用卷積核進行特徵提取和

深度學習基礎—— 從多層感知機MLP神經網路CNN

經典的多層感知機(Multi-Layer Perceptron)形式上是全連線(fully-connected)的鄰接網路(adjacent network)。 That is, every neuron in the network is connec

乾貨 | 深度學習神經網路CNN的前向傳播演算法詳解

微信公眾號 關鍵字全網搜尋最新排名 【機器學習演算法】:排名第一 【機器學習】:排名第一 【Python】:排名第三 【演算法】:排名第四 前言 在(乾貨 | 深度學習之卷積神經網路(CNN)的模型結構)中,我們對CNN的模型結構做了總結,這裡我們就在CNN的模型基礎上,看看CNN的前向傳播演算法是什麼樣

【深度學習神經網路CNN

卷積神經網路(Convolutional Neural NetWork,CNN): 自然語言處理、醫藥發現、災難氣候發現、人工智慧程式。 輸入層: 整個神經網路的輸入 卷積層: 卷積神經網路中最重要的部分,卷積層中每一個節點的輸入只是上一層神經網路的一小塊,一般為3

神經網路CNN在語音識別中的應用

卷積神經網路(CNN)在語音識別中的應用 作者:侯藝馨 前言 總結目前語音識別的發展現狀,dnn、rnn/lstm和cnn算是語音識別中幾個比較主流的方向。2012年,微軟鄧力和俞棟老師將前饋神經網路FFDNN(Feed Forward Deep Neural Network)引入到聲學模

神經網路CNN_相關知識

斯坦福公開課 CS231n Convolutional Neural Networks for Visual Recognition : http://cs231n.stanford.edu/syllabus.html 網路引數初始化:https://www.cnblogs.com/yinheyi

神經網路CNN概念原理

  什麼是卷積神經網路呢?這個的確是比較難搞懂的概念,特別是一聽到神經網路,大家腦海中第一個就會想到複雜的生物學,讓人不寒而慄,那麼複雜啊.卷積神經網路是做什麼用的呢?它到底是一個什麼東東呢? 卷積神經網路的靈感源一種生物程序,其中神經元之間的聯結模式和動物視覺皮層組織非常相似。所以發明者把它叫做卷積神經網

【6年人工智慧開發】簡述神經網路CNN

    在百度做了6年人工智慧方面的程式設計開發,也有很多這方面的經驗吧,從古至今,機器人一直承載著人類巨大的夢想。隨著各類感測器、語音互動、機器識別、SLAM等技術的蓬勃發展,機器人開始從科幻作品中走出

神經網路CNN基礎

CNN的基本結構 原文地址:https://www.jianshu.com/p/da0c4cc76a06 CNN分為幾層 CNN一共有卷積層(CONV)、ReLU層(ReLU)、池化層(Pooling)、全連線層(FC(Full Connection))下面是各個層的

神經網路CNN之一維、二維、三維詳解

由於計算機視覺的大紅大紫,二維卷積的用處範圍最廣。因此本文首先介紹二維卷積,之後再介紹一維卷積與三維卷積的具體流程,並描述其各自的具體應用。 1. 二維卷積 圖中的輸入的資料維度為14×1414×14,過濾器大小為5×55×5,二者做卷積,輸出的資料維度為10×1

簡單介紹神經網路CNN

前言: 原創: Python開發者 內容取自公眾號——Python開發者,有興趣的可以關注一下 什麼是卷積神經網路,它為何重要? 卷積神經網路(也稱作 ConvNets 或 CNN)是神經網路的一種,它在影象識別和分類等領域已被證明非常有效。 卷積神經網路除了為機器人