总结
来源:互联网 发布:美国特效软件 编辑:程序博客网 时间:2024/05/20 06:49
1 课程项目
1.1环境搭建
conda install tensorflowconda安装flask
conda install flaskpip安装pytesseract
sudo apt-get install tesseract-ocr sudo pip install pytesseract
pip安装mongo
sudo apt-get install mongodb # 如果找不到可以先sudo apt-get update sudo service mongodb started sudo pip install pymongo
运行
cd BloodTestReportOCR python view.py # upload图像,在浏览器打开http://yourip:8080
1.2 文件说明
view.py:web端上传图片到服务器,存入mongodb并获取id。
imageFilter.py:对图像透视裁剪和orc简单的封装,以便于模块之间交互
1.3 模块组成
1.3.1图像处理模块
先进行图像预处理,灰度化,二值化,腐蚀,膨胀,中值滤波去除噪点。
#灰度化 img_gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #Otsu thresholding 二值化 ret,result= cv2.threshold(img_gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) #腐蚀去除一些小的点 kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,2)) eroded = cv2.erode(result,kernel) #将结果放大便于识别 result = cv2.resize(result,(128,128),interpolation=cv2.INTER_CUBIC) # cv2.imshow('result',result) # cv2.waitKey(0) #腐蚀去除放大后的一些小的点 eroded = cv2.erode(result,kernel) # cv2.imshow('eroded',eroded) # cv2.waitKey(0) #膨胀使数字更饱满 result = cv2.dilate(eroded,kernel) # cv2.imshow('dilated',result) #直方图均衡化使图像更清晰 cv2.equalizeHist(result) #中值滤波去除噪点 result = cv2.medianBlur(result,5) # cv2.imshow('median',result) # cv2.waitKey(0) return result
然后对图片进行进行处理,描绘边缘,调用findContours提取轮廓,选择最大的三个轮廓,将轮廓变为线,根据这三条线来确定表头和表尾的位置。用透视转换将表格区域转化成1000*700的图。
# 载入图像,灰度化,开闭运算,描绘边缘 img_sp = self.img.shape ref_lenth = img_sp[0] * img_sp[1] * ref_lenth_multiplier img_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) img_gb = cv2.GaussianBlur(img_gray, (gb_param, gb_param), 0) closed = cv2.morphologyEx(img_gb, cv2.MORPH_CLOSE, kernel) opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel) edges = cv2.Canny(opened, canny_param_lower , canny_param_upper) # 调用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 def distance(box): delta1 = box[0]-box[2] delta2 = box[1]-box[3] distance1 = np.dot(delta1,delta1) distance2 = np.dot(delta2,delta2) distance_avg = (distance1 + distance2) / 2 return distance_avg # 筛选出对角线足够大的几个轮廓 found = [] for i in range(len(contours)): box = getbox(i) distance_arr = distance(box) if distance_arr > ref_lenth: found.append([i, box]) def getline(box): if np.dot(box[1]-box[2],box[1]-box[2]) < np.dot(box[0]-box[1],box[0]-box[1]): point1 = (box[1] + box[2]) / 2 point2 = (box[3] + box[0]) / 2 lenth = np.dot(point1-point2, point1-point2) return point1, point2, lenth else: point1 = (box[0] + box[1]) / 2 point2 = (box[2] + box[3]) / 2 lenth = np.dot(point1-point2, point1-point2) return point1, point2, lenth # 将轮廓变为线 line = [] for i in found: box = i[1] point1, point2, lenth = getline(box) line.append([point1, point2, lenth]) # 把不合适的线删去 if len(line)>3: for i in line: for j in line: if i is not j: rst = linecmp(i, j) if rst > 0: deleteline(line, j) elif rst < 0: deleteline(line, i) #检测出的线数量不对就返回-1跳出 if len(line) != 3: print "it is not a is Report!,len(line) =",len(line) return None def distance_line(i, j): dis1 = np.dot(i[0]-j[0], i[0]-j[0]) dis2 = np.dot(i[0]-j[1], i[0]-j[1]) dis3 = np.dot(i[1]-j[0], i[1]-j[0]) dis4 = np.dot(i[1]-j[1], i[1]-j[1]) return min(dis1, dis2, dis3, dis4) def findhead(i, j, k): dis = [] dis.append([distance_line(i, j), i, j]) dis.append([distance_line(j, k), j, k]) dis.append([distance_line(k, i), k, i]) dis.sort() if dis[0][1] is dis[2][2]: return dis[0][1], dis[2][1] if dis[0][2] is dis[2][1]: return dis[0][2], dis[2][2] def cross(vector1, vector2): return vector1[0]*vector2[1]-vector1[1]*vector2[0] # 由三条线来确定表头的位置和表尾的位置 line_upper, line_lower = findhead(line[2],line[1],line[0])知道了表格的尺寸,就可以进行裁剪了。
def autocut(self, num, param=default): if self.PerspectiveImg is None: self.PerspectivImg = self.filter(param) # 仍然是空,说明不是报告 if self.PerspectiveImg is None: return -1 #输出年龄 img_age = self.PerspectiveImg[15 : 70, 585 : 690] cv2.imwrite(self.output_path + 'age.jpg', img_age) #输出性别 img_gender = self.PerspectiveImg[15 : 58, 365 : 420] cv2.imwrite(self.output_path + 'gender.jpg', img_gender) #输出时间 img_time = self.PerspectiveImg[722 : 760, 430 : 630] cv2.imwrite(self.output_path + 'time.jpg', img_time) #转换后的图分辨率是已知的,所以直接从这个点开始读数据就可以了 startpoint = [199, 132] vertical_lenth = 37 lateral_lenth = 80 def getobjname(i, x, y): region_roi = self.PerspectiveImg[y : y+vertical_lenth, x : x+170] filename = self.output_path + 'p' + str(i) + '.jpg' cv2.imwrite(filename, region_roi) def getobjdata(i, x, y): region_roi = self.PerspectiveImg[y : y+vertical_lenth, x : x+lateral_lenth] filename = self.output_path + 'data' + str(i) + '.jpg' cv2.imwrite(filename, region_roi) #输出图片 if num <= 13 and num > 0: for i in range(num): getobjname(int(i), 25, startpoint[1]) getobjdata(int(i), startpoint[0], startpoint[1]) startpoint[1] = startpoint[1] + 40 elif num > 13: for i in range(13): getobjname(int(i), 25, startpoint[1]) getobjdata(int(i), startpoint[0], startpoint[1]) startpoint[1] = startpoint[1] + 40 startpoint = [700, 135] for i in range(num-13): getobjname(int(i+13), 535, startpoint[1]) getobjdata(int(i+13), startpoint[0], startpoint[1]) startpoint[1] = startpoint[1] + 40 #正常结束返回0 return 0最后进行识别。
1.3.2字符识别模块
1.3.3预测模块
预测用sklearn中sklearn.ensemble.RandomForestClassifier随机森林算法来进行预测。随机森林,指的是利用多棵树对样本进行训练并预测的一种分类器。对于每棵树,它们使用的训练集是从总的训练集中有放回采样出来的,这意味着,总的训练集中的有些样本可能多次出现在一棵树的训练集中,也可能从未出现在一棵树的训练集中。在训练每棵树的节点时,使用的特征是从所有特征中按照一定比例随机地无放回的抽取的,根据Leo Breiman的建议,假设总的特征数量为M,这个比例可以是sqrt(M),1/2sqrt(M),2sqrt(M)。
2 课程心得
转眼,课程已进入尾声,网络程序设计的上课形式与其他的课程不太一样,由同学主导课堂,每周都会有同学上台分享自己最近新学的知识和代码。这对提升我们的演讲水平和编码能力很有帮助。我讲的是A1手写字符神经网络,发现很多时候自己能理解的东西,未必能准确的表达出来。其实还是因为自己对某些知识点一知半解,没有完全理解。倘若能完全理解,自然就能用自己的话表述出来。还有就r是自己上台演讲没有做好充足的准备,讲解不够流畅,时间也没能掌握好。最好能提前演练一两遍,控制好时间和讲解速度,这样才能确保自己的内容能够顺利讲完。本课程还有很多有意思的任务,这些对我来说都是第一次接触,我们可以自己选择做一些力所能及的工作,也可以学习一些大神们提交的代码。但我觉得最好的方式还是去强迫自己去接受一个任务并独立完成,要相信自己,可能不试一次,你永远也不会知道自己竟有这样的潜能。哪怕最后无法完成,我相信这个过程中你也会学到很多东西。再有就是git的学习使用,git是个很实用的工具,很多公司都在使用,互联网公司大都是多人协作开发,就需要要像git一样的版本控制工具。尤其是以后当我主导一个项目的时候,我知道可以用git来提高团队的开发效率。
最后感谢老师对这个项目的维护,对每个pr都认真处理,给出修改意见。也感谢同学提交的代码,让我有能学习的机会。希望下学期能继续选孟老师的高软,听说又会有很多高质量的代码可以学习。
pull request:
1.https://coding.net/u/mengning/p/np2016/git/pull/171 随机森林73%性别预测正确率(拒绝)
2.https://coding.net/u/mengning/p/np2016/git/pull/89 前端不合格图片弹框显示(接受)
知识分享:
1.准备ppt重点分析本项目中使用的神经网络算法,应该先介绍算法涉及的主要原理等数学知识再具体解释算法的实现代码
2.非监督kmeans算法分享