完整版请点击链接: https://mp.weixin.qq.com/s/5gHXGmLbtO7m3dOFrDUiHQ 或微信关注 "大数据技术宅"
继用 TensorFlow 教你做手写字识别 (准确率 94.09%) 文章中, 笔者给出了 CNN 模型的训练以及给出了一些数字图像进行效果测试, 这篇文章, 笔者将给出自己手写数字图像, 并且对图像进行简单处理, 用上一篇文章中训练的网络进行手写数字的识别. 下边跟着笔者的步伐实现属于自己的数字图像识别.
工具要求
工具及环境要求如下, 如果大家在安装 TensorFlow 过程遇到问题, 可以咨询笔者一起探讨.
- Python 2.7.14
- TensorFlow 1.5
- pip 10.0.1
Linux 环境
- openCV 2.4.13.6
- C++
数字图像素材准备
笔者画了两个手写字, 如图 1 所示, 读者可以自行绘制自己的手写字图像.
图 1 手绘数字图片
手绘数字图像预处理
由于笔者训练的 CNN 网络的输入图像是 28*28 像素的, 所以需要对手绘数字图像进行简单处理, 转换成 28*28 的灰度图像. 图像处理的工具用的是 openCV,C++ 代码如下:
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #include "cv.h"
- #include <string>
- #include <stdio.h>
- using namespace cv;
- using namespace std;
- cv::Mat org,dst,img,tmp;
- void on_mouse(int event,int x,int y,int flags,void *ustc)//event 鼠标事件代号, x,y 鼠标坐标, flags 拖拽和键盘操作的代号
- {
- static Point pre_pt = cv::Point(-1,-1);// 初始坐标
- static Point cur_pt = cv::Point(-1,-1);// 实时坐标
- char temp[16];
- if (event == CV_EVENT_LBUTTONDOWN)// 左键按下, 读取初始坐标, 并在图像上该点处划圆
- {
- org.copyTo(img);// 将原始图片复制到 img 中
- sprintf(temp,"(%d,%d)",x,y);
- pre_pt = Point(x,y);
- putText(img,temp,pre_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255),1,8);// 在窗口上显示坐标
- circle(img,pre_pt,2,Scalar(255,0,0,0),CV_FILLED,CV_AA,0);// 划圆
- imshow("img",img);
- }
- else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))// 左键没有按下的情况下鼠标移动的处理函数
- {
- img.copyTo(tmp);// 将 img 复制到临时图像 tmp 上, 用于显示实时坐标
- sprintf(temp,"(%d,%d)",x,y);
- cur_pt = Point(x,y);
- putText(tmp,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));// 只是实时显示鼠标移动的坐标
- imshow("img",tmp);
- }
- else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))// 左键按下时, 鼠标移动, 则在图像上划矩形
- {
- img.copyTo(tmp);
- sprintf(temp,"(%d,%d)",x,y);
- cur_pt = Point(x,y);
- putText(tmp,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));
- rectangle(tmp,pre_pt,cur_pt,Scalar(0,255,0,0),1,8,0);// 在临时图像上实时显示鼠标拖动时形成的矩形
- imshow("img",tmp);
- }
- else if (event == CV_EVENT_LBUTTONUP)// 左键松开, 将在图像上划矩形
- {
- org.copyTo(img);
- sprintf(temp,"(%d,%d)",x,y);
- cur_pt = Point(x,y);
- putText(img,temp,cur_pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255));
- circle(img,pre_pt,2,Scalar(255,0,0,0),CV_FILLED,CV_AA,0);
- rectangle(img,pre_pt,cur_pt,Scalar(0,255,0,0),1,8,0);// 根据初始点和结束点, 将矩形画到 img 上
- imshow("img",img);
- img.copyTo(tmp);
- // 截取矩形包围的图像, 并保存到 dst 中
- int width = abs(pre_pt.x - cur_pt.x);
- int height = abs(pre_pt.y - cur_pt.y);
- if (width == 0 || height == 0)
- {
- printf("width == 0 || height == 0");
- return;
- }
- dst = org(Rect(min(cur_pt.x,pre_pt.x),min(cur_pt.y,pre_pt.y),width,height));
- Mat dst02;
- cv::resize(dst,dst02,Size(28,28));
- imwrite("/home/openCV/mnist/temp.png",dst02);// 注意将这里改为自己的处理结果存储地址
- namedWindow("dst02");
- imshow("dst02",dst02);
- waitKey(0);
- }
- }
- int main()
- {
- org = imread("/home/openCV/mnist/ceshi8.jpg");// 读取图片地址
- org.copyTo(img);
- org.copyTo(tmp);
- namedWindow("img");// 定义一个 img 窗口
- setMouseCallback("img",on_mouse,0);// 调用回调函数
- imshow("img",img);
- cv::waitKey(0);
- }
C++ 代码需要先编译, 再运行, 运行过程中如果遇到什么问题, 欢迎读者跟笔者沟通, 处理完之后图像如图 2 所示:
图 2 预处理后手写图像
调用 CNN 网络对图像进行识别
用上一篇文章 (用 TensorFlow 教你做手写字识别(准确率 94.09%)) 部分, 测试模型的代码, 对处理过的手写图像进行识别, 识别结果如图 3 所示:
图 3 手写数字是被结果
通过笔者两篇手写数字识别文章的学习, 相信动手尝试的读者已经对图像识别的流程有了简单的了解, 在后续的图像识别系列文章中笔者会更加深入的介绍图像识别. 图像识别的接下来两篇文章中笔者会用一篇讲解 Faster R-CNN 的原理, 另一篇介绍 Faster R-CNN 的应用, 并附上模型代码, 预计要达到的效果如图 4 所示:
图 4 图像识别效果
最后, 笔者说一些题外话, 本公众号运营到维护已经有近两个月时间, 由于是笔者利用周末和业余时间所写, 所以更新会比较缓慢, 但笔者可以保证每周至少有一篇原创分享, 并且保证本公众号不会存在任何商业行为, 完全出于笔者爱好. 希望想从事大数据及人工智能相关工作的读者与笔者互动交流, 一块进步.
持续更新 ing
来源: https://www.cnblogs.com/followees/p/10422791.html