表格图片的内容识别
接到个任务需要将几万张带表格的图片转换成结构化数据。
1. 大步骤
最终算是完成任务,但是识别率上还有一点问题,人工再过一下,还是蛮快的。先说一下大的步骤:
- 分割单元格。将图片中的表格全部定位出来,然后按单元格裁剪成一个个小图片,以便后续分析及操作;
- 聚焦。其实就是将单元格中的文本区域裁剪出来,将多余的空白去掉;
- 大图片的识别。对于大图片用图像相似性的算法(phash+汉明距离)做识别;
- 小图片的识别。对于小图片,做字符分割,然后用NN做分类识别;
- 识别结果输出到txt;
- txt输出到excel。将全部txt按照目标表格的格式,解析输出到excel。
1.1 分割单元格
既然只关心表格区域,所以第一步先将各个单元格拆分出来,截取成一个个小图片。尝试用图像的膨胀、腐蚀来定位表格区域,图像处理包skimage,最后算是定位出了表格区域,也分割出了各个单元格图片,其中部分中间过程的图片如下:
分割单元格这一块的基本流程是:
- 读取图像;
- 二值化处理;
- 横向、纵向的膨胀、腐蚀操作,得到横线图img_row和竖线图img_col;
- 得到点图,img_row + img_col=img_dot;
- 得到线图,img_row × img_col=img_line(线图只是拿来看看的,后续没有用到);
- 浓缩点团到单个像素;
- 开始遍历各行的点,将各个单元格从二值图像上裁剪出来,保存到temp文件夹。
参考资料:
1.1.1 读取图像、二值化
import skimage
# 读取图片,并转灰度图
img=io.imread(imgFilePath,True)
#二值化
bi_th=0.81
img[img<=bi_th]=0
img[img>bi_th]=1
1.1.2 膨胀、腐蚀操作
# 膨胀腐蚀操作
def dil2ero(img,selem):
img=morphology.dilation(img,selem)
imgres=morphology.erosion(img,selem)
return imgres
# 求图像中的横线和竖线
rows,cols=img.shape
scale=80
col_selem=morphology.rectangle(cols//scale,1)
img_cols=dil2ero(img,col_selem)
row_selem=morphology.rectangle(1,rows//scale)
img_rows=dil2ero(img,row_selem)
1.1.3 得到点图、线图
# 线图
img_line=img_cols*img_rows
# 点图
img_dot=img_cols+img_rows_temp
img_dot[img_dot>0]=1
img_dot=clearEdge(img_dot,3)
1.1.4 浓缩点为单个像素
# 收缩点团为单像素点(3×3)
def isolate(img):
idx=np.argwhere(img<1)
rows,cols=img.shape
for i in range(idx.shape[0]):
c_row=idx[i,0]
c_col=idx[i,1]
if c_col+1<cols and c_row+1<rows:
img[c_row,c_col+1]=1
img[c_row+1,c_col]=1
img[c_row+1,c_col+1]=1
if c_col+2<cols