完整版請點擊連接:https://mp.weixin.qq.com/s/5gHXGmLbtO7m3dOFrDUiHQ 或微信關注「大數據技術宅」linux
繼用TensorFlow教你作手寫字識別(準確率94.09%)文章中,筆者給出了CNN模型的訓練以及給出了一些數字圖像進行效果測試,這篇文章,筆者將給出本身手寫數字圖像,而且對圖像進行簡單處理,用上一篇文章中訓練的網絡進行手寫數字的識別。下邊跟着筆者的步伐實現屬於本身的數字圖像識別。微信
工具要求網絡
工具及環境要求以下,若是你們在安裝TensorFlow過程遇到問題,能夠諮詢筆者一塊兒探討。函數
Python 2.7.14工具
TensorFlow 1.5學習
pip 10.0.1測試
linux環境大數據
openCV 2.4.13.6ui
C++人工智能
數字圖像素材準備
筆者畫了兩個手寫字,如圖1所示,讀者能夠自行繪製本身的手寫字圖像。
圖1 手繪數字圖片
手繪數字圖像預處理
因爲筆者訓練的CNN網絡的輸入圖像是28*28像素的,因此須要對手繪數字圖像進行簡單處理,轉換成28*28的灰度圖像。圖像處理的工具用的是openCV,C++代碼以下:
1#include <opencv2/core/core.hpp>
2#include <opencv2/highgui/highgui.hpp>
3#include <opencv2/imgproc/imgproc.hpp>
4#include "cv.h"
5#include <string>
6#include <stdio.h>
7using namespace cv;
8using namespace std;
9
10cv::Mat org,dst,img,tmp;
11void on_mouse(int event,int x,int y,int flags,void *ustc)//event鼠標事件代號,x,y鼠標座標,flags拖拽和鍵盤操做的代號
12{
13 static Point pre_pt = cv::Point(-1,-1);//初始座標
14 static Point cur_pt = cv::Point(-1,-1);//實時座標
15 char temp[16];
16 if (event == CV_EVENT_LBUTTONDOWN)//左鍵按下,讀取初始座標,並在圖像上該點處劃圓
17 {
18 org.copyTo(img);//將原始圖片複製到img中
19 sprintf(temp,"(%d,%d)",x,y);
20 pre_pt = Point(x,y);
21 putText(img,temp,pre_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255),1,8);//在窗口上顯示座標
22 circle(img,pre_pt,2,Scalar(255,0,0,0),CV_FILLED,CV_AA,0);//劃圓
23 imshow("img",img);
24 }
25 else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))//左鍵沒有按下的狀況下鼠標移動的處理函數
26 {
27 img.copyTo(tmp);//將img複製到臨時圖像tmp上,用於顯示實時座標
28 sprintf(temp,"(%d,%d)",x,y);
29 cur_pt = Point(x,y);
30 putText(tmp,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));//只是實時顯示鼠標移動的座標
31 imshow("img",tmp);
32 }
33 else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))//左鍵按下時,鼠標移動,則在圖像上劃矩形
34 {
35 img.copyTo(tmp);
36 sprintf(temp,"(%d,%d)",x,y);
37 cur_pt = Point(x,y);
38 putText(tmp,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));
39 rectangle(tmp,pre_pt,cur_pt,Scalar(0,255,0,0),1,8,0);//在臨時圖像上實時顯示鼠標拖動時造成的矩形
40 imshow("img",tmp);
41 }
42 else if (event == CV_EVENT_LBUTTONUP)//左鍵鬆開,將在圖像上劃矩形
43 {
44 org.copyTo(img);
45 sprintf(temp,"(%d,%d)",x,y);
46 cur_pt = Point(x,y);
47 putText(img,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));
48 circle(img,pre_pt,2,Scalar(255,0,0,0),CV_FILLED,CV_AA,0);
49 rectangle(img,pre_pt,cur_pt,Scalar(0,255,0,0),1,8,0);//根據初始點和結束點,將矩形畫到img上
50 imshow("img",img);
51 img.copyTo(tmp);
52 //截取矩形包圍的圖像,並保存到dst中
53 int width = abs(pre_pt.x - cur_pt.x);
54 int height = abs(pre_pt.y - cur_pt.y);
55 if (width == 0 || height == 0)
56 {
57 printf("width == 0 || height == 0");
58 return;
59 }
60 dst = org(Rect(min(cur_pt.x,pre_pt.x),min(cur_pt.y,pre_pt.y),width,height));
61 Mat dst02;
62 cv::resize(dst,dst02,Size(28,28));
63
64 imwrite("/home/openCV/mnist/temp.png",dst02);//注意將這裏改成本身的處理結果存儲地址
65 namedWindow("dst02");
66 imshow("dst02",dst02);
67 waitKey(0);
68 }
69}
70int main()
71{
72 org = imread("/home/openCV/mnist/ceshi8.jpg");//讀取圖片地址
73 org.copyTo(img);
74 org.copyTo(tmp);
75 namedWindow("img");//定義一個img窗口
76 setMouseCallback("img",on_mouse,0);//調用回調函數
77 imshow("img",img);
78 cv::waitKey(0);
79}
C++代碼須要先編譯,再運行,運行過程當中若是遇到什麼問題,歡迎讀者跟筆者溝通,處理完以後圖像如圖2所示:
圖2 預處理後手寫圖像
調用CNN網絡對圖像進行識別
用上一篇文章(用TensorFlow教你作手寫字識別(準確率94.09%))部分,測試模型的代碼,對處理過的手寫圖像進行識別,識別結果如圖3所示:
圖3 手寫數字是被結果
經過筆者兩篇手寫數字識別文章的學習,相信動手嘗試的讀者已經對圖像識別的流程有了簡單的瞭解,在後續的圖像識別系列文章中筆者會更加深刻的介紹圖像識別。圖像識別的接下來兩篇文章中筆者會用一篇講解Faster R-CNN的原理,另外一篇介紹Faster R-CNN的應用,並附上模型代碼,預計要達到的效果如圖4所示:
圖4 圖像識別效果
最後,筆者說一些題外話,本公衆號運營到維護已經有近兩個月時間,因爲是筆者利用週末和業餘時間所寫,因此更新會比較緩慢,但筆者能夠保證每週至少有一篇原創分享,而且保證本公衆號不會存在任何商業行爲,徹底出於筆者愛好。但願想從事大數據及人工智能相關工做的讀者與筆者互動交流,一塊進步。
持續更新ing