林牧 SA16222166

  • 课程目标
  • 课程安排
  • A1a
  • A2
  • A3
  • 项目集成
  • 环境搭建
  • 其他方面的收获
  • 本课心得

课程目标

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

课程安排

  • A1a 神经网络实现手写字符识别系统
  • A2 血常规检验报告的图像OCR识别
  • A3 根据血常规检验的各项数据预测年龄和性别

Pull Request

A1a

  该项目属于神经网络中的"Hello World",本项目的目的是通过对一定量数字的训练,达到对手写数字的识别。输入的图像是一个20x20的图像,共有400个像素点。我们把这400个像素点都作为输入加入到神经网络的输入层。然后,我们为隐藏层设置为15个节点。输出层设置为10个节点,这10个节点也就是该神经网络对输入图像进行分类所输出的分类信息,我们从中可以确定输出的是哪个数字。然后在网页端显示出来。

A2

  A2部分主要是对得到的化验单进行图像预处理后,利用OCR提取出其中有用的信息。例如人名,时间以及各种化验指标等。在这一部分,我的思路主要是用一些形态学的方法(腐蚀膨胀)对图像进行预处理,代码如下:

def preprocess(gray):
# 1. Sobel算子,x方向求梯度
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)
cv2.namedWindow("sobel")
cv2.imshow("sobel", sobel)
cv2.waitKey(0)
# 2. 二值化
ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)
cv2.namedWindow("binary")
cv2.imshow("binary", binary)
cv2.waitKey(0)
# 3. 膨胀和腐蚀操作的核函数 element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 3))
element2 = cv2.getStructuringElement (cv2.MORPH_RECT, (17,3)) # 4. 膨胀一次,让轮廓突出
dilation = cv2.dilate(binary, element2, iterations = 1)
cv2.namedWindow("dilation1")
cv2.imshow("dilation1", dilation)
cv2.waitKey(0)
# 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线
erosion = cv2.erode(dilation, element1, iterations = 1)
cv2.namedWindow("erosion")
cv2.imshow("erosion", erosion)
cv2.waitKey(0)
#6. 再次膨胀,让轮廓明显一些
dilation2 = cv2.dilate(erosion, element2, iterations = 1)
cv2.namedWindow("dilation2")
cv2.imshow("dilation2", dilation2)
cv2.waitKey(0)
# 7. 存储中间图片
cv2.imwrite("binary.png", binary)
cv2.imwrite("dilation1.png", dilation)
cv2.imwrite("erosion.png", erosion)
cv2.imwrite("dilation2.png", dilation2) return dilation2

  这里大概解释一下,膨胀和腐蚀操作都是通过一个核对图像进行类似卷积的操作实现的,其中膨胀操作会使图像的区域变大,而腐蚀的操作会使图像的区域变小。在本例中,先使用一个水平方向的sobel算子求梯度。这样一来,长横线在水平方向上一直存在,也就是说梯度是趋近于0,在梯度操作后会消失。然后进行了膨胀——腐蚀——膨胀的操作。第一次膨胀使轮廓更加明显,接下来的腐蚀操作会去掉一些噪点,最后的膨胀操作有补偿腐蚀操作的作用,这样一来经过腐蚀操作还留下来的点会扩大一点使轮廓更清晰,而噪点会消失。如下两图所示:

  然后,排除其中面积比较小的区域,把大的区域圈出来:

  最后取出圈出的点,利用tesseract进行识别。

  然而,最后还是放弃了这个办法,因为在数字和文字离得很近的时候无法分开数字和文字,导致文字和数字在一起识别的时候没有办法识别出数字和文字。

  最后使用的是某个大神针对我们要处理的图像的进行的特别的处理,主要步骤如下:

  1. 原图像如下:

  2. 开闭操作后采用canny算子提取边缘  

  3. 用findCounters提取出三条线的轮廓:

  4. 将轮廓变成线,准备下一步的处理,在下一步处理之前,如果多于三条线,则选出其中最长的三条线。接着,根据三条线互相之间的距离确定表头和表尾的位置:

  5. 然后,根据叉乘不可变性确定起始点,切下表格进行透视投影变换。

 

  在提取有用部分的时候,我们直接使用上下两条线之间的距离作为一个基准距离,从而可以得到每一个栏目所在的位置的像素点的坐标,然后精准的提取出所要的项目名称和数字。该方法的好处是,可以把数字和文字精准的分开。但是在换其他格式的表格可能会出现一些问题。当然,在本项目中,如果只使用同种格式的表格,该方法是十分高效且便利的。

