网络程序设计课程总结

姓名:万溪吟 学号:sa16225276

1.课程相关知识

神经网络模型
所谓神经网络就是将许多个单一“神经元”联结在一起,这样,一个“神经元”的输出就可以是另一个“神经元”的输入。神经网络由能够互相通信的节点构成,赫布理论解释了人体的神经网络是如何通过改变自身的结构和神经连接的强度来记忆某种模式的。而人工智能中的神经网络与此类似。请看下图,最左一列蓝色节点是输入节点,最右列节点是输出节点,中间节点是隐藏节点。该图结构是分层的,隐藏的部分有时候也会分为多个隐藏层。如果使用的层数非常多就会变成我们平常说的深度学习了。

例如,下图就是一个简单的神经网络:
这里写图片描述
我们使用圆圈来表示神经网络的输入,标上“\textstyle +1”的圆圈被称为偏置节点,也就是截距项。神经网络最左边的一层叫做输入层,最右的一层叫做输出层(本例中,输出层只有一个节点)。中间所有节点组成的一层叫做隐藏层,因为我们不能在训练样本集中观测到它们的值。同时可以看到,以上神经网络的例子中有3个输入单元(偏置单元不计在内),3个隐藏单元及一个输出单元。

本例神经网络的计算步骤如下:

a(2)1a(2)2a(2)3hW,b(x)=f(W(1)11x1+W(1)12x2+W(1)13x3+b(1)1)=f(W(1)21x1+W(1)22x2+W(1)23x3+b(1)2)=f(W(1)31x1+W(1)32x2+W(1)33x3+b(1)3)=a(3)1=f(W(2)11a(2)1+W(2)12a(2)2+W(2)13a(2)3+b(2)1)

这样我们就可以得到一种更简洁的表示法。这里我们将激活函数 \textstyle f(\cdot) 扩展为用向量(分量的形式)来表示,即 \textstyle f([z_1, z_2, z_3]) = [f(z_1), f(z_2), f(z_3)] ,那么,上面的等式可以更简洁地表示为:

z(2)a(2)z(3)hW,b(x)=W(1)x+b(1)=f(z(2))=W(2)a(2)+b(2)=a(3)=f(z(3))

我们将上面的计算步骤叫作前向传播。回想一下,之前我们用 \textstyle a^{(1)} = x 表示输入层的激活值,那么给定第 \textstyle l 层的激活值 \textstyle a^{(l)} 后,第 \textstyle l+1 层的激活值 \textstyle a^{(l+1)} 就可以按照下面步骤计算得到:

z(l+1)a(l+1)=W(l)a(l)+b(l)=f(z(l+1))

将参数矩阵化,使用矩阵-向量运算方式,我们就可以利用线性代数的优势对神经网络进行快速求解。

机器学习框架tensorflow
TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow为张量从流图的一端流动到另一端计算过程。TensorFlow是将复杂的数据结构传输至人工智能神经网中进行分析和处理过程的系统。
TensorFlow可被用于语音识别或图像识别等多项机器深度学习领域,对2011年开发的深度学习基础架构DistBelief进行了各方面的改进,它可在小到一部智能手机、大到数千台数据中心服务器的各种设备上运行。TensorFlow将完全开源,任何人都可以用。TensorFlow支持CNN、RNN和LSTM算法,这都是目前在Image,Speech和NLP最流行的深度神经网络模型。
官方文档中文版:http://wiki.jikexueyuan.com/project/tensorflow-zh/

OCR
OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程;即,针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,并通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术。如何除错或利用辅助信息提高识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也因此而产生。衡量一个OCR系统性能好坏的主要指标有:拒识率、误识率、识别速度、用户界面的友好性,产品的稳定性,易用性及可行性等。

2.项目介绍

本课程主要学习神经网络程序设计,基于深度学习神经网络等机器学习技术实现一个医学辅助诊断的专家系统原型,具体切入点为课程项目:对血常规检验报告的OCR识别、深度学习与分析。实现下列项目:

A1:神经网络实现手写字符识别系统
用户在一个20*20的画布上写下一个数字,通过神经网络的训练,便可预测出数字为多少。用于手写识别的一个神经网络,有一组输入神经元。输入神经元会被输入图像的数据所激发。在激励值被加权并通过一个函数后,这些神经元的激励值被传递到其他神经元。这个过程不断重复,直到输出神经元被激发。最后,输出神经元的激励值决定了识别出来的是哪个数字。

