import cv2 from app.core.config import settings from app.core.logger import get_logger from app.services.defect_service import DefectInferenceService from app.services.card_rectify_and_center import CardRectifyAndCenter from app.utils.score_inference.CardScorer import CardScorer import numpy as np import json logger = get_logger(__name__) class ScoreService: def __init__(self): self.scoring_config_path = settings.SCORE_CONFIG_PATH self.card_scorer = CardScorer(config_path=self.scoring_config_path) self.defect_service = DefectInferenceService() self.rectify_center_service = CardRectifyAndCenter() def score_inference(self, score_type: str, is_reflect_card: bool, img_bgr: np.ndarray) -> dict: # 解包返回值,获取转正后的外框数据 img_bgr, transformed_outer_json = self.rectify_center_service.rectify_and_center(img_bgr) if img_bgr is None: raise ValueError("图像转正处理失败") imageHeight, imageWidth = img_bgr.shape[:2] logger.info("开始进行卡片分数推理, 使用变换后的外框") # 定义通用参数,传入 pre_calculated_outer_result defect_kwargs = { "img_bgr": img_bgr.copy(), "pre_calculated_outer_result": transformed_outer_json } if score_type == 'front_ring' or score_type == 'front_coaxial': center_data = self.defect_service.defect_inference("pokemon_front_card_center", **defect_kwargs) else: center_data = self.defect_service.defect_inference("pokemon_back_card_center", **defect_kwargs) if is_reflect_card: if score_type == 'front_ring': defect_data = self.defect_service.defect_inference('pokemon_front_face_reflect_ring_light_defect', **defect_kwargs) elif score_type == 'front_coaxial': defect_data = self.defect_service.defect_inference('pokemon_front_face_reflect_coaxial_light_defect', **defect_kwargs) elif score_type == 'back_ring': defect_data = self.defect_service.defect_inference('pokemon_back_face_ring_light_defect', **defect_kwargs) elif score_type == 'back_coaxial': defect_data = self.defect_service.defect_inference('pokemon_back_face_coaxial_light_defect', **defect_kwargs) else: return {} else: if score_type == 'front_ring': defect_data = self.defect_service.defect_inference('pokemon_front_face_no_reflect_ring_light_defect', **defect_kwargs) elif score_type == 'front_coaxial': defect_data = self.defect_service.defect_inference('pokemon_front_face_no_reflect_coaxial_light_defect', **defect_kwargs) elif score_type == 'back_ring': defect_data = self.defect_service.defect_inference('pokemon_back_face_ring_light_defect', **defect_kwargs) elif score_type == 'back_coaxial': defect_data = self.defect_service.defect_inference('pokemon_back_face_coaxial_light_defect', **defect_kwargs) else: return {} logger.info("模型推理结束, 开始计算分数") if score_type == 'front_ring' or score_type == 'front_coaxial': card_aspect = "front" else: card_aspect = "back" if score_type == 'front_ring' or score_type == 'back_ring': card_light_type = "ring" else: card_light_type = "coaxial" if card_light_type == 'ring': center_score_data = self.card_scorer.calculate_centering_score(card_aspect, center_data, True) # 计算角, 边, 面的分数, 会把分数写入json, 然后传入刚写好的, 继续写边的分数 defect_data = self.card_scorer.calculate_defect_score('corner', card_aspect, card_light_type, defect_data, True) defect_data = self.card_scorer.calculate_defect_score('edge', card_aspect, card_light_type, defect_data, True) defect_score_data = self.card_scorer.calculate_defect_score('face', card_aspect, card_light_type, defect_data, True) elif card_light_type == 'coaxial': # 居中 center_score_data = {} # 同轴光照片只计算面缺陷 defect_score_data = self.card_scorer.calculate_defect_score('face', card_aspect, card_light_type, defect_data, True) else: return {} result_json = self.card_scorer.formate_one_card_result(center_score_data, defect_score_data, card_light_type=card_light_type, card_aspect=card_aspect, imageHeight=imageHeight, imageWidth=imageWidth) temp_score_json_path = settings.TEMP_WORK_DIR / f'{score_type}_score.json' with open(temp_score_json_path, 'w', encoding='utf-8') as f: json.dump(result_json, f, ensure_ascii=False, indent=2) logger.info("分数推理完成 ") return result_json def recalculate_defect_score(self, score_type: str, json_data: dict): center_json_data = json_data["result"]['center_result'] defect_json_data = json_data["result"]['defect_result'] imageHeight = json_data["result"].get('imageHeight', 0) imageWidth = json_data["result"].get('imageWidth', 0) # 正反面类型分类 if score_type == 'front_ring' or score_type == 'front_coaxial': card_aspect = "front" else: card_aspect = "back" if score_type == 'front_ring' or score_type == 'back_ring': card_light_type = "ring" else: card_light_type = "coaxial" logger.info("开始进行缺陷信息重计算") defect_data = self.defect_service.re_inference_from_json(card_light_type=card_light_type, center_json=center_json_data, defect_json=defect_json_data) logger.info("开始重新计算分数") if card_light_type == 'ring': logger.info("开始进行居中信息重计算") center_data = self.defect_service.re_inference_from_json(card_light_type="center", center_json=center_json_data, defect_json=defect_json_data) center_score_data = self.card_scorer.calculate_centering_score(card_aspect, center_data, True) # 计算角, 边, 面的分数, 会把分数写入json, 然后传入刚写好的, 继续写边的分数 logger.info("开始重新计算:边角面") defect_data = self.card_scorer.calculate_defect_score('corner', card_aspect, card_light_type, defect_data, True) defect_data = self.card_scorer.calculate_defect_score('edge', card_aspect, card_light_type, defect_data, True) defect_score_data = self.card_scorer.calculate_defect_score('face', card_aspect, card_light_type, defect_data, True) elif card_light_type == 'coaxial': # 居中 center_score_data = {} # 同轴光照片只计算面缺陷 logger.info("开始重新计算:面") defect_score_data = self.card_scorer.calculate_defect_score('face', card_aspect, card_light_type, defect_data, True) else: return {} result_json = self.card_scorer.formate_one_card_result(center_score_data, defect_score_data, card_light_type=card_light_type, card_aspect=card_aspect, imageHeight=imageHeight, imageWidth=imageWidth) temp_score_json_path = settings.TEMP_WORK_DIR / f're_{score_type}_score.json' with open(temp_score_json_path, 'w', encoding='utf-8') as f: json.dump(result_json, f, ensure_ascii=False, indent=2) logger.info("分数推理完成 ") return result_json