前言
在医疗信息化进程不断推进的当下,医疗化验单的数字化处理成为提升医疗效率的关键环节。快瞳科技凭借在图像识别领域的深厚技术积累,成功攻克了医疗化验单 OCR 识别难题,为医疗行业的智能化转型提供了有力支持。
一、项目要求
快瞳科技与广州知名药企携手,旨在精准识别医疗化验单表格内容,尤其是化验数值和名称的准确率,要求达到85%以上。化验单上的三线表内容为本次项目的核心识别对象,而像姓名、年龄等表格外信息则不在本次识别范围内。
由于化验单来源多样,包括PDF版、手动拍照版以及拍摄电脑屏幕版,存在竖线、手写体等多种干扰因素,给识别工作带来了极大挑战。药企此前使用的识别模型准确率难以提升,因此将目光投向了快瞳科技,期望借助我们的技术实力解决这一难题。
二、解决思路
模型选择
本方案采用快瞳智能文档抽取模型作为基础。该模型在文字识别方面具有较高的准确率和良好的通用性,为项目的顺利开展奠定了坚实基础。
图像扶正
面对化验单图片存在倾斜角度、曲折等问题,快瞳科技深知必须先将图片扶正,使其处于水平状态,以提高OCR识别准确率。同时,扶正后的图片便于后续裁剪操作,进一步提升识别精度。
考虑到药企希望将此技术应用于小程序,对模型大小有一定限制,快瞳科技决定采用opencv技术来实现图片扶正。通过分析三线表的直线特征,计算其斜率并取平均值作为判断图片是否水平的依据。
在尝试多种opencv识别直线算法后,霍夫变换因其经典实用且经过调参优化后效果良好,成为最终选择。尽管样本干扰较多,霍夫变换仍能相对准确地识别出直线,为图片扶正提供了可靠依据。
图像裁剪
在解决图片倾斜问题后,快瞳科技发现仅将需要识别的表格裁剪出来,可显著提高识别精度。对于三线表,找出第一根和最后一根直线,即可实现表格的精准裁剪。
此外,针对双栏表(中间有一条竖线,分为两栏内容),快瞳科技采取将其裁剪成两部分的策略,进一步优化了识别效果,确保各类表格的识别精度都能得到充分保障。
完整流程
构建了一套完整的流程:将一张化验单图片输入后,先进行预处理,包括图片扶正和裁剪等操作,然后将预处理后的图片送入 PaddleOCR 模型进行识别,最后通过文字纠正(模型后处理)环节,输出高质量的识别结果。
import cv2
import numpy as np
import math
import os
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
for i in range(len(a)):
if cv2.arcLength(a[i],closed=True)>col/2 and cv2.arcLength(a[i],closed=True)<1.9*(col+row):
cv2.drawContours(img,a,i,(0,0,255),2)
coor=a[i]
break
if cv2.minAreaRect(coor)[2]<45:
imgs=self.rotate_bound(img,-(cv2.minAreaRect(coor)[2]))
else:
imgs=self.rotate_bound(img,90-(cv2.minAreaRect(coor)[2]))
cv2.namedWindow("before",cv2.WINDOW_NORMAL)
cv2.resizeWindow("before",1200,1200)
cv2.imshow("before",img)
cv2.imshow("after",imgs)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 霍夫变换
def find_lines(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,160,255,cv2.THRESH_BINARY)
dst=cv2.GaussianBlur(binary, (9,9), 0)
img=pic.copy()
edges = cv2.Canny(dst, 70, 150,)
lines = cv2.HoughLinesP(edges ,1,np.pi/180, 100,minLineLength= 200, maxLineGap=200)
slope_list=[]
for i in range(len(lines)):
x_1, y_1, x_2, y_2 = lines[i][0]
if (x_1-x_2)!=0:
slope_list.append(round((y_1-y_2)/(x_1-x_2),2))
cv2.line(img, (x_1, y_1), (x_2, y_2), (255, 0, 0), 3)
imgs=self.rotate_bound(img,-(math.degrees(math.atan(np.mean(slope_list)))))
cv2.namedWindow("before",cv2.WINDOW_NORMAL)
cv2.resizeWindow("before",1200,1200)
cv2.imshow("before",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
使用示例
pic_path= "pic6.png" #这里需改为实际的图片路径
rectify = RectifyBias(pic_path)
rectify.find_lines()
rectify.find_contour()
最终效果
三、总结
经过快瞳科技团队的不懈努力,项目取得了圆满成功。团队成员各司其职,通过多次尝试和优化,不仅成功解决了图片倾斜、干扰因素等难题,还实现了对不同表格形式的精准裁剪和识别。
最终,项目识别精度不仅达到了药企的要求,还实现了超越,为药企提供了高性价比的医疗化验单OCR识别解决方案,成功签订了合作协议。这不仅彰显了快瞳科技在图像识别领域的专业能力,也为公司在医疗行业的业务拓展树立了良好的口碑,为未来更多的医疗信息化项目奠定了坚实基础。