A2:血常规检验报告的图像OCR识别
A3:根据血常规检验的各项数据预测年龄和性别
将A2和A3进行整合,最终实现一个完整的web系统,实现:用户上传一张血常规报告单的图片,提交的结果是图片存储到了mongodb数据库得到一个OID或到指定目录到一个path。图片识别得到一个json数据存储到了mongodb数据库得到一个OID,json数据。自动截取目标区域,不同旋转角度的图片自动准备截取目标区域,处理。ocr识别得出每项的数值,上部是原始图片,下部是一个显示识别数据的表格,以便对照识别结果。最后根据血常规检验的各项数据预测年龄和性别。

3.项目实现

版本库url

版本库地址:https://coding.net/u/wxiy/p/np2016/git

安装运行说明

运行环境

# 安装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
$ sudo apt-get install python-numpy
$ sudo apt-get install python-imaging
$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl

运行

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

运行结果

(1)web首页,可进行血常规检验报告图片的上传
这里写图片描述
(2)提交图片系统显示处理过的合格图片
这里写图片描述
(3)点击生成报告得出识别结果
这里写图片描述
(4)点击预测,得出结果
这里写图片描述

.项目分析

项目模块

对整个项目做一个回顾,并对其中的重点部分做一些详细的分析。
(1) 图片处理及orc识别
a. 对整张图片做预处理及线段检测

#灰度化
img_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
#高斯平滑
img_gb = cv2.GaussianBlur(img_gray, (gb_param,gb_param), 0)
#canny算子边缘检测
edges = cv2.Canny(opened, canny_param_lower , canny_param_upper)
#调用CV2模块的findContours提取矩形轮廓,筛选对角线大于阀值的轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE,
 cv2.CHAIN_APPROX_SIMPLE)
#求最小外接矩形
def getbox(i):
            rect = cv2.minAreaRect(contours[i])
            box = cv2.cv.BoxPoints(rect)
            box = np.int0(box)
            return box

这里写图片描述
将轮廓变成线:比较最小外接矩形相邻两条边的长短,以两条短边的中点作为线的两端;
若线数量大于三则根据线长短继续筛选长线。根据三条线间的距离确定表格头部和内容的位置;

这里写图片描述
b.透视变换

#使用透视变换将表格区域转换为一个1000*760的图
PerspectiveMatrix = cv2.getPerspectiveTransform(points,standard)

self.PerspectiveImg = cv2.warpPerspective(self.img,PerspectiveMatrix, (1000, 760))

c.将图片内容分割为个别的数据,返回正面图与报告单内容每项的剪切图 ,在temp_pics文件夹中生成
这里写图片描述

d.对每份数据调用pytesserac的OCR库进行识别

(2)预测
本次项目采用的是tensorflow预测年龄性别,项目中采用的是训练好的模型进行预测
预测流程:

数据预处理(一般是归一化)常见的归一化方法

def normalized(a,b):
    for i in range(22):
        tmp = np.mean(a[:, i])
        a[:, i] = a[:, i] - tmp
        b[:, i] = b[:, i] - tmp
        if np.min(a[:, i]) != np.max(a[:, i]):
            b[:, i] = 2 * (b[:, i] - np.min(a[:, i])) / (np.max(a[:, i]) - np.min(a[:, i])) - 1
        else:
            b[:, i] = 0
    return b

tensorflow 初始化并预测

