1. 程式人生 > >牛奶盒噴碼字元識別(基於opencv)————(三)字元的識別

牛奶盒噴碼字元識別(基於opencv)————(三)字元的識別

更新

效果

先看效果吧。
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
效果極佳,

方法

1.製作模板

將分割出來的數字,效果很不錯的當作我們的模板,後面用作匹配,C L :都當作數字處理
在這裡插入圖片描述

2.讀入模板,

這裡我通過建立三維陣列,採用for迴圈讀入
注意,讀取時候,要加0引數,不然會以三通道方式讀取。

templatepath="C:\\Users\\mechrevo\\Desktop\\template\\" #模板
template=np.zeros([dsize,dsize,13],np.uint8) #注意uint8為1通道,預設為 3通道
for i in range(13):
    #print(i)
    template[
:,:,i] = cv2.imread(templatepath + "%d.png" %i, 0)

3.讀入分割出來的圖片

將上一節分割出來的20張圖片,都讀入進去,同樣構建三維陣列,for迴圈讀入

img=np.zeros([dsize,dsize,20],np.uint8)
for i in range(20):
   # print(i)
    img[:,:,i] = cv2.imread(root + "%d.png" %i, 0) #記住引數 0 
    #cv2.imshow("s"+ "%d" %i, img[:,:,i])

4.逐一匹配

採用巢狀for迴圈,使得每個分割的影象與模板匹配,算出來的rez值最大的,就是最有可能的字元,這裡採用cv2.TM_CCOEFF_NORMED

標準相關匹配方法,這是 OpenCV 支援的最複雜的一種相似度演算法。這裡的相關運算就是數理統計學科的相關係數計算方法。
總之,越複雜,佔用cpu越多,越耗時,但是越準確。

res=np.zeros([13],np.float16)

for i in range(20):
    
    for j in range(13):
        
        res[j] = cv2.matchTemplate(img[:,:,i],template[:,:,j],cv2.TM_CCOEFF_NORMED) #注意邏輯
    maxindex  = np.argmax(res)    
    
    if
(maxindex<10 and maxindex >=0): print(maxindex) elif (maxindex == 10): print("C") elif (maxindex == 11): print("L") elif (maxindex == 12): print(":") #print(res)

在這裡插入圖片描述
看看誰最大,使用np.argmax直接得出答案,在等於10,11,12加入判斷即可
效果如頂部那樣,統計了50張圖,也就是1000個數字,準確率為95.2%

不足

當然演算法還有一些不足之處:
比如:
1.如果字元不為20的話,演算法會出錯,只不過我的資料集90%的圖都是20個字元的,要改進,可以使用檔案操作相關函式
2.對於0和8,或扭曲數字,很容易出錯,有機會我會嘗試卷積神經網路。
3.對於一些扭曲的圖片,兩行直接沒有白色畫素,有很小几率會無法切割行。

總之,這只是一門選修課,我也不願太費心思去繼續改進,有什麼問題可以評論區交流.
等結課後公佈完整程式碼,供大家學習交流。