A3

  这一部分任务主要是对大量的数据进行处理,然后通过得到的模型对年龄和性别进行预测。在这一部分中,我使用了sklearn库中的svm模型,达到了70%的准确率,实现代码如下:

#coding = utf-8
import pickle
import numpy as np
from sklearn import svm
from sklearn import metrics
from sklearn.cross_validation import train_test_split
def extract(filename):
X = np.loadtxt(filename, skiprows= 1,delimiter=',', usecols=(3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28))
y = np.loadtxt(filename, dtype='string', skiprows= 1,delimiter=',', usecols=(1,))
for i in range(len(y)):
if y[i] == '\xc4\xd0':
y[i] = 1
else:
y[i] = 0
return X,y
def split_test(X,y):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)
return X_train, X_test, y_train, y_test
def save_model(model,name):
pickle.dump(model, open(str(name)+'.pkl', 'w'))
def load_model(name):
model = pickle.load(open(str(name)+'.pkl'))
return model
if __name__ == "__main__":
X, y = extract('train.csv')
X_train, X_test, y_train, y_test = split_test(X, y)
clf = svm.SVC(kernel='linear', gamma=0.7, C = 1.0).fit(X_train, y_train)
y_predicted = clf.predict(X_test)
print metrics.classification_report(y_test, y_predicted)
print
print "test_accuracy_score"
print metrics.accuracy_score(y_test, y_predicted)
save_model(clf,'sex')
X, y =extract('predict.csv')
clf2 = load_model('sex')
y2_predicted = clf2.predict(X)
print "accuracy_score"
print metrics.accuracy_score(y, y2_predicted)

  支持向量机(support vector machine)是一种分类算法,通过寻求结构化风险最小来提高学习机泛化能力,实现经验风险和置信范围的最小化,从而达到在统计样本量较少的情况下,亦能获得良好统计规律的目的。通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,即支持向量机的学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。

  SVM从线性可分情况下的最优分类面发展而来。最优分类面就是要求分类线不但能够将两类正确分开(训练错误率位0),且使分类间隔最大。SVM考虑寻找一个满足分类要求的超平面,并且是训练集中的点距离分类面尽可能的远,也就是寻找一个分类面使它两侧的空白区域(margin)最大。过两类样本中离分类面最近的点且平行于最优分类面的超平面上H1,H2的训练样本就叫做支持向量。这也是支持向量机的名称的由来。

  

  关于支持向量机的具体内容,可以参照手把手教你实现SVM算法这一系列文章。

集成:

  项目集成后再web端展示:

  1. 用户上传一张化验单:

  

  

  2. 点击生成报告,可以得到每一个项目的报告,如果生成的结果有误,用户可以手动纠正:

  

  3. 点击predict,可以对用户年龄和性别进行预测:

  

环境搭建:

#安装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

#安装PIL
sudo apt-get install python-imaging
#安装Tensorflow
pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl

#运行demo
cd  BloodTestReportOCR
python view.py # upload图像,在浏览器打开http://localhost:8080

本课心得:

  经过几个星期的艰苦奋战,在孟宁老师和全班所有学生的努力之下,终于完成了这个项目。我收获很多。

  在这门课的学习中,我了解到了很多机器学习的算法,从最简单的knn,到决策树,随机森林,svm,LR,贝叶斯等等,以及bp神经网络,卷积神经网络,递归神经网络包括LSTM等等,现在的状态就是对这些算法有了大致的了解,深入细节还是一知半解甚至有的还啥都不懂,在算法这一块,后边还有很多书要啃。

  对这门课的整体感受就是信息量巨大,很多来不及消化和实践,在课程结束后还要继续深究。关于Git多人合作开发,从开始的迷茫体会不到好处到后来被深深折服,孟宁老师作为项目的总指挥,布置阶段性任务的方式使我们一步实现一个小目标,成就感十足,同时深感人多力量大,以后遇到同样的情况要多做贡献!对于文档,以前一直忽略,现在越来越体会到了其重要性,虽然自己还写的很烂,但要养成写文档的好习惯,不然别说别人看不懂,时间久了自己的代码都要看不懂了。 
总之,收获满满,一切才刚刚开始,要学的还有很多!

    

