新增自动识别错误检查功能
This commit is contained in:
230
photo_review/photo_review_error_check.py
Normal file
230
photo_review/photo_review_error_check.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import date, timedelta
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
|
||||
import requests
|
||||
from PIL import ImageFont, ImageDraw, Image
|
||||
from sqlalchemy import update
|
||||
|
||||
from db import MysqlSession
|
||||
from db.mysql import ViewErrorReview, ZxPhhd, ZxPhrec, ZxIeResult, ZxIeSettlement, ZxIeDischarge, ZxIeCost
|
||||
from ucloud import ufile
|
||||
from util import image_util
|
||||
|
||||
|
||||
def main(pk_phhd=None):
|
||||
session = MysqlSession()
|
||||
error_query = (session.query(ZxPhhd.pk_phhd, ZxPhhd.cXm, ViewErrorReview.pk_yljg, ViewErrorReview.pk_yljg_ocr,
|
||||
ViewErrorReview.pk_ylks, ViewErrorReview.pk_ylks_ocr, ViewErrorReview.cdoctor,
|
||||
ViewErrorReview.cdoctor_ocr, ViewErrorReview.czyh, ViewErrorReview.czyh_ocr,
|
||||
ViewErrorReview.dzyrq, ViewErrorReview.dzyrq_ocr, ViewErrorReview.dcyrq,
|
||||
ViewErrorReview.dcyrq_ocr, ViewErrorReview.input_cxm, ViewErrorReview.input_cxm_ocr,
|
||||
ViewErrorReview.ffsylfy, ViewErrorReview.ffsylfy_ocr, ViewErrorReview.fgrzfje1,
|
||||
ViewErrorReview.fgrzfje1_ocr, ViewErrorReview.fgezfje2, ViewErrorReview.fgezfje2_ocr,
|
||||
ViewErrorReview.fgrzfje, ViewErrorReview.fgrzfje_ocr, ViewErrorReview.yb_type,
|
||||
ViewErrorReview.yb_type_ocr, ViewErrorReview.cjsd_id, ViewErrorReview.cjsd_id_ocr,
|
||||
ViewErrorReview.fage, ViewErrorReview.fage_ocr, ZxPhhd.problem_note)
|
||||
.join(ZxPhhd, ViewErrorReview.pk_phhd == ZxPhhd.pk_phhd, isouter=True))
|
||||
if pk_phhd:
|
||||
error_query = error_query.filter(ZxPhhd.pk_phhd == pk_phhd)
|
||||
else:
|
||||
today = date.today()
|
||||
error_query = (error_query.filter(ZxPhhd.problem_note.is_(None))
|
||||
.filter(ViewErrorReview.creationtime >= today)
|
||||
.filter(ViewErrorReview.creationtime < today + timedelta(days=1))
|
||||
.order_by(ViewErrorReview.creationtime.desc()))
|
||||
error_review = error_query.limit(1).one_or_none()
|
||||
if error_review is None:
|
||||
print("没有需要检查的记录")
|
||||
sys.exit()
|
||||
|
||||
pk_phhd = error_review.pk_phhd
|
||||
# 文件路径
|
||||
directory = f"./review_error_check/{pk_phhd}"
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
json_result = {
|
||||
"pk_phhd": pk_phhd,
|
||||
"cXm": error_review.cXm
|
||||
}
|
||||
|
||||
settlement_query = session.query(ZxIeSettlement.pk_ie_settlement)
|
||||
discharge_query = session.query(ZxIeDischarge.pk_ie_discharge)
|
||||
cost_query = session.query(ZxIeCost.pk_ie_cost)
|
||||
|
||||
if error_review.pk_yljg != error_review.pk_yljg_ocr:
|
||||
json_result["医院pk_yljg"] = error_review.pk_yljg
|
||||
json_result["pk_yljg_ocr"] = error_review.pk_yljg_ocr
|
||||
discharge_query = discharge_query.add_columns(ZxIeDischarge.hospital, ZxIeDischarge.pk_yljg)
|
||||
if error_review.pk_ylks != error_review.pk_ylks_ocr:
|
||||
json_result["科室pk_ylks"] = error_review.pk_ylks
|
||||
json_result["pk_ylks_ocr"] = error_review.pk_ylks_ocr
|
||||
discharge_query = discharge_query.add_columns(ZxIeDischarge.department, ZxIeDischarge.pk_ylks)
|
||||
if error_review.cdoctor != error_review.cdoctor_ocr:
|
||||
json_result["医生cdoctor"] = error_review.cdoctor
|
||||
json_result["cdoctor_ocr"] = error_review.cdoctor_ocr
|
||||
discharge_query = discharge_query.add_column(ZxIeDischarge.doctor)
|
||||
if error_review.czyh != error_review.czyh_ocr:
|
||||
json_result["住院号czyh"] = error_review.czyh
|
||||
json_result["czyh_ocr"] = error_review.czyh_ocr
|
||||
settlement_query = settlement_query.add_column(ZxIeSettlement.admission_id)
|
||||
discharge_query = discharge_query.add_column(ZxIeDischarge.admission_id)
|
||||
if error_review.dzyrq != error_review.dzyrq_ocr:
|
||||
json_result["入院日期dzyrq"] = error_review.dzyrq
|
||||
json_result["dzyrq_ocr"] = error_review.dzyrq_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.admission_date_str,
|
||||
ZxIeSettlement.admission_date)
|
||||
discharge_query = discharge_query.add_columns(ZxIeDischarge.admission_date_str, ZxIeDischarge.admission_date)
|
||||
cost_query = cost_query.add_columns(ZxIeCost.admission_date_str, ZxIeCost.admission_date)
|
||||
if error_review.dcyrq != error_review.dcyrq_ocr:
|
||||
json_result["出院日期dcyrq"] = error_review.dcyrq
|
||||
json_result["dcyrq_ocr"] = error_review.dcyrq_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.discharge_date_str,
|
||||
ZxIeSettlement.discharge_date)
|
||||
discharge_query = discharge_query.add_columns(ZxIeDischarge.discharge_date_str, ZxIeDischarge.discharge_date)
|
||||
cost_query = cost_query.add_columns(ZxIeCost.discharge_date_str, ZxIeCost.discharge_date)
|
||||
if error_review.input_cxm != error_review.input_cxm_ocr:
|
||||
json_result["姓名input_cxm"] = error_review.input_cxm
|
||||
json_result["input_cxm_ocr"] = error_review.input_cxm_ocr
|
||||
settlement_query = settlement_query.add_column(ZxIeSettlement.name)
|
||||
discharge_query = discharge_query.add_column(ZxIeDischarge.name)
|
||||
cost_query = cost_query.add_column(ZxIeCost.name)
|
||||
if error_review.ffsylfy != error_review.ffsylfy_ocr:
|
||||
json_result["费用总额ffsylfy"] = error_review.ffsylfy
|
||||
json_result["ffsylfy_ocr"] = error_review.ffsylfy_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.medical_expenses_str,
|
||||
ZxIeSettlement.medical_expenses)
|
||||
cost_query = cost_query.add_columns(ZxIeCost.medical_expenses_str, ZxIeCost.medical_expenses)
|
||||
if error_review.fgrzfje1 != error_review.fgrzfje1_ocr:
|
||||
json_result["个人现金支付fgrzfje1"] = error_review.fgrzfje1
|
||||
json_result["fgrzfje1_ocr"] = error_review.fgrzfje1_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_cash_payment_str,
|
||||
ZxIeSettlement.personal_cash_payment)
|
||||
if error_review.fgezfje2 != error_review.fgezfje2_ocr:
|
||||
json_result["个人账户支付fgezfje2"] = error_review.fgezfje2
|
||||
json_result["fgezfje2_ocr"] = error_review.fgezfje2_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_account_payment_str,
|
||||
ZxIeSettlement.personal_account_payment)
|
||||
if error_review.fgrzfje != error_review.fgrzfje_ocr:
|
||||
json_result["个人自费fgrzfje"] = error_review.fgrzfje
|
||||
json_result["fgrzfje_ocr"] = error_review.fgrzfje_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.personal_funded_amount_str,
|
||||
ZxIeSettlement.personal_funded_amount)
|
||||
if error_review.yb_type != error_review.yb_type_ocr:
|
||||
json_result["医保类型yb_type"] = error_review.yb_type
|
||||
json_result["yb_type_ocr"] = error_review.yb_type_ocr
|
||||
settlement_query = settlement_query.add_columns(ZxIeSettlement.medical_insurance_type_str,
|
||||
ZxIeSettlement.medical_insurance_type)
|
||||
if error_review.cjsd_id != error_review.cjsd_id_ocr:
|
||||
json_result["结算单号cjsd_id"] = error_review.cjsd_id
|
||||
json_result["cjsd_id_ocr"] = error_review.cjsd_id_ocr
|
||||
settlement_query = settlement_query.add_column(ZxIeSettlement.settlement_id)
|
||||
if error_review.fage != error_review.fage_ocr:
|
||||
json_result["年龄fage"] = error_review.fage
|
||||
json_result["fage_ocr"] = error_review.fage_ocr
|
||||
discharge_query = discharge_query.add_column(ZxIeDischarge.age)
|
||||
|
||||
settlement = settlement_query.filter(ZxIeSettlement.pk_phhd == pk_phhd).one_or_none()
|
||||
if settlement is not None:
|
||||
json_result["settlement"] = settlement._asdict()
|
||||
discharge = discharge_query.filter(ZxIeDischarge.pk_phhd == pk_phhd).one_or_none()
|
||||
if discharge is not None:
|
||||
json_result["discharge"] = discharge._asdict()
|
||||
cost = cost_query.filter(ZxIeCost.pk_phhd == pk_phhd).one_or_none()
|
||||
if cost is not None:
|
||||
json_result["cost"] = cost._asdict()
|
||||
|
||||
phrecs = session.query(ZxPhrec.pk_phrec, ZxPhrec.pk_phhd, ZxPhrec.cRectype, ZxPhrec.cfjaddress).filter(
|
||||
ZxPhrec.pk_phhd == pk_phhd).all()
|
||||
for phrec in phrecs:
|
||||
img_name = phrec.cfjaddress
|
||||
img_path = ufile.get_private_url(img_name)
|
||||
|
||||
response = requests.get(img_path)
|
||||
image = Image.open(BytesIO(response.content)).convert("RGB")
|
||||
font_size = image.width * image.height / 200000
|
||||
font = ImageFont.truetype("./font/simfang.ttf", size=font_size)
|
||||
|
||||
ie_result = session.query(ZxIeResult.id, ZxIeResult.content, ZxIeResult.rotation_angle, ZxIeResult.x_offset,
|
||||
ZxIeResult.y_offset).filter(ZxIeResult.pk_phrec == phrec.pk_phrec).all()
|
||||
if not ie_result:
|
||||
no_ie_directory = f"{directory}/0"
|
||||
if not os.path.exists(no_ie_directory):
|
||||
os.makedirs(no_ie_directory)
|
||||
image.save(f"{no_ie_directory}/{img_name}")
|
||||
|
||||
for _, group_results in groupby(ie_result, key=lambda x: x.id):
|
||||
draw = ImageDraw.Draw(image)
|
||||
for ocr_item in group_results:
|
||||
result = json.loads(ocr_item.content)
|
||||
rotation_angle = ocr_item.rotation_angle
|
||||
x_offset = ocr_item.x_offset
|
||||
y_offset = ocr_item.y_offset
|
||||
for key in result:
|
||||
for value in result[key]:
|
||||
box = value["bbox"][0]
|
||||
|
||||
if rotation_angle:
|
||||
box = image_util.invert_rotate_rectangle(box, (image.width / 2, image.height / 2),
|
||||
rotation_angle)
|
||||
if x_offset:
|
||||
box[0] += x_offset
|
||||
box[2] += x_offset
|
||||
if y_offset:
|
||||
box[1] += y_offset
|
||||
box[3] += y_offset
|
||||
|
||||
draw.rectangle(box, outline="red", width=2) # 绘制矩形
|
||||
draw.text((box[0], box[1] - font_size), key, fill="blue", font=font) # 在矩形上方绘制文本
|
||||
draw.text((box[0], box[3]), value["text"], fill="blue", font=font) # 在矩形下方绘制文本
|
||||
ie_directory = f"{directory}/{ocr_item.id}"
|
||||
os.makedirs(ie_directory, exist_ok=True)
|
||||
image.save(f"{ie_directory}/{img_name}")
|
||||
session.close()
|
||||
|
||||
# 自定义JSON处理器
|
||||
def default(obj):
|
||||
if isinstance(obj, Decimal):
|
||||
return float(obj)
|
||||
if isinstance(obj, date):
|
||||
return obj.strftime("%Y-%m-%d")
|
||||
|
||||
with open(f"{directory}/result.json", "w", encoding="utf-8") as json_file:
|
||||
json.dump(json_result, json_file, indent=4, ensure_ascii=False, default=default)
|
||||
|
||||
return pk_phhd
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pk_phhd = main()
|
||||
while True:
|
||||
check_finish = input(f"{pk_phhd}是否完成(是/否):")
|
||||
if check_finish == "是":
|
||||
"""
|
||||
错误描述的写法:
|
||||
1. 查看result.json,以含中文的key中的中文为现在的key
|
||||
2. 为方便输入,key之后跟中文冒号
|
||||
3. 冒号之后写错误原因,原因最好是固定的几种写法
|
||||
4. 可以在原因后跟中文括号,并在括号中进行补充说明
|
||||
5. 写完错误原因以中文分号结尾,最后一个可以不加分号
|
||||
举例:
|
||||
错误描述:医院:未知错误;科室:还是未知错误(补充说明)
|
||||
"""
|
||||
error_descript = input("错误描述:")
|
||||
break
|
||||
elif check_finish == "否":
|
||||
sys.exit()
|
||||
else:
|
||||
print("无效输入!请输入“是”或者“否”")
|
||||
|
||||
session = MysqlSession()
|
||||
update_error = update(ZxPhhd).where(ZxPhhd.pk_phhd == pk_phhd).values(problem_note=error_descript)
|
||||
session.execute(update_error)
|
||||
session.commit()
|
||||
session.close()
|
||||
print(f"【{pk_phhd}】错误分析已完成。错误描述:{error_descript}")
|
||||
99
photo_review/photo_review_error_report.py
Normal file
99
photo_review/photo_review_error_report.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from datetime import date, timedelta
|
||||
|
||||
from sqlalchemy.sql.functions import count
|
||||
|
||||
from db import MysqlSession
|
||||
from db.mysql import ZxPhhd, ViewErrorReview
|
||||
from util import util
|
||||
|
||||
|
||||
def handle_reason(reason):
|
||||
if "(" in reason:
|
||||
reason = reason.split("(")[0]
|
||||
return reason
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
today = date.today()
|
||||
session = MysqlSession()
|
||||
error_reviews_count = (session.query(count())
|
||||
.filter(ViewErrorReview.creationtime >= today)
|
||||
.filter(ViewErrorReview.creationtime < today + timedelta(days=1))
|
||||
.scalar())
|
||||
error_reviews = (session.query(ZxPhhd.problem_note, ViewErrorReview.pk_phhd)
|
||||
.join(ZxPhhd, ViewErrorReview.pk_phhd == ZxPhhd.pk_phhd, isouter=True)
|
||||
.filter(ZxPhhd.problem_note.is_not(None))
|
||||
.filter(ViewErrorReview.creationtime >= today)
|
||||
.filter(ViewErrorReview.creationtime < today + timedelta(days=1))
|
||||
.all())
|
||||
session.close()
|
||||
|
||||
result = {f"{today}涂抹错误图片总数": error_reviews_count}
|
||||
hospital_result = defaultdict(int)
|
||||
department_result = defaultdict(int)
|
||||
doctor_result = defaultdict(int)
|
||||
admission_id_result = defaultdict(int)
|
||||
admission_date_result = defaultdict(int)
|
||||
discharge_date_result = defaultdict(int)
|
||||
name_result = defaultdict(int)
|
||||
medical_expenses_result = defaultdict(int)
|
||||
personal_cash_payment_result = defaultdict(int)
|
||||
personal_account_payment_result = defaultdict(int)
|
||||
personal_funded_amount_result = defaultdict(int)
|
||||
medical_insurance_type_result = defaultdict(int)
|
||||
settlement_id_result = defaultdict(int)
|
||||
age_result = defaultdict(int)
|
||||
for error_review in error_reviews:
|
||||
columns = error_review.problem_note.split(";")
|
||||
for column in columns:
|
||||
key, value = column.split(":")
|
||||
if key == "医院":
|
||||
hospital_result[handle_reason(value)] += 1
|
||||
elif key == "科室":
|
||||
department_result[handle_reason(value)] += 1
|
||||
elif key == "医生":
|
||||
doctor_result[handle_reason(value)] += 1
|
||||
elif key == "住院号":
|
||||
admission_id_result[handle_reason(value)] += 1
|
||||
elif key == "入院日期":
|
||||
admission_date_result[handle_reason(value)] += 1
|
||||
elif key == "出院日期":
|
||||
discharge_date_result[handle_reason(value)] += 1
|
||||
elif key == "姓名":
|
||||
name_result[handle_reason(value)] += 1
|
||||
elif key == "费用总额":
|
||||
medical_expenses_result[handle_reason(value)] += 1
|
||||
elif key == "个人现金支付":
|
||||
personal_cash_payment_result[handle_reason(value)] += 1
|
||||
elif key == "个人账户支付":
|
||||
personal_account_payment_result[handle_reason(value)] += 1
|
||||
elif key == "个人自费":
|
||||
personal_funded_amount_result[handle_reason(value)] += 1
|
||||
elif key == "医保类别":
|
||||
medical_insurance_type_result[handle_reason(value)] += 1
|
||||
elif key == "结算单号":
|
||||
settlement_id_result[handle_reason(value)] += 1
|
||||
elif key == "年龄":
|
||||
age_result[handle_reason(value)] += 1
|
||||
result["医院"] = hospital_result
|
||||
result["科室"] = department_result
|
||||
result["主治医生"] = doctor_result
|
||||
result["住院号"] = admission_id_result
|
||||
result["住院日期"] = admission_date_result
|
||||
result["出院日期"] = discharge_date_result
|
||||
result["患者姓名"] = name_result
|
||||
result["费用总额"] = medical_expenses_result
|
||||
result["个人现金支付"] = personal_cash_payment_result
|
||||
result["个人账户支付"] = personal_account_payment_result
|
||||
result["个人自费"] = personal_funded_amount_result
|
||||
result["医保类型"] = medical_insurance_type_result
|
||||
result["结算单号"] = settlement_id_result
|
||||
result["年龄"] = age_result
|
||||
|
||||
print(result)
|
||||
with open("photo_review_error_report.txt", 'w', encoding='utf-8') as file:
|
||||
file.write(json.dumps(result, indent=4, ensure_ascii=False))
|
||||
file.write(util.get_default_datetime())
|
||||
print("结果已保存。")
|
||||
Reference in New Issue
Block a user