OCR可能是实际落地最广最多的人工智能应用了,生活中各种各样的场景都可以使用到它,例如识别车牌号、身份证、发票等。
在研究学习中,我们可能更加注重于通用OCR识别能力,但是企业往往要求不仅能识别出图片上的文字,还要提供结构化的数据供后台系统进行处理。
一种常见的结构化思路就是通过模板匹配来进行处理,这里先说下大致的步骤:
- 首先需要准备一张模板图片,然后送入通用OCR中识别出所有的文字以及对应的坐标;
- 选取一些容易识别且分布比较分散的字段作为定位字段,记录好字段值和坐标区域,最少选取四个区域,用于后续求解投影变换矩阵;
- 对模板上的字段进行分析,挑选出后续结构化需要的数据作为识别字段,记录好坐标区域;
- 上述步骤为前期准备,现在开始一张测试图片的处理流程,首先识别出测试图片的所有文字和坐标区域;
- 在测试图片的识别结果中搜索匹配模板的定位字段,从而得到了两组坐标区域值,一组来自模板,一组来自测试图片;
- 通过这两组坐标区域(实际上,每个区域选取一个坐标点即可,默认选取左上角的坐标点)求出投影变换矩阵,然后利用矩阵将投影变换作用到测试图片上的所有坐标区域,得到一组新的坐标区域,称为测试图片的投影坐标区域;
- 把模板识别字段的坐标区域与测试图片的投影坐标区域作iou计算,求出每个识别字段最匹配的投影坐标区域;
- 测试图片的每个投影坐标区域都对应一个识别结果,因此,对于模板的每个识别字段,我们都找到了一个识别结果,将其做一些正则化处理返回即可。
代码细节
这里给出几个关键的代码
计算投影变换矩阵
import numpy as np
import cv2
pts1 = np.float32([[0,0], [1,1], [2,2], [3,3]])
pts2 = np.float32([[0,0], [1,1], [2,2], [3,3]])
m = cv2.getPerspectiveTransform(pts1, pts2)
进行投影变换
import numpy as np
import cv2
def transform(m, points):
pts = np.float32([points])
new_pts = cv2.perspectiveTransform(pts, m)
return new_pts[0]
不规则四边形iou计算
from shapely.geometry import Polygon
def cal_iou(area1, area2):
poly1 = Polygon(area1)
poly2 = Polygon(area2)
if not poly1.intersects(poly2):
return 1e-6
inter_area = poly1.intersection(poly2).area
union_area = poly1.area + poly2.area - inter_area
return inter_area / (union_area + 1e-6)