Python實現手寫體數字圖片識別+GUI界面+畫板數字識別


__pycache__文件夾是Python自動生成的,詳細瞭解https://blog.csdn.net/yitiaodashu/article/details/79023987
其他各個文件在之後部分會依次介紹

圖片識別

版本:
python3.6
tensorflow 1.13.1(一定要安裝1.幾版本,不要安裝2.幾)
運行時可能有很多warning,不影響運行結果
此部分大多程序參考《TensorFlow實戰Google深度學習框架》

這裏使用的是基於全連接層網絡結構的神經網絡,對數字識別已經有了不錯的效果,但使用卷積神經網絡還可以提高正確率(大約99.2%),比如LeNet-5模型(https://blog.csdn.net/louishao/article/details/60867339)

在開始正式做之前,先看幾篇博客大致瞭解一下MNIST數據集:
https://blog.csdn.net/qq_38269418/article/details/78991649
https://blog.csdn.net/wspba/article/details/54311566
MNIST是深度學習的經典入門demo,他是由6萬張訓練圖片和1萬張測試圖片構成的,每張圖片都是28*28的灰度圖,像素取值爲0~1。這些圖片是採集的不同的人手寫從0到9的數字。TensorFlow將這個數據集和相關操作封裝到了庫中,每一張圖片是一個長度爲784的一維數組。
下面展示一些 內聯代碼片。

from tensorflow.examples.tutorials.mnist import input_data
1

會自動下載封裝好的數據集。但是我自己引入minst數據集會報各種各樣的錯誤,印象最深刻的是


我以爲是自己tensorflow和python版本的問題,因爲我同學就很順利就成功了,說真的浪費了好多時間在這個問題上,最後終於發現是數據集的原因,都快高興哭了https://blog.csdn.net/weixin_30699955/article/details/98091451
MNIST_data就是我根據這篇博客下載的tensorflow_mnist數據集
接下來是數字圖片識別相關的文件:
mnist_inference.py文件定義了前向傳播過程以及神經網絡的參數。三層全連接網絡結構,通過加入隱藏層實現了多層網絡結構。
mnist_train.py定義了神經網絡的訓練過程。運行mnist_train.py文件便會開始訓練模型,MNIST_model文件已經有訓練好的模型,你也可以刪掉或修改然後重新訓練。
MNIST_model文件夾保存了已經訓練30000次的模型
mnist_eval.py文件定義了測試過程。運行mnist_eval.py文件就是計算在mnist數據集上測試1萬張圖片的正確率。比如在MNIST數據集10000張測試圖片上的正確率

picture文件夾存放的是自己手寫數字的圖片
app.py文件實現了測試自己手寫數字的圖片。運行後直接識別picture文件夾裏的所有圖片。

遇到的困難

  • 不知道模型訓練好了怎麼測試自己手寫的圖片
    mnist_inference.py、mnist_train.py 和 mnist_eval.py這三個文件已經可以實現訓練模型和測試正確率。之後怎麼測試自己的圖片呢?
    輸入節點是長度爲784的數組,所以得把自己的圖片轉化爲長度是784的數組,才能輸入到模型裏,才能得到結果。
    代碼在app.py裏的image_prepare()函數,通過使用圖像處理庫PIL把圖片轉化爲灰度圖並且修改尺寸爲28*28,然後轉化爲數組。
  • 測試自己手寫圖片的正確率太低
    在mnist測試數據集上的正確率有98%以上,而測試自己手寫數字的正確率太低了,大部分數字都被識別成8。

    這部分我參考了https://blog.csdn.net/qq_43479622/article/details/90906094,從這裏我們可以看出找到幾個原因
  • mnist數據集圖片是黑底白字,而我們平時都是白底黑字,所以要對測試圖片灰度反轉。
    修改後已經可以識別幾個數字了,但還是很多被識別成了8。原因是自己拍的圖片有很多噪點,直接輸入給模型就因爲噪點太多,被誤認爲是8。
  • 二值化來降噪


    使用opencv二值化圖像cv2.threshold(img,127,255,cv2.THRESH_BINARY)
    雖然還有少量噪點,但已經有很好的識別效果了。(還可以再調整閾值)
  • 對自己手寫圖片的選取可以參考:
    https://blog.csdn.net/qq_38269418/article/details/78991649

Gui界面

run1.py是界面文件
timg是界面背景圖,你也可以自己選

 


利用PyQt畫界面按鈕和文本框的介紹網上有很多。直接拿過來用就好。這部分的關鍵是怎麼把app.py的思路搬進run1.py。如果你的app.py運行順利的話,這部分也不會很難。
這部分我有兩個錯誤:

  • 代碼順序引起的問題
    錯誤代碼:
evaluate(pic)
def evaluate(pic):
    。。。
123

改正代碼:

def evaluate(pic):
  。。。
evaluate(pic)
123
  • 圖片名稱輸出錯誤
    pic_name是函數參數,在app.py的時候設置了,但是在run1.py裏我並沒有設置這個參數,即使設置也會出現別的錯誤。於是我先把pic_name設置成100行的「x」看輸出是否有錯誤。最終控制面板輸出是 x is 4。由此可見其他程序都沒有問題
    經別人介紹用瞭如圖第99行的函數來進行圖片名稱的調用。

畫板數字識別

思路:在畫板上畫數字,之後截圖輸出,再通過GUI界面選擇這張圖片進行識別。
as.png截圖畫板輸出的圖片。
導出.png是畫板左上角的圖標,點擊後生成as.png。
now.py運行後,出現畫板界面。

畫板:https://www.jb51.net/article/126189.htm
需要一個列表來保存所有移動過的點,然後把所有相鄰兩個點之間都畫一條線,就能斷斷續續連成鼠標的痕跡了。當鼠標按住移動然後鬆開的時候,往保存所有移動過的點的列表中添加一個斷點(-1, -1)。然後在每次畫線的時候,都判斷一下是不是斷點,如果是斷點的話就想辦法跳過去,並且不連續的開始接着畫線。

截圖:https://blog.csdn.net/mxdzchallpp/article/details/79097951?utm_source=blogxgwz4&utm_medium=distribute.pc_relevant.none-task-blog-utm_term-3&spm=1001.2101.3001.4242
最終結果:

注意:
畫板中使用的是drawline函數,如果畫筆線條很細,識別率特別低,除非通過不斷描繪,人爲加粗線條,最終識別率還挺高的。但是最簡單的方法還是設置畫筆粗細。
https://blog.csdn.net/La_vie_est_belle/article/details/84930977?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160429169019724822515101%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160429169019724822515101&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v28-1-84930977.first_rank_ecpm_v3_pc_rank_v2&utm_term=PYQT++繪圖%2B打印&spm=1018.2118.3001.4449

PS:如有需要Python學習資料的小夥伴可以加點擊下方鏈接自行獲取

python免費學習資料以及羣交流解答點擊即可加入