网络程序设计总结

前言

SA16225178 刘林熊

当初抱着对时下热门的机器学习、神经网络等知识的好奇心,选了孟宁老师的网络程序设计。
老实说,对一个自学能力极差又零基础的人而言,孟宁老师的授课方式一开始真没适应过来。学得慢,代码写的慢,好不容易有点微小的成果,没来得及pull request,别人就已经上传了,写的还比我的好。导致的后果就是所谓的课程零贡献,不知道会不会挂科。
但是上课的意义就是为了让学生学到东西,通过这门课,我学到了很多,包括对机器学习、神经网络的认识很理解,以及对一些机器学习基本框架的使用,包括caffe、tensorflow、keras。

课程目标

通过实现一个医学辅助诊断的专家系统原型。具体为实现对血常规检测报告OCR识别结果,预测患者的年龄和性别,学习机器学习的常见算法框架,重点分析神经网路,理解和掌握常用算法框架工具的使用。

神经网络介绍

人工神经网络(Artificial Neural Networks,简写为ANNs)也简称为神经网络(NNs)或称作连接模型(Connection Model),它是一种模仿动物神经网络行为特征,进行分布式并行信息处理的算法数学模型。这种网络依靠系统的复杂程度,通过调整内部大量节点之间相互连接的关系,从而达到处理信息的目的。
人工神经网络:是一种应用类似于大脑神经突触联接的结构进行信息处理的数学模型。在工程与学术界也常直接简称为“神经网络”或类神经网络。
这是百度百科上对神经网络的定义。机器学习是个很神奇的东西,而神经网络就是其中的典型代表。在我看来,一个人对事物的认知不可能将每个事物都高清无码地存储在记忆中。类似于图像JPEG压缩存储中,只存储人类敏感部分的色素一样,人们对一个事物的认识是通过学习它的特征,通过事物之间的特征联系,来识别不同的事物。
在机器学习中,我们会定义很多权值参数,我们用计算机学习的过程,就是确定每个权值参数的值,以更好地让计算机能通过这些权值来判断出不同的事物,进而进行不能的选择操作。
卷积神经网络
如图所示,作为一个工程实践人员,我们要做的就是定义好最适合的神经网络以供机器学习的训练测试,并提供给定格式的数据输入,接收数据输出。
在这篇文章里,我会介绍简单介绍时下流行的机器学习框架caffe、tensorflow、keras。然后再介绍课程所做的对血常规检验报告的OCR识别、深度学习与分析。

我的工作(项目贡献)

本来应该是项目贡献的模块。虽然既没有pull request,也没有分享过PPT。但我自己还是自学了很多内容,因此改为我的工作模块。
除了学习课程中的OCR图像识别相关内容,我也很认真地学习了caffe,tensorflow,keras等时下比较热门的机器学习框架,并做了一些相关的项目。我对这门课程付出的努力主要就体现在这些项目上了。内容比较多,我将所要介绍的框架写在了不同的博文上,以下提供链接。

caffe安装
caffe性别预测
caffe自定义网络模型图像识别
tensorflow实现简单手写识别
keras实现性别预测

项目地址

coding.net

对血常规检验报告的OCR识别、深度学习与分析

运行环境

操作系统:Ubuntu 16.04

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 安装numpy,
sudo apt-get install python-numpy # http://www.numpy.org/
# 安装opencv
sudo apt-get install python-opencv # http://opencv.org/
#安装OCR和预处理相关依赖
sudo apt-get install tesseract-ocr
sudo pip install pytesseract
sudo apt-get install python-tk
sudo pip install pillow
# 安装Flask框架、mongo
sudo pip install Flask
sudo apt-get install mongodb # 如果找不到可以先sudo apt-get update
sudo service mongodb started
sudo pip install pymongo
#安装tensorflow,keras框架
sudo pip install tensorflow
sudo pip install keras

运行

1
2
cd BloodTestReportOCR
python view.py # upload图像,在浏览器打开http://yourip:8080

文件介绍

view.py

Web 端上传图片到服务器,存入mongodb并获取oid,稍作修整,希望能往REST架构设计,目前还不完善; 前端采用了vue.js, mvvm模式。写了两个版本,一个是index.html无插件,另一个使用了bootstrap-fileinput插件,有点问题;

imageFilter.py

对图像透视裁剪和OCR进行了简单的封装,以便于模块间的交互,规定适当的接口

1
2
3
imageFilter = ImageFilter() # 可以传入一个opencv格式打开的图片
num = 22
print imageFilter.ocr(num)

ocr函数 - 模块主函数返回识别数据

用于对img进行ocr识别,他会先进行剪切,之后进一步做ocr识别,返回一个json对象 如果剪切失败,则返回None @num 规定剪切项目数

perspect函数做 - 初步的矫正图片

