import json from typing import List, Dict, Any, Tuple class CardScorer: """ 它从一个JSON配置文件加载评分规则,并根据输入的卡片数据计算分数。 """ def __init__(self, config_path: str): try: with open(config_path, 'r', encoding='utf-8') as f: self.config = json.load(f) self.base_score = self.config.get("base_score", 10.0) except FileNotFoundError: raise ValueError(f"配置文件未找到: {config_path}") except json.JSONDecodeError: raise ValueError(f"配置文件格式错误: {config_path}") def _get_score_from_tiers(self, value: float, rules: List[List[Any]]) -> float: """ 一个通用的辅助函数,根据分层规则查找值对应的分数。 """ for tier in rules: threshold, score = tier if threshold == "inf" or value < threshold: return float(score) return 0.0 # 如果没有匹配的规则,不扣分 def calculate_defect_score(self, aspect: str, defect_data: Dict[str, List[float]]) -> float: """ 一个通用的缺陷计分函数,用于计算角、边、表面的加权分数。 'corners', 'edges', 'face' """ aspect_config = self.config[aspect] total_deduction = 0.0 weighted_scores = {} # 1. 计算每种缺陷类型的总扣分 for defect_type, values in defect_data.items(): if defect_type not in aspect_config['rules']: continue rules = aspect_config['rules'][defect_type] # 累加所有同类型缺陷的扣分 type_deduction = sum(self._get_score_from_tiers(v, rules) for v in values) weighted_scores[defect_type] = type_deduction # 2. 根据权重/系数计算最终扣分 weights = aspect_config.get(f"{self.current_face}_weights") or aspect_config.get("coefficients") if not weights: raise ValueError(f"在配置中未找到 '{aspect}' 的权重/系数") for defect_type, score in weighted_scores.items(): total_deduction += score * weights.get(defect_type, 1.0) return total_deduction def calculate_centering_score(self, card_type: str, center_data: dict) -> float: """ 计算居中度分数。 card_type 为 front或 back """ if card_type != "front" and card_type != "back": raise TypeError("calculate_centering_score:card_type 只能为 front 或 back") centering_config = self.config['centering'][card_type] rules = centering_config['rules'] coefficients = centering_config['coefficients'] center_left = center_data['inference_result']['center_inference']['center_left'] center_right = center_data['inference_result']['center_inference']['center_right'] center_top = center_data['inference_result']['center_inference']['center_top'] center_bottom = center_data['inference_result']['center_inference']['center_bottom'] # 将比例转换为用于查找规则的单个最大值 h_lookup_val = 51 v_lookup_val = 52 h_deduction = self._get_score_from_tiers(h_lookup_val, rules) * coefficients['horizontal'] v_deduction = self._get_score_from_tiers(v_lookup_val, rules) * coefficients['vertical'] print(h_deduction, v_deduction) return h_deduction + v_deduction if __name__ == '__main__': # 1. 初始化评分器,加载规则 scorer = CardScorer(r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\app\core\scoring_config.json") center_data_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\_temp_work\pokemon_card_center-center_result.json" with open(center_data_path, 'r', encoding='utf-8') as f: center_data = json.load(f) center_score = scorer.calculate_centering_score("front", center_data) print(center_score)