def predict(data_predict):
    tf.reset_default_graph()
    data_nor = np.loadtxt(open("./data.csv", "rb"), delimiter=",", skiprows=0)
    data_predict = normalized(data_nor[:, 2:], data_predict)
    '''
        参数
        '''
    learning_rate = 0.005
    display_step = 100
    n_input = 22
    n_hidden_1_age = 32
    n_hidden_2_age = 16
    n_classes_age = 1
    n_hidden_1_sex = 16
    n_hidden_2_sex = 8
    n_classes_sex = 2
    data = np.loadtxt(open("./data.csv", "rb"), delimiter=",", skiprows=0)
    '''
    建立年龄模型
    '''
    x_age = tf.placeholder("float", [None, n_input])
    y_age = tf.placeholder("float", [None, n_classes_age])
    def multilayer_perceptron_age(x_age, weights_age, biases_age):
        # Hidden layer with RELU activation
        layer_1 = tf.add(tf.matmul(x_age, weights_age['h1']), biases_age['b1'])
        layer_1 = tf.nn.relu(layer_1)
        # Hidden layer with RELU activation
        layer_2 = tf.add(tf.matmul(layer_1, weights_age['h2']), biases_age['b2'])
        layer_2 = tf.nn.relu(layer_2)
        # Output layer with linear activation
        out_layer = tf.matmul(layer_2, weights_age['out']) + biases_age['out']
        return out_layer
    weights_age = {
        'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1_age])),
        'h2': tf.Variable(tf.random_normal([n_hidden_1_age, n_hidden_2_age])),
        'out': tf.Variable(tf.random_normal([n_hidden_2_age, n_classes_age]))
    }
    biases_age = {
        'b1': tf.Variable(tf.random_normal([n_hidden_1_age])),
        'b2': tf.Variable(tf.random_normal([n_hidden_2_age])),
        'out': tf.Variable(tf.random_normal([n_classes_age]))
    }
    pred_age = multilayer_perceptron_age(x_age, weights_age, biases_age)
    '''
    建立性别模型
    '''
    x_sex = tf.placeholder("float", [None, n_input])
    y_sex = tf.placeholder("float", [None, n_classes_sex])
    def multilayer_perceptron_sex(x_sex, weights_sex, biases_sex):
        # Hidden layer with RELU activation
        layer_1 = tf.add(tf.matmul(x_sex, weights_sex['h1']), biases_sex['b1'])
        layer_1 = tf.nn.relu(layer_1)
        # Hidden layer with RELU activation
        layer_2 = tf.add(tf.matmul(layer_1, weights_sex['h2']), biases_sex['b2'])
        layer_2 = tf.nn.relu(layer_2)
        # Output layer with linear activation
        out_layer = tf.matmul(layer_2, weights_sex['out']) + biases_sex['out']
        return out_layer
    weights_sex = {
        'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1_sex])),
        'h2': tf.Variable(tf.random_normal([n_hidden_1_sex, n_hidden_2_sex])),
        'out': tf.Variable(tf.random_normal([n_hidden_2_sex, n_classes_sex]))
    }
    biases_sex = {
        'b1': tf.Variable(tf.random_normal([n_hidden_1_sex])),
        'b2': tf.Variable(tf.random_normal([n_hidden_2_sex])),
        'out': tf.Variable(tf.random_normal([n_classes_sex]))
    }
    pred_sex = multilayer_perceptron_sex(x_sex, weights_sex, biases_sex)
    '''
    共同的初始化
    '''
    saver = tf.train.Saver()
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        saver.restore(sess, "./model.ckpt")
        print ("load model success!")
        p_sex = sess.run(pred_sex, feed_dict={x_sex: data_predict})
        p_age = sess.run(pred_age, feed_dict={x_age: data_predict})
    if p_sex[0][0] > p_sex[0][1]:
        sex_result = 1
    else:
        sex_result = 0
    age_result = p_age[0][0] * 50 +50
    return sex_result,age_result

(3)web整合
Vue.js :实现响应的数据绑定和组合的视图组件。
Web框架:Flask,主要用于处理前端的http请求。
json;传输数据

文件描述

view.py
从Web端上传图片到服务器,存入mongodb数据库并获取oid,调用imageFilter.py和tf_predict.py等文件中的函数进行图像处理、OCR识别和分析预测,并将识别结果显示到Web端

imgproc.py

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

imageFilter.py
对图像透视裁剪和OCR进行了简单的封装,以便于模块间的交互,规定适当的接口封装了图像处理和OCR识别函数。图像处理包括载入图像,灰度化,开闭运算,描绘边缘,并提取轮廓,剪裁出各体检项目编号及数据的图片。
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

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

digits

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

tf_predict.py
用于实现得出的数据后的性别年龄预测。

4.课程心得体会

学习笔记
使用TensorFlow创建手写识别
使用caffe实现性别年龄预测

经过短短7周紧张又充实的学习,我有了很多有关网络程序设计这门课程的收获与感想。首先,这门课程的授课模式是十分新颖的,不同于传统的授课模式,每位同学都亲身参与一个项目的开发,熟悉一个完整项目的开发过程,并在这个过程中通过自己查询资料、与同学交流讨论等等方式学习了有关神经网络的相关模型、算法、ocr识别等相关知识。 这种方式极大的提高了我们去广泛深入学习的必要,让大家能真正的学以致用,在实践中学习,跟随着项目,真正的学到了许多。
就我个人而言,很惭愧,在整个项目的过程中没有做出什么贡献,仅仅是跟着大家的脚步去学习。通过平时课堂上的同学对深度学习相关算法的分享以及在项目中pr的代码的学习。我收获了很多。
另外通过这次的上课模式,我对团队合作完成一个项目也有了许多认识。首先是合作的重要性,大家相互学习、相互促进对开发效率有很大的提高,同时思维碰撞的过程也带来了很多灵感和想法,同时也可以让不同同学的专长得以利用,大家更好的相互学习。再有就是需要主动参与到项目中去,积极pr,贡献自己力量的的同时也可以帮助自己更好的参与、理解整个项目。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值