from flask import Blueprint, views, render_template, request from utils.util import * import re from utils.conf import MAX_CONTENT_LENGTH idc = Blueprint("idc", __name__, url_prefix="/idc") __exclude = "中国CHINA *#★☆" __face_ptn = r"^姓名(?P.+)性别(?P男|女)民族(?P.+)" \ r"出生(?P\d{4})年(?P\d\d)月(?P\d\d)日" \ r"住址(?P.+)公民身份号码(?P\d{17}\d|x|X)$" __icon_ptn = r"^中华人民共和国居民身份证签发机关(?P.+)" \ r"有效期限(?P\d{4})\.(?P\d{2})\.(?P\d{2})" \ r"[^\d]+(?P\d{4})\.(?P\d{2})\.(?P\d{2})$" def get_face_info(data: "list[str]") -> "tuple[dict, str, bool]": res = {"name": "", "gender": "", "nation": "", "birth": {"year": "", "month": "", "day": ""}, "addr": "", "idn": ""} if len(data) < 5: # 最少 5 个识别结果 return res, "请使用正确的身份证人像面照片", False str_all = "".join([item for item in data if not str_include(__exclude, item)]) if match := re.match(__face_ptn, str_all): res["name"] = match.group("name") res["gender"] = match.group("gender") res["nation"] = match.group("nation") res["birth"] = { "year": match.group("year"), "month": match.group("month"), "day": match.group("day") } res["addr"] = match.group("addr") res["idn"] = match.group("idn") return res, str_all, True return res, "识别失败,请重新选择", False def get_icon_info(data: "list[str]"): res = {"agent": "", "from": {"year": "", "month": "", "day": ""}, "to": {"year": "", "month": "", "day": ""}} if len(data) < 4: # 最少 4 个识别结果 return res, "请使用正确的身份证国徽面照片", False str_all = "".join([item for item in data if not str_include(__exclude, item)]) if match := re.match(__icon_ptn, str_all): res["agent"] = match.group("agent") res["from"] = { "year": match.group("from_year"), "month": match.group("from_month"), "day": match.group("from_day"), } res["to"] = { "year": match.group("to_year"), "month": match.group("to_month"), "day": match.group("to_day"), } return res, str_all, True return res, "识别失败,请重新选择", False class IdcView(views.MethodView): @staticmethod def get(): return render_template("idc_index.html") @staticmethod def post(): which = request.form.get("which") if which is not None: which = which.lower() if which not in ["face", "icon"]: return Response(f"not recognized arg : '{which}'") pic = request.files.get("picture") if pic is None: return Response("empty body") ext = get_ext_name(pic.filename) if not is_image_ext(ext): return Response("文件类型错误") content = pic.read() if len(content) > MAX_CONTENT_LENGTH: return Response("文件过大,请重新选择") images = rotate(content) rec = rec_multi(images) info, msg, sta, idx = {}, "识别失败,请重新选择", False, 0 for idx, (ocr_res, _) in enumerate(rec): words = [it[1][0].replace(" ", "") for it in ocr_res] if which == "face": if not words[0].startswith("姓名"): continue info, msg, sta = get_face_info(words) else: if not words[0].startswith("中华"): continue info, msg, sta = get_icon_info(words) if sta: break if sta: raw_path = f"static/images/{current_time()}_{rand_str()}.{ext}" save_img(raw_path, images[idx]) return Response(data=info) return Response(msg, info) class IdcHtmlView(views.MethodView): @staticmethod def post(): which = request.form.get("which") if which is not None: which = which.lower() if which not in ["face", "icon"]: return Response(f"not recognized arg : '{which}'") pic = request.files.get("picture") if pic is None: return Response("empty body") ext = get_ext_name(pic.filename) if not is_image_ext(ext): return Response("文件类型错误") content = pic.read() if len(content) > MAX_CONTENT_LENGTH: return Response("文件过大,请重新选择") images = rotate(content) rec = rec_multi(images) info, msg, sta, idx = {}, "识别失败,请重新选择", False, 0 for idx, (ocr_res, _) in enumerate(rec): words = [it[1][0].replace(" ", "") for it in ocr_res] if which == "face": if not words[0].startswith("姓名"): continue info, msg, sta = get_face_info(words) else: if not words[0].startswith("中华"): continue info, msg, sta = get_icon_info(words) if sta: break cut, rnd = current_time(), rand_str() raw_path = f"static/images/{cut}_{rnd}.{ext}" rec_path = f"static/images/{cut}_{rnd}_rec.{ext}" save_img(raw_path, images[idx]) draw_img(rec[idx][1], [{"pos": it[0], "word": it[1][0], "rate": it[1][1]} for it in rec[idx][0]], rec_path) info["SUCCESS"] = str(sta).upper() info["MESSAGE"] = msg return render_template("k-v_result.html", raw=raw_path, rec=rec_path, data=info) idc.add_url_rule("/", view_func=IdcView.as_view("idc")) idc.add_url_rule("/html/", view_func=IdcHtmlView.as_view("idc-html"))