手写数字识别

前言

这几日,作息回到了早睡早醒,每天就花些时间去读书、去摄影、去锻炼以及做那些在WaitingList里躺了很久的有趣的事。
老板出差在美国,工作显得并不是那么忙碌,就在每天下班后抽出几个小时的时间去做了个手写数字识别的项目。主要涉及的技术包括了:机器视觉、深度学习(人工神经网络),当然相关的编程语言也是不可少的。

深度学习

就像hello world是每一个码农写的第一行代码,手写数字识别也是每一个想进入人工智能领域的人必上的第一课。
深度学习的框架很多,比如我司的caffe,但是由于最近实在对C++无感,所以本文采用了tensorflow,这个google大法开源的python框架。如果官网访问有难度,请自觉科学上网。
训练的数据集来自Yann LeCun’s website
训练模型我采用了最简单的softmax,因为急于先将整个流程走通,这个模型最后的测试集合的识别率只有92%。很槽糕,对不对,但是没关系以后还可以慢慢优化,:)希望可以说到做到。
训练过程用了梯度下降法去优化模型参数,大约300圈,识别率就打到了90%左右,后面的迭代基本就是不断的出现过拟合和修正过拟合问题。在训练结束之后可以保存训练模型:

1
2
3
saver = tf.train.Saver()
save_path = "./model/model.ckpt"
saver.save(sess, save_path)

以后在inference阶段,就可以直接提出这个模型和训练好的参数

1
2
3
saver = tf.train.Saver([W, b])
sess = tf.Session()
saver.restore(sess, "./model/model.ckpt")

有没有觉得这个过程很简单,哈哈,那是因为我对这个算法也是一知半解,也失去了少年时推导出数学公式时的欣喜。

图形预处理

事实上,更多的时间花会花在inference阶段如何对识别到的图形进行预处理上面。
机器视觉最主要的一个问题在于算法的通用性上,因为视觉受环境的影响很大,不同光照环境中得到的图片差别就像隔了一条银河。所以你会发现在自动驾驶领域,总会集成视觉、激光雷达、IMU等多种类型的传感器(ps.多元传感器信息融合是我的老本行,哈哈,爸爸就是靠这个硕士毕业的)。
所以在拍摄到每一张图片以后就需要对图片进行预处理和特征的提取,这里只罗列了关键的步骤,详细的代码请参考附录我的git的仓库

  • 拍摄得到原始彩色图片
  • 做一次5阶的gauss平滑
  • 转换成灰度图像
  • 二值化,二值化的阈值要考实验,当然参数不好后面也有一步去补救
  • 对二值化后的图片进行腐蚀和膨胀,主要是去除噪点让图像看起来比较饱满
  • 用canny算子提取ROI(region of interest 不知道中文怎么说,感兴趣的区域?)的轮廓
  • 找到ROI的外接矩形
  • 裁剪出ROI的subImage
  • resize 这个subImage倒特定的像素点(因为训练模型需要固定像素点的输入图形)
  • 最后再对这张图做一次膨胀和腐蚀(注意顺序和前面不一样哦,哈哈,想知道为什么请自行谷歌)
  • 最后将这张图形输入inference,模型就可以告诉你你到底写的是什么鸟语了

TensorBoard图形化展示

在模型的最后添加一行代码保存模型图到文件,这里保存到了当前.路径下面

1
file_writer = tf.summary.FileWriter('.', sess.graph)

之后只需要在对应的路径(这里为当前路径)下运行

1
tensorboard --logdir .

之后就可以显示出图形化展示的URL地址。ex.http://192.168.1.6:6006
直接访问以上地址就可以读取训练模型相关的图形化的显示,详细的资料可以参考一下链接

下一步计划

  1. 搭建更好的训练模型
  2. 改善预处理的算法
  3. 做一块智能硬件,和电脑端无线通讯,在电脑端得到识别结果之后,发给硬件板子,板子可以触发对应的动作,比如说控制无人机的姿态,想不出来其它点子,有点累了,脑洞变小了。

附录

最后附上训练好的模型、图像预处理代码以及测试集的下载地址