用于透视image,他会缓存一个透视后的opencv numpy矩阵,并返回该矩阵 透视失败,则会返回None,并打印不是报告 @param 透视参数

  • 关于param: 参数的形式为[p1, p2, p3 ,p4 ,p5]。 p1,p2,p3,p4,p5都是整型,其中p1必须是奇数。

p1是高斯模糊的参数,p2和p3是canny边缘检测的高低阈值,p4和p5是和筛选有关的乘数。

如果化验报告单放在桌子上时,有的边缘会稍微翘起,产生比较明显的阴影,这种阴影有可能被识别出来,导致定位失败。 解决的方法是调整p2和p3,来将阴影线筛选掉。但是如果将p2和p3调的比较高,就会导致其他图里的黑线也被筛选掉了。 参数的选择是一个问题。 我在getinfo.default中设置的是一个较低的阈值,p2=70,p3=30,这个阈值不会屏蔽阴影线。 如果改为p2=70,p3=50则可以屏蔽,但是会导致其他图片识别困难。

就现在来看,得到较好结果的前提主要有三个

  • 化验单尽量平整
  • 图片中应该包含全部的三条黑线
  • 图片尽量不要包含化验单的边缘,如果有的话,请尽量避开有阴影的边缘。

filter函数 - 过滤掉不合格的或非报告图片

返回img经过透视过后的PIL格式的Image对象,如果缓存中有PerspectivImg则直接使用,没有先进行透视 过滤失败则返回None @param filter参数

autocut函数 - 将图片中性别、年龄、日期和各项目名称数据分别剪切出来

用于剪切ImageFilter中的img成员,剪切之后临时图片保存在out_path, 如果剪切失败,返回-1,成功返回0 @num 剪切项目数 @param 剪切参数

剪切出来的图片在BloodTestReportOCR/temp_pics/ 文件夹下

函数输出为data0.jpg,data1.jpg……等一系列图片,分别是白细胞计数,中性粒细胞记数等的数值的图片。

classifier.py

用于判定裁剪矫正后的报告和裁剪出检测项目的编号

imgproc.py

将识别的图像进行处理二值化等操作,提高识别率 包括对中文和数字的处理

digits

将该文件替换Tesseract-OCR\tessdata\configs中的digits

主要知识介绍

图像处理 - 透视变换

  • 图像预处理去噪
    降噪后的图片
  • 采用Canny算子提取边缘
    提取边缘后的图片
  • 画线使用变换公式生成图片
    透视变化后的图片

ocr图像识别

提高图像识别的方法:

  • 对图片进行二值化处理,这里我使用了ostu算法对图像进行二值化处理,它是一种高效的二值化算法,可以参考wiki里关于算法的详细介绍。
  • 为了处理图片中的噪声点,对图片进行了腐蚀操作
  • 将图片放大,Tesseract对于较大的图片有较好的识别结果
  • 再次腐蚀被放大的噪声点
  • 膨胀使图片内容饱满便于识别
  • 直方图均衡化,提高图片的对比度
  • 中值滤波去除孤立的噪声点

切割后的数据:
切割后的图片

识别成的最终数据:
最终识别显示的数据

使用机器学习框架进行性别预测

keras方法
caffe方法

成果展示

最终预测结果如下:
最终预测结果

个人心得

知识方面
对机器学习及神经网络有了入门到深入认识的过程。通过提取数据的特征,使用算法表征这些特征并通过特征做出判断识别,这就是一个机器学习的过程。
老实说,刚接触人工智能的时候,感觉这些很神奇。也许不就的将来,这会成为科幻电影中智能机器人的开端吧。从简单的二分类数据识别,到最后复杂的行为判断,想想都会觉得兴奋。
但是对于神经网络,机器学习,自己真正掌握的还只是九牛一毛。作为一个工程人员,我应该尽可能地去理解相关算法的原理,在理解原理的基础上,使用相关框架工具为不同的任务去搭建最适合的网络,输入合适的数据源,以此来获得良好的结果,通过这些返回的结果,进一步去判断,去选择,让机器显得智能,直到最后真的智能。
对于这一方面的发展,我觉得就是要不断精进训练数据,合理搭配最适合的网络。朝着这两个方向不断发展。

课程方面
老实说,这门课程的学习还受到很多同学帮助交流,这里特别感谢欧小铉同学、夏天同学和寇亚飞大神的指导和交流,让我在对框架学习的时候不至于陷入死胡同而无法自拔。同时也要感谢孟宁老师对同学们的督促和交流学习。孟宁老师特别的学习方式,然后明白团队协作的重要性。但是由于本人性格内向,自学能力弱外加代码写的慢,正想pr的时候就发现已经有别的同学甚至做的更好的项目已经pr上去了,导致最后零贡献。这些正是我缺乏的吧。在以后的学习中我会争取慢慢改善这些缺点。但最后我还是学到了很多知识,掌握了一定的技能,在此,我再次感谢老师同学们。