parent
6fd52609e9
commit
2b15d49b5c
212
票据理赔自动化/main.py
212
票据理赔自动化/main.py
|
|
@ -14,7 +14,7 @@ from datetime import datetime
|
||||||
from decimal import Decimal, ROUND_HALF_UP
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy
|
import numpy
|
||||||
|
|
@ -28,66 +28,6 @@ from utils.client import Authenticator, HTTPClient
|
||||||
# from utils.ocr import fuzzy_match
|
# from utils.ocr import fuzzy_match
|
||||||
|
|
||||||
|
|
||||||
def idcard_extraction(**kwargs) -> dict | None:
|
|
||||||
"""居民身份证数据提取"""
|
|
||||||
|
|
||||||
# 影像件全局唯一标识:优先使用关键词变量,其次使用全局变量,再次使用随机唯一标识
|
|
||||||
image_guid = kwargs.get(
|
|
||||||
"image_guid", globals().get("image_guid", uuid.uuid4().hex.upper())
|
|
||||||
)
|
|
||||||
|
|
||||||
# 影像件格式
|
|
||||||
image_format = kwargs.get("image_format", globals()["image_format"])
|
|
||||||
if image_format is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# 影像件BASE64编码
|
|
||||||
image_base64 = kwargs.get("image_base64", globals()["image_base64"])
|
|
||||||
if image_base64 is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# 请求深圳快瞳居民身份证识别接口
|
|
||||||
response = globals()["http_client"].post(
|
|
||||||
url=(url := "https://ai.inspirvision.cn/s/api/ocr/identityCard"),
|
|
||||||
headers={"X-RequestId-Header": image_guid},
|
|
||||||
data={
|
|
||||||
"token": globals()["authenticator"].get_token(
|
|
||||||
servicer="szkt"
|
|
||||||
), # 使用全局变量
|
|
||||||
"imgBase64": f"data:image/{image_format};base64,{image_base64}",
|
|
||||||
}, # 支持同时识别居民身份证正反面
|
|
||||||
guid=hashlib.md5((url + image_guid).encode("utf-8")).hexdigest().upper(),
|
|
||||||
)
|
|
||||||
|
|
||||||
# 若响应非成功,则返回NONE
|
|
||||||
if not (response.get("status") == 200 and response.get("code") == 0):
|
|
||||||
return None
|
|
||||||
|
|
||||||
extraction = {
|
|
||||||
"姓名": response["data"]["name"],
|
|
||||||
"性别": response["data"]["sex"],
|
|
||||||
"民族": response["data"]["nation"],
|
|
||||||
"出生": response["data"][
|
|
||||||
"birthday"
|
|
||||||
], # 深圳快瞳居民身份证出生日期格式为%Y-%m-%d
|
|
||||||
"住址": response["data"]["address"],
|
|
||||||
"公民身份号码": response["data"]["idNo"],
|
|
||||||
"签发机关": response["data"]["issuedBy"],
|
|
||||||
"有效期起": parse(
|
|
||||||
(date := response["data"]["validDate"]).split("-")[0]
|
|
||||||
).strftime(
|
|
||||||
"%Y-%m-%d"
|
|
||||||
), # 深圳快瞳居民身份证识别中有效期日期格式为%Y.%m.%d,转为%Y-%m-%d
|
|
||||||
"有效期止": (
|
|
||||||
date
|
|
||||||
if (date := date.split("-")[1]) == "长期"
|
|
||||||
else parse(date).strftime("%Y-%m-%d")
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
return extraction
|
|
||||||
|
|
||||||
|
|
||||||
def bankcard_extraction(**kwargs) -> dict | None:
|
def bankcard_extraction(**kwargs) -> dict | None:
|
||||||
"""银行卡数据提取"""
|
"""银行卡数据提取"""
|
||||||
|
|
||||||
|
|
@ -1195,14 +1135,112 @@ if __name__ == "__main__":
|
||||||
return image_base64, image_type, image_orientation
|
return image_base64, image_type, image_orientation
|
||||||
|
|
||||||
# noinspection PyShadowingNames
|
# noinspection PyShadowingNames
|
||||||
def image_recognize(image_base64, image_type) -> Optional[Dict]:
|
def image_recognize(image_guid, image_format, image_base64, image_type) -> None:
|
||||||
"""
|
"""
|
||||||
影像件分类并旋正
|
影像件识别并整合至赔案档案
|
||||||
|
:param image_guid: 影像件唯一标识
|
||||||
|
:param image_format: 影像件格式
|
||||||
:param image_base64: 影像件BASE64编码
|
:param image_base64: 影像件BASE64编码
|
||||||
:param image_type: 影像件类型
|
:param image_type: 影像件类型
|
||||||
:return: 影像件识别内容
|
:return: 空
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# noinspection PyShadowingNames
|
||||||
|
def idcard_recognize(
|
||||||
|
image_guid, image_format, image_base64, image_type
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
居民身份证别并整合至赔案档案
|
||||||
|
:param image_guid: 影像件唯一标识
|
||||||
|
:param image_format: 影像件格式
|
||||||
|
:param image_base64: 影像件BASE64编码
|
||||||
|
:param image_type: 影像件类型
|
||||||
|
:return: 空
|
||||||
|
"""
|
||||||
|
# 请求深圳快瞳居民身份证识别接口
|
||||||
|
response = http_client.post(
|
||||||
|
url=(url := "https://ai.inspirvision.cn/s/api/ocr/identityCard"),
|
||||||
|
headers={
|
||||||
|
"X-RequestId-Header": image_guid
|
||||||
|
}, # 以影像件唯一标识作为请求唯一标识,用于双方联查
|
||||||
|
data={
|
||||||
|
"token": authenticator.get_token(
|
||||||
|
servicer="szkt"
|
||||||
|
), # 获取深圳快瞳访问令牌
|
||||||
|
"imgBase64": f"data:image/{image_format.lstrip(".")};base64,{image_base64}",
|
||||||
|
}, # 支持同时识别居民身份证正反面
|
||||||
|
guid=md5((url + image_guid).encode("utf-8")).hexdigest().upper(),
|
||||||
|
)
|
||||||
|
# 若响应非成功则抛出异常
|
||||||
|
# TODO: 若响应非成功则流转至人工处理
|
||||||
|
if not (response.get("status") == 200 and response.get("code") == 0):
|
||||||
|
raise RuntimeError("请求深圳快瞳居民身份证识别接口发生异常")
|
||||||
|
|
||||||
|
if image_type in ["居民身份证(正背面)", "居民身份证(正面)"]:
|
||||||
|
dossier["赔案层"]["申请人信息"].update(
|
||||||
|
{
|
||||||
|
"证件有效期起": datetime.strptime(
|
||||||
|
extraction["有效期起"], "%Y-%m-%d"
|
||||||
|
),
|
||||||
|
"证件有效期止": (
|
||||||
|
date
|
||||||
|
if (date := extraction["有效期止"]) == "长期"
|
||||||
|
else datetime.strptime(date, "%Y-%m-%d")
|
||||||
|
), # 若证件有效期止为NONE默认为“长期”,
|
||||||
|
}
|
||||||
|
) # 原则上由影像件数据提取环节负责数据标准化,赔案档案数据填充环节负责数据机构化
|
||||||
|
|
||||||
|
if image_type in ["居民身份证(正背面)", "居民身份证(背面)"]:
|
||||||
|
dossier["赔案层"]["申请人信息"].update(
|
||||||
|
{
|
||||||
|
"姓名": extraction["姓名"],
|
||||||
|
"证件类型": "居民身份证",
|
||||||
|
"证件号码": extraction["公民身份号码"],
|
||||||
|
"性别": extraction["性别"],
|
||||||
|
"出生": datetime.strptime(
|
||||||
|
extraction["出生"], "%Y-%m-%d"
|
||||||
|
), # 默认日期格式为%Y-%m-%d
|
||||||
|
"省": (address := parse_location(extraction["住址"])).get(
|
||||||
|
"province"
|
||||||
|
),
|
||||||
|
"地": address.get("city"),
|
||||||
|
"县": address.get("county"),
|
||||||
|
"详细地址": address.get("detail"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
extraction = {
|
||||||
|
"姓名": response["data"]["name"],
|
||||||
|
"性别": response["data"]["sex"],
|
||||||
|
"民族": response["data"]["nation"],
|
||||||
|
"出生": response["data"][
|
||||||
|
"birthday"
|
||||||
|
], # 深圳快瞳居民身份证出生日期格式为%Y-%m-%d
|
||||||
|
"住址": response["data"]["address"],
|
||||||
|
"公民身份号码": response["data"]["idNo"],
|
||||||
|
"签发机关": response["data"]["issuedBy"],
|
||||||
|
"有效期起": parse(
|
||||||
|
(date := response["data"]["validDate"]).split("-")[0]
|
||||||
|
).strftime(
|
||||||
|
"%Y-%m-%d"
|
||||||
|
), # 深圳快瞳居民身份证识别中有效期日期格式为%Y.%m.%d,转为%Y-%m-%d
|
||||||
|
"有效期止": (
|
||||||
|
date
|
||||||
|
if (date := date.split("-")[1]) == "长期"
|
||||||
|
else parse(date).strftime("%Y-%m-%d")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
# 根据影像件类型匹配影像件识别方法
|
||||||
|
match image_type:
|
||||||
|
# TODO: 后续添加居民户口簿识别和整合方法
|
||||||
|
case "居民户口簿":
|
||||||
|
raise RuntimeError("暂不支持居民户口簿")
|
||||||
|
case (
|
||||||
|
"居民身份证(国徽、头像面)" | "居民身份证(国徽面)" | "居民身份证(头像面)"
|
||||||
|
):
|
||||||
|
idcard_recognize(image_guid, image_format, image_base64)
|
||||||
|
|
||||||
# 遍历工作目录中赔案目录并创建赔案档案(模拟自动化域就待自动化任务创建理赔档案)
|
# 遍历工作目录中赔案目录并创建赔案档案(模拟自动化域就待自动化任务创建理赔档案)
|
||||||
for case_path in [x for x in directory_path.iterdir() if x.is_dir()]:
|
for case_path in [x for x in directory_path.iterdir() if x.is_dir()]:
|
||||||
# 初始化赔案档案(实际报案层包括保险分公司名称、报案渠道、批次号、报案号和报案时间等)
|
# 初始化赔案档案(实际报案层包括保险分公司名称、报案渠道、批次号、报案号和报案时间等)
|
||||||
|
|
@ -1264,9 +1302,8 @@ if __name__ == "__main__":
|
||||||
}
|
}
|
||||||
)["result"]["recognition_enable"]:
|
)["result"]["recognition_enable"]:
|
||||||
continue
|
continue
|
||||||
|
# 影像件识别并整合至赔案档案
|
||||||
# 影像件识别
|
image_recognize(image_guid, image_format, image_base64, image_type)
|
||||||
recognition = image_recognize(image_base64, image_type)
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
@ -1274,48 +1311,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 根据影像件类型匹配影像件数据提取
|
|
||||||
# noinspection PyUnreachableCode
|
|
||||||
match image_type:
|
|
||||||
case "居民身份证(正背面)" | "居民身份证(正面)" | "居民身份证(背面)":
|
|
||||||
extraction = idcard_extraction()
|
|
||||||
# 若发生异常则跳过该影像件
|
|
||||||
if extraction is None:
|
|
||||||
dossier["影像件层"][-1]["已识别"] = "否,无法识别"
|
|
||||||
continue
|
|
||||||
|
|
||||||
if image_type in ["居民身份证(正背面)", "居民身份证(正面)"]:
|
|
||||||
dossier["赔案层"]["申请人信息"].update(
|
|
||||||
{
|
|
||||||
"证件有效期起": datetime.strptime(
|
|
||||||
extraction["有效期起"], "%Y-%m-%d"
|
|
||||||
),
|
|
||||||
"证件有效期止": (
|
|
||||||
date
|
|
||||||
if (date := extraction["有效期止"]) == "长期"
|
|
||||||
else datetime.strptime(date, "%Y-%m-%d")
|
|
||||||
), # 若证件有效期止为NONE默认为“长期”,
|
|
||||||
}
|
|
||||||
) # 原则上由影像件数据提取环节负责数据标准化,赔案档案数据填充环节负责数据机构化
|
|
||||||
|
|
||||||
if image_type in ["居民身份证(正背面)", "居民身份证(背面)"]:
|
|
||||||
dossier["赔案层"]["申请人信息"].update(
|
|
||||||
{
|
|
||||||
"姓名": extraction["姓名"],
|
|
||||||
"证件类型": "居民身份证",
|
|
||||||
"证件号码": extraction["公民身份号码"],
|
|
||||||
"性别": extraction["性别"],
|
|
||||||
"出生": datetime.strptime(
|
|
||||||
extraction["出生"], "%Y-%m-%d"
|
|
||||||
), # 默认日期格式为%Y-%m-%d
|
|
||||||
"省": (
|
|
||||||
address := parse_location(extraction["住址"])
|
|
||||||
).get("province"),
|
|
||||||
"地": address.get("city"),
|
|
||||||
"县": address.get("county"),
|
|
||||||
"详细地址": address.get("detail"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
case "银行卡":
|
case "银行卡":
|
||||||
extraction = bankcard_extraction()
|
extraction = bankcard_extraction()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue