| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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)
|