【项目总结】医疗化验单的OCR识别 您所在的位置:网站首页 验光单数据解读图片 【项目总结】医疗化验单的OCR识别

【项目总结】医疗化验单的OCR识别

2024-07-12 05:32| 来源: 网络整理| 查看: 265

项目总结

医疗化验单OCR

文章目录 项目总结前言一、项目要求二、解决思路1.模型1.扶正2.裁剪3.pipeline 三、总结

前言

课题组项目的总结。

一、项目要求

课题组和广州的一家药企有合作,甲方要求把一张医疗化验单内的表格内容整体识别出来,特别是化验的数值和名称的准确率,要求达到85%以上。

比如下面一张样本,三线表之外的内容都不需要我们负责(比如姓名、年龄这些),我们只需要把三线表里面的内容识别出来,特别是项目栏、结果栏的识别精度要高。但是很明显有很多干扰(竖线、手写体),这些都会严重影响识别精度。这还是PDF版的,属于干扰最少的,还有手动拍照的、拍摄电脑屏幕的样本更难识别。

请添加图片描述

甲方的要求就是我们把数值和名称的识别准确率优先提上去。甲方之前有一个识别模型,但是准确率提不上去,也想过找百度合作,但是成本太高,所以找到了我们课题组。

二、解决思路 1.模型

OCR模型我们选用的是百度开源的PaddleOCR。 Git:PaddleOCR

1.扶正

由于要识别的样本不是很规整,有PDF、手动拍照、拍电脑屏幕的。这就导致样本有各种各样的倾斜角度,有的照片甚至有曲折,这给OCR识别造成了很大的困扰。所以针对这些干扰,首先解决倾斜问题,要把样本图片的角度扶正也就是成水平状态,这样能提高OCR的准确率。并且我们实验发现,如果把整张表传进去识别,准确率会很低。而如果只把我们需要的表格裁剪下来,那识别精度就会很高了,所以把图片扶正也是为了裁剪做准备。

甲方想要做成小程序,所以深度学习这方面就不考虑,要尽量减小模型,只能用opencv的技术。要把图片扶正,首先要找一个参考点,我们的思路是以表格的这些直线作为参考,计算他们的斜率是否为0来判断图片是否水平。

以三线表为例,通过opencv把三线表的三条直线识别出来,因为识别的直线有误差,所以决定计算三条直线的斜率取平均,平均斜率就是我们的判断依据。

opencv识别直线的算法其实有很多,我们也尝试了很多种例举两种。

一是通过找轮廓的方法,也就是opencv的cv2.findContours函数。根据找出轮廓的周长大小来把直线筛选出来。因为三线表的三条直线明显比其他的要长很多,自然周长也会大些。实验效果虽然也还不错,但是如果样本干扰太多,这个方法会有很大的误差,会找出很多非直线的轮廓。这个方法也就pass。 二是通过霍夫变换。霍夫变换是一个非常经典的算法,简单实用。霍夫变换实验的效果一开始其实不是很好,因为样本真的没有想象那么好,非常非常多的干扰,识别出来的效果如下(蓝色线即霍夫变换识别出来的直线): 在这里插入图片描述 肉眼看很明显的三条直线直接识别出来几百条,霍夫变换不可能像人一样精准的标注出一条直线,它是根据像素之间的关系来计算的,所以看起来一个地方只有一条直线,其实它预测了很多条只是斜率相差很小很小,所以这就是为什么要取平均的另一个原因。后续就开始了调参之路(调参不是漫无目的地调要弄懂原理),有的样本适合这个参数有的适合另一个参数。调参后: 在这里插入图片描述

部分代码demo

class RectifyBias(): def __init__(self,pic_path): self.pic_path=pic_path #图片路径 def rotate_bound(self,image, angle): (h, w) = image.shape[:2] (cX, cY) = (w / 2, h / 2) M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0) cos = np.abs(M[0, 0]) sin = np.abs(M[0, 1]) nW = int((h * sin) + (w * cos)) nH = int((h * cos) + (w * sin)) M[0, 2] += (nW / 2) - cX M[1, 2] += (nH / 2) - cY return cv2.warpAffine(image, M, (nW, nH)) # 轮廓方法 def find_contour(self): pic=cv2.imdecode(np.fromfile(self.pic_path,dtype=np.uint8),cv2.IMREAD_COLOR) gray=cv2.cvtColor(pic,cv2.COLOR_BGR2GRAY) thresh, binary=cv2.threshold(gray,150,255,cv2.THRESH_BINARY) img=pic.copy() a,b=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) row,col=binary.shape # j=0 for i in range(len(a)): if cv2.arcLength(a[i],closed=True)>col/2 and cv2.arcLength(a[i],closed=True)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有