机器学习AI算法工程 公众号:datayx
最近做了个手写汉字简历识别比赛,需要先提取表格中含有指定信息的各个框,再用TensorFlow对框中的信息进行汉字、数字、英文识别。
所有代码获取:
本文相关代码 项目获取方式:
关注微信公众号 datayx 然后回复 简历 即可获取。
AI项目体验地址 https://loveai.tech
网上对表格框的提取的相关资料较少,尤其是Python+OpenCV的实现方面。
整体流程
该算法的主体思路是:通过对旋转、平移校正的表格用开操作提取网格,获取各信息所在的矩形位置;根据各信息对应的大致中心坐标筛选出对应的矩形,进行文字分割后,将汉字、ABO字母、数字分别输入卷积神经网络进行识别,得到的结果进行校验后即写入CSV文件。
程序主要分成九个Python文件:ABO_mix.py实现的是基于卷积神经网络的手写ABO字母识别,chinese_ocr.py实现的是基于卷积神经网络的手写汉字识别,chinese_out.py实现的是对手写汉字、字母的分割,chinese_out_jiguan.py实现的是对手写汉字(籍贯部分)的分割,mnist_recognize.py实现的是基于卷积神经网络的手写数字识别,num_out.py实现的是对手写数字的分割,time_out.py实现的是对手写时间数字的分割,time_recognize.py实现的是基于卷积神经网络的手写时间数字识别,table_choose.py实现的是表格预处理、函数调用与识别结果的写入。
整体的工作量有点大,此篇先介绍如何对表格中各个框进行提取,此部分代码位于table_choose.py文件中的前半部分,本文中摘取部分进行说明,具体可见上文开源Github代码链接。笔者先前用的都是C++版的OpenCV,因为TensorFlow识别部分的代码基于python,为了减少工作量,这次就顺便使用了Python版的OpenCV,需要在OpenCV编译时补全Python项,并复制cv2.so和cv.py文件【重要!否则import cv2会提示找不到module,见https://www.cnblogs.com/freeweb/p/5794447.html】。
如今OpenCV官方的Document里都包含了各API的Python版用法,从C++转换到Python用起来意外的顺手。这里附上官方的在线Document地址,记得选对应版本:https://docs.opencv.org/
该部分的编译环境如下:
(1)Ubuntu16.04 64位 支持utf-8编码
(2)Python2.7
(3)OpenCV3.4.3 (与Python2.7编译通)
(4)Python2.7 numpy模块、PIL模块、logging模块、pickle模块、os模块、random模块、time模块、matplotlib模块、math模块、csv模块
Python+OpenCV校正并提取表格中的各个框的整体代码table_choose.py(其中包含识别部分的功能,提取表格的功能需要摘出来使用)
读取表格图片文件
这段即将test_data文件中的所有文件进行遍历读取,也可注释最下方的两行,并去除docu_num一行的注释,即可对一张图片文件进行反复的读取、处理。
统计图中长横线的斜率来判断整体需要旋转矫正的角度
这段做的是旋转校正操作,先把表格图片转换为灰度图,再用Canny算子提取边缘(灰度+Canny是提取边缘的标准操作)得到如下这张图片edges_whole.jpg
可见,这张表格是倾斜的,需要对表格进行旋转。旋转需要参照物吧?笔者选择用霍夫变换HoughLinesP()对表格中的长直线进行识别并提取。然后再对这些长直线中斜率小于pi/4且大于-pi/4的直线进行筛选,统计它们的斜率平均值。这样除非这张表格的倾斜度超过45度,或者表格中含有人为划的长横线,这个斜率平均值都可以作为校正旋转的角度了。长直线筛选后的图片见下图line_detect4rotation.jpg:
之后便是用getRotationMatrix2D()、warpAffine()函数进行旋转变换,此处笔者拷贝了一份不进行绘图操作的图片(不然都涂花了,干嘛为难自己)。旋转后的表格图片如下image_Rotation.jpg:
通过对表格左下角直角进行识别,将其顶点统一平移矫正至(78,1581)
这段做的是平移校正操作,其中大部分是为了应对数据集中的各种意外情况,譬如表格形式不同。但对于Github中给出的三幅较为统一的图片,核心的操作只有对旋转校正后的表格左下角进行横线、竖线用HoughLinesP()进行提取,归一后求二者的交点。将交点平移至设定好的坐标即可统筹处理所有表格图片。此处对霍夫变换求出的各条直线分别与设定好两个等分点进行距离求解,选出最靠近等分点的横线、竖线作为归一结果。求得交点坐标后用np.array()函数与cv.warpAffine()函数即可完成平移操作。
横线、竖线的交点求得后在旋转后的表格图像上作图如下line_detect_possible_demo.jpg:
分别通过对二值化后的表格用长横条、长竖条内核进行开操作,将表格分别化为全横线与全竖线,叠加后提取交点,即可得到表格中每个矩形的四个顶点
此段是功能实现的核心操作:通过对校正图像进行横向、纵向的投影,并提取直线、直线交点,提取轮廓后通过所需表格框的尺寸数据对交点进行筛选、匹配,即可得到表格中的各个框四个顶点的坐标。此处理对表格中的小框效果拔群,对大型框进行提取可能遇到一框中有多个小框的情况,需要后续加以限制(统计该框内是否有别的顶点)。具体操作是:
对未涂花的原始图像进行灰度变化和自适应阈值的二值化操作adaptiveThreshold(),这样能最大可能地保留表格中的直线,效果如下图th2.jpg:
之后对图像进行先腐蚀erode()后膨胀dilate()的闭操作,腐蚀与膨胀分别使用N*1与1*N的形态学操作中的核进行处理。该操作可以理解为把表格中所有的像素进行横向、纵向的投影,且投影会往原先已存在直线上偏移,而文字状的不构成直线的像素则会在腐蚀操作中被抹消。就像从长条形的横、纵栅格中看表格图片一般。将横向、纵向投影好的图片进行叠加即如下图mask.jpg:
表格被神奇地提取出来了!这一步需要注意,一定要是旋转校正过的图像,因为对于一张倾斜的图像,投影操作会让图像变“正”了,实际上图像并没有被旋转过来,这对后续的坐标提取是致命的。既然已经提取出了表格框,那我们就可以通过bitwise_and()函数提取出表格框中的各个交点,如下图joints.jpg:
接下来即通过findContours()函数寻找图像轮廓,并用contourArea()函数求出各个轮廓的面积,以对过小的轮廓进行排除。通过approxPolyDP()与boundingRect()函数用矩形去包围各个轮廓,即可得到该表格图片中各个矩形框的位置数据。之后通过再次使用findContours()函数遍历图像轮廓,用尺寸数据对矩形框进行筛选即可得到表格中所需的框的集合。在校正图像上画出这个集合里的所有框,如下图table_out.jpg:
矫正后的表格中信息的大致位置各在一定范围内,根据大致位置的坐标点筛选出该表中该信息对应的矩形框具体坐标
既然框都已经被提取出来了,那不是大功告成了吗?
并没有。因为我们还需要对所需要的位置的框进行提取,先前提取出的框又不附带标签。因此我们此处需要做两步:
首先是选择标准图像中所需的框位置的中心点作为这个框的“ID”,标准图像即先前所说的坐标(78,1581)所在的那张图片。上文代码里即选择(700,370)作为“性别”数据的所在框的大致位置。
其次是通过遍历的方式筛选出这个中心点坐标所处在的矩形框的坐标。因为框较大,因此即使校正的不够精准,这种方法一样可以将目标框精准地框出,只要标准图像中的那个大致位置不偏移得太过严重。
不断更新资源
深度学习、机器学习、数据分析、python
搜索公众号添加: datayx
长按图片,识别二维码,点关注