np2016课程总结的更多相关文章

  1. .NET 提升教育 第一期:VIP 付费课程培训通知!

    为响应 @当年在远方 同学的建议,在年前尝试进行一次付费的VIP培训. 培训的课件:点击下载培训周期:10个课程左右,每晚1个半小时培训价格:1000元/人.报名方式:有意向的请加QQ群:路过秋天.N ...

  2. 14门Linux课程,打通你Linux的任督二脉!

    Linux有很多优点:安全.自主.开源--,也正是这些优点使得很多人都在学Linux. 虽说网上有大把的Linux课程资源,但是对很多小白来说网上的课程资源比较零散并不适合新手学习. 正因为此,总结了 ...

  3. 在线课程笔记—.NET基础

    关于学习北京理工大学金旭亮老师在线课程的笔记. 介绍: 在线课程网址:http://mooc.study.163.com/university/BIT#/c 老师个人网站:http://jinxuli ...

  4. [LeetCode] Course Schedule II 课程清单之二

    There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...

  5. [LeetCode] Course Schedule 课程清单

    There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...

  6. DDD建模案例----“视频课程”场景

    接触领域驱动设计DDD有一年多的时间了,中间看过不少书,参与过一些讨论(ENode QQ群).目前对DDD的认知还停留在理论阶段,所以对领域建模非常感兴趣,这里说的建模是指以DDD的思想为指导再加上D ...

  7. 课程上线 -“新手入门 : Windows Phone 8.1 开发”

    经过近1个月的准备和录制,“新手入门 : Windows Phone 8.1 开发”系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microsoftvirtuala ...

  8. Hibernate注解----关联映射注解以及课程总结详解----图片版本

    上一篇,记录了Hibernate注解----类级别注解以及属性注解详解 ,我们这一节主要讲解的是Hibernate注解----关联映射注解以及课程总结详解. 本节的主要内容: 第3章 关联映射注解 3 ...

  9. 《Java程序设计》 课程教学

    <Java程序设计> 课程教学 给学生 考核方式 100分构成 翻转课堂考核12次(5*12 = 60):每次考试20-30道题目,考试成绩规格化成5分(比如总分20分就除以4) 注意:不 ...

随机推荐

  1. Java多线程开发系列之三:线程这一辈子(线程的生命周期)

    前文中已经提到了,关于多线程的基础知识和多线程的创建.但是如果想要很好的管理多线程,一定要对线程的生命周期有一个整体概念.本节即对线程的一生进行介绍,让大家对线程的各个时段的状态有一定了解. 线程的一 ...

  2. Java多线程开发系列之二:如何创建多线程

    前文已介绍过多线程的基本知识了,比如什么是多线程,什么又是进程,为什么要使用多线程等等. 在了解了软件开发中使用多线程的基本常识后,我们今天来聊聊如何简单的使用多线程. 在Java中创建多线程的方式有 ...

  3. html5,加密元素

    <form action="">    账号:<input type="text" name="user">     ...

  4. Linux 下 PHP 扩展 cURL 编译安装

    下载 cURL http://pan.baidu.com/s/1hqrHWkG (curl-7.39.0.tar.gz) 3.98MB 解压: tar zxvf curl-7.39.0.tar.gz ...

  5. ceph_deploy部署ceph分布式文件系统

    1.前期准备:centos6.5 minimal版本3台 选择其中一台作为一个安装节点,能无密码登录其他机器.ssh-keygen ssh-keygen -i ~/.ssh/id_rsa.pub no ...

  6. 在DOM中搜索元素

    方法 现代浏览器中使用XPath document.getElementById document/node.getElementsByTagName Limit search by parent e ...

  7. 161230、利用代理中间件实现大规模Redis集群

    前面在<大规模互联网应用Redis架构要点>和<Redis官方集群方案 Redis Cluster>两篇文章中分别介绍了多Redis服务器集群的两种方式,它们是基于客户端sha ...

  8. ubuntu vim8.0源码安装

    安装篇 从https://github.com/vim/vim下载相应zip源码文件,利用unzip vim-master.zip 命令解压到当前用户目录,即~: 解压后进入vim的src目录,首先, ...

  9. MySQL时间段查询,无数据补0

    上一节提到分时间段统计,可是无数据的时候不显示,而此时我们需要让他显示0. 首先我们需要建一个时间表. CREATE TABLE `my_date` ( `date` date NOT NULL, P ...

  10. IOS OC数据类型

    1.只有浮点型数据除以0.0才能得到+-无穷大的数,而整形或char型数据会得到边界值 2.BOOL的实际类型是signed char,他的底层只占一个字节(只有八位),如果将一个较大的非零整数值赋给 ...