ocr 识别身份证后如何对文本块进行排序?

203 天前
 qinyui

在使用 PaddleOCR 对身份证图片进行 OCR 识别时,识别到的文本是一块一块的,并且是乱序的

现在识别到的文本块列表是这样的: ['姓名张小明', '出生 1997 年 2 月 7 日', '性别男', '民族汉','荣街金明路 12', '住址', '河南省平顶山市卫东区繁', '号', '公民身份号码', '410221199702071234']

同时还有每个文本块对应的四个点的坐标信息,如: [[283.0,581.0],[396.0,573.0],[398.0,613.0],[285.0,620.0]]

为了后续的关键信息提取更方便,现在想对文本块先进行排序处理

根据坐标信息,如何对文本块按照从上到下从左到右的顺序进行排序?

比如示例的数据,排序后预期应该输出如下: ['姓名张小明', '性别男', '民族汉','出生 1997 年 2 月 7 日', '住址', '河南省平顶山市卫东区繁', '荣街金明路 12', '号', '公民身份号码', '410221199702071234']

或者有没有其他更好的思路?

1392 次点击
所在节点    Python
19 条回复
woodfizky
203 天前
反过来想,姓名、民族、性别、身份证号码,这些格式都是固定的,可以固定判断拿出来。

剩下的就是住址,按 x 坐标排序后拼接得到原始住址。
woodfizky
203 天前
另外,没用过这个 OCR ,但是一般 OCR 不都是同一行是一块文本吗,而且为什么你这里的符号被干掉了。。
noyidoit
203 天前
调公有云身份证 OCR 接口,直接从 key-value 的响应里取值 XD ;这个提取出来的文本块列表感觉有点太乱了,而且对少数民族身份证可能会支持不太友好
edward1987
203 天前
先自己裁切每一部分图片后再去识别,地址的话就分两行两部分识别
qinyui
203 天前
@woodfizky 一般一块的文本是连着的,示例的地址是因为太长在身份证上占了三行,这种识别出来就是三个文本块
qinyui
203 天前
@woodfizky 现在麻烦的就是识别出来的地址文本是被拆分的,并且”姓名“和名字有时也是分开的,还有性别民族等文本的干扰,直接提取是很难区分的
qinyui
203 天前
@edward1987 是个思路,就是实现成本有些高,需要先裁剪出身份证图片再定位每个区域,精度可能会是个问题,还有分多次识别的话整体速度也可能会变慢
qinyui
203 天前
@noyidoit 现在用的就是百度云的身份证 OCR 识别,就是长期使用成本有点高,才想自己研究下的
mMartin
202 天前
paddleocr 有 ser 啊 自动对应关系的
mMartin
202 天前
关键信息提取 paddleocr 本身就支持的 尤其是身份证这种场景简单的
mMartin
202 天前
tarasha
202 天前
我也是用的百度的 ocr-kie 。kie 可以将识别出的文本分类,例如:
{'NAME_KEY': [], 'NAME_VALUE': ['姓名张三'], 'SEX_KEY': ['性别男民族汉'], 'SEX_VALUE': [], 'NATION_KEY': [], 'NATION_VALUE': []}
唯一需要排序的场景是地址的提取,因为地址可能会换行。
我的办法是通过对比地址和证件号码的位置关系,确定照片的角度是哪一种,然后再依据每种角度来排序
0°:左上角 Y 点从小到大
90°:左上角 X 点从大到小
180°:左上角 Y 点从大到小
270°:左上角 X 点从小到大

# points 结构为 [[左上角 X, 左上角 Y], [右上角 X, 右上角 Y], [右下角 X, 右下角 Y], [左下角 X, 左下角 Y]]
# X 从左至右增大,Y 从上至下增大
# 计算地址文本块水平宽度 右上角 X - 左上角 X
x_length = address_points[1][0] - address_points[0][0]
# 计算地址文本块垂直高度 左下角 Y - 左上角 Y
y_length = address_points[3][1] - address_points[0][1]
# 判断图片是否水平
# 若地址文本块水平宽度大于垂直高度则说明图片处于 0°或 180°,否则处于 90°或 270°
is_horizontal = x_length > y_length
# 判断图片是否反转
# 若水平且地址文本块左上角 Y 点大于证件号码文本块左上角 Y 点 (即地址位于号码下方)则处于 180°
# 若非水平且地址文本块左上角 X 点大于证件号码文本块左上角 X 点 (即地址位于号码右侧),则处于 90°
is_reverse = (is_horizontal and address_points[0][1] >= number_points[0][1]) or \
(not is_horizontal and address_points[0][0] >= number_points[0][0])
# 执行排序
sorted_address_data = sorted(
address_data, reverse=is_reverse,
key=lambda x: x['points'][0][1 if is_horizontal else 0],
)
rev1si0n
202 天前
PaddleOCR 应该会返回文字对应坐标的吧,根据坐标对应不就行了吗
qinyui
202 天前
@tarasha 我找到了个 PP-StructureV2 模型,是这个吗?还是说要自己训练模型呢?
tarasha
202 天前
@qinyui 还是需要训练下的,需要自定义字典文件。也就是分类。看下这个:
https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/doc/doc_ch/kie.md
tarasha
202 天前
@qinyui 我这边有训练好的,不知道你要不要。
NoOneNoBody
202 天前
身份证这种格式都是固定的图片,且跨时间长度和跨项目的,可以用固定参数来写就好了
可以前置一个标准化步骤,把输入的图片旋转、裁切、缩放到固定的尺寸和方向
qinyui
202 天前
@tarasha 我的使用场景中身份证图片是没有经过裁剪的(可能有外界其他信息干扰),不知道通用不?我先自己研究试试
DarylDiao
3 天前
@tarasha 兄弟,训练好的模型可以发一个吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/984991

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX