AnlaAnla 3 mesiacov pred
rodič
commit
e52c4fe4d7

+ 1 - 1
Test/切割合并.py

@@ -2,7 +2,7 @@ import json
 import numpy as np
 import cv2
 from typing import Dict
-from app.utils.CardDefectAggregator import CardDefectAggregator
+from app.utils.defect_inference.CardDefectAggregator import CardDefectAggregator
 from pathlib import Path
 
 from app.utils.card_inference.fry_bisenetv2_predictor_V04_250819 import FryBisenetV2Predictor

+ 2 - 2
Test/区分角和边.py

@@ -1,5 +1,5 @@
 import json
-from app.utils.ClassifyEdgeCorner import ClassifyEdgeCorner
+from app.utils.defect_inference.ClassifyEdgeCorner import ClassifyEdgeCorner
 
 
 def load_json_data(json_file):
@@ -21,7 +21,7 @@ if __name__ == '__main__':
     # --- 文件路径配置 ---
     DEFECT_JSON_PATH = r"..\_temp_work\pokemon_front_corner_no_reflect_defect-area_result.json"
     OUTER_BOX_JSON_PATH = '../temp/outer/250805_pokemon_0001.json'  # 包含外框坐标的文件
-    OUTPUT_JSON_PATH = 'classified_defects_result.json'
+    OUTPUT_JSON_PATH = '23.json'
 
     # 加载数据
     defect_data = load_json_data(DEFECT_JSON_PATH)

+ 1 - 1
Test/计算居中.py

@@ -2,7 +2,7 @@ import dataclasses
 import cv2
 import numpy as np
 import json
-from app.utils.AnalyzeCenter import analyze_centering_rotated, draw_rotated_bounding_boxes
+from app.utils.defect_inference.AnalyzeCenter import analyze_centering_rotated, draw_rotated_bounding_boxes
 
 
 

+ 1 - 1
Test/面积计算.py

@@ -1,6 +1,6 @@
 import cv2
 
-from app.utils.arean_anylize_draw import DefectProcessor, to_json_serializable, DrawingParams
+from app.utils.defect_inference.arean_anylize_draw import DefectProcessor, to_json_serializable, DrawingParams
 import json
 
 if __name__ == '__main__':

+ 3 - 2
app/api/card_inference.py

@@ -4,7 +4,7 @@ from fastapi.concurrency import run_in_threadpool
 from enum import Enum
 from ..core.config import settings
 from app.services.card_service import CardInferenceService, card_service
-from app.services.defect_service import DefectInferenceService, defect_service
+from app.services.defect_service import DefectInferenceService
 from app.core.logger import logger
 import json
 
@@ -48,10 +48,11 @@ async def card_model_inference(
              description="环形光居中计算, 环形光正反边角缺陷, 同轴光正反表面缺陷")
 async def card_model_inference(
         defect_type: DefectType,
-        service: DefectInferenceService = Depends(lambda: defect_service),
+        # service: DefectInferenceService = Depends(lambda: defect_service),
         file: UploadFile = File(...),
         is_draw_image: bool = False,
 ):
+    service = DefectInferenceService()
     image_bytes = await file.read()
 
     try:

+ 42 - 0
app/api/score_inference.py

@@ -0,0 +1,42 @@
+from fastapi import APIRouter, File, UploadFile, Depends, HTTPException
+from fastapi.responses import FileResponse, JSONResponse
+from fastapi.concurrency import run_in_threadpool
+from enum import Enum
+from ..core.config import settings
+from app.services.score_service import ScoreService
+from app.core.logger import logger
+import json
+
+router = APIRouter()
+
+score_names = settings.SCORE_TYPE
+ScoreType = Enum("InferenceType", {name: name for name in score_names})
+
+
+@router.post("/score_inference", description="输入卡片类型(正反面, 缺陷类型), 是否为反射卡")
+async def card_model_inference(
+        score_type: ScoreType,
+        is_reflect_card: bool = False,
+        file: UploadFile = File(...)
+):
+    """
+    接收一张卡片图片,使用指定类型的模型进行推理,并返回JSON结果。
+
+    - **inference_type**: 要使用的模型类型(从下拉列表中选择)。
+    - **file**: 要上传的图片文件。
+    """
+    service = ScoreService()
+    image_bytes = await file.read()
+
+    try:
+        json_result = await run_in_threadpool(
+            service.score_inference,
+            score_type=score_type.value,
+            is_reflect_card=is_reflect_card,
+            image_bytes=image_bytes
+        )
+        return json_result
+    except ValueError as e:
+        raise HTTPException(status_code=400, detail=str(e))
+    except Exception as e:
+        raise HTTPException(status_code=500, detail=f"服务器内部错误: {e}")

+ 8 - 2
app/core/config.py

@@ -13,10 +13,13 @@ class CardModelConfig:
 
 
 class Settings:
-    API_prefix: str = "/api/card_inference"
+    API_Inference_prefix: str = "/api/card_inference"
+    API_Score_prefix: str = "/api/card_score"
+
     BASE_PATH = Path(__file__).parent.parent.parent.absolute()
 
     TEMP_WORK_DIR = BASE_PATH / "_temp_work"
+    SCORE_CONFIG_PATH = BASE_PATH / "app/core/scoring_config.json"
 
     # 图片像素与真实图片缩放比例
     PIXEL_RESOLUTION = 24.54
@@ -74,7 +77,7 @@ class Settings:
 
     # 包含, 环形光居中计算, 环形光正反边角缺陷, 同轴光正反表面缺陷
     # 里面存储需要用到的模型类型
-    DEFECT_TYPE: Dict[str, CardModelConfig] = {
+    DEFECT_TYPE: Dict[str, dict] = {
         "pokemon_card_center": {
             "inner_box": "pokemon_inner_box",
             "outer_box": "pokemon_outer_box",
@@ -93,6 +96,9 @@ class Settings:
         }
     }
 
+    SCORE_TYPE: List[str] = ["front_corner_edge", "front_face",
+                             "back_corner_edge", "back_face"]
+
 
 settings = Settings()
 print(settings.BASE_PATH)

+ 24 - 14
app/core/scoring_config.json

@@ -1,6 +1,6 @@
 {
   "base_score": 10.0,
-  "corners": {
+  "corner": {
     "rules": {
       "wear_area": [
         [
@@ -24,7 +24,7 @@
           -5.0
         ]
       ],
-      "sharp_loss_area": [
+      "loss_area": [
         [
           0.05,
           -0.1
@@ -49,18 +49,18 @@
     },
     "front_weights": {
       "wear_area": 0.3,
-      "sharp_loss_area": 0.7
+      "loss_area": 0.7
     },
     "back_weights": {
       "wear_area": 0.3,
-      "sharp_loss_area": 0.7
+      "loss_area": 0.7
     },
     "final_weights": {
       "front": 0.7,
       "back": 0.3
     }
   },
-  "edges": {
+  "edge": {
     "rules": {
       "wear_area": [
         [
@@ -84,7 +84,7 @@
           -5.0
         ]
       ],
-      "block_loss_area": [
+      "loss_area": [
         [
           0.05,
           -0.1
@@ -109,11 +109,11 @@
     },
     "front_weights": {
       "wear_area": 0.4,
-      "block_loss_area": 0.6
+      "loss_area": 0.6
     },
     "back_weights": {
       "wear_area": 0.4,
-      "block_loss_area": 0.6
+      "loss_area": 0.6
     },
     "final_weights": {
       "front": 0.7,
@@ -122,7 +122,7 @@
   },
   "face": {
     "rules": {
-      "dent_area": [
+      "pit_area": [
         [
           0.05,
           -0.1
@@ -169,16 +169,28 @@
       "scratch_length": [
         [
           1.0,
-          -0.5
+          -0.1
         ],
         [
-          3.0,
-          -1.5
+          2.0,
+          -0.5
         ],
         [
           5.0,
+          -1.0
+        ],
+        [
+          10.0,
+          -2.0
+        ],
+        [
+          20.0,
           -3.0
         ],
+        [
+          50.0,
+          -4.0
+        ],
         [
           "inf",
           -5.0
@@ -312,8 +324,6 @@
         "vertical": 0.9
       }
     },
-    "tilt_penalty": -1.5,
-    "tilt_threshold_degrees": 0.5,
     "final_weights": {
       "front": 0.75,
       "back": 0.25

+ 3 - 1
app/main.py

@@ -2,6 +2,7 @@ from fastapi import FastAPI
 from contextlib import asynccontextmanager
 from .core.model_loader import load_models, unload_models
 from app.api.card_inference import router as card_inference_router
+from app.api.score_inference import router as score_inference_router
 import os
 
 from .core.config import settings
@@ -20,4 +21,5 @@ async def lifespan(main_app: FastAPI):
 
 app = FastAPI(title="卡片框和缺陷检测服务", lifespan=lifespan)
 
-app.include_router(card_inference_router, prefix=settings.API_prefix)
+app.include_router(card_inference_router, prefix=settings.API_Inference_prefix)
+app.include_router(score_inference_router, prefix=settings.API_Score_prefix)

+ 5 - 6
app/services/defect_service.py

@@ -1,10 +1,10 @@
 import cv2
 import numpy as np
 from ..core.model_loader import get_predictor
-from app.utils.CardDefectAggregator import CardDefectAggregator
-from app.utils.arean_anylize_draw import DefectProcessor, DrawingParams
-from app.utils.AnalyzeCenter import analyze_centering_rotated
-from app.utils.ClassifyEdgeCorner import ClassifyEdgeCorner
+from app.utils.defect_inference.CardDefectAggregator import CardDefectAggregator
+from app.utils.defect_inference.arean_anylize_draw import DefectProcessor, DrawingParams
+from app.utils.defect_inference.AnalyzeCenter import analyze_centering_rotated
+from app.utils.defect_inference.ClassifyEdgeCorner import ClassifyEdgeCorner
 from app.utils.json_data_formate import formate_center_data, formate_face_data
 from app.core.config import settings
 from app.core.logger import logger
@@ -153,6 +153,5 @@ class DefectInferenceService:
         else:
             return {}
 
-
 # 创建一个单例服务
-defect_service = DefectInferenceService()
+# defect_service = DefectInferenceService()

+ 68 - 0
app/services/score_service.py

@@ -0,0 +1,68 @@
+from app.core.config import settings
+from app.core.logger import logger
+from app.services.defect_service import DefectInferenceService
+from app.utils.score_inference.CardScorer import CardScorer
+from app.utils.json_data_formate import formate_one_card_result
+import json
+
+
+class ScoreService:
+    def __init__(self):
+        self.scoring_config_path = settings.SCORE_CONFIG_PATH
+
+    def score_inference(self, score_type: str, is_reflect_card: bool,
+                        image_bytes: bytes) -> dict:
+        defect_service = DefectInferenceService()
+        card_scorer = CardScorer(config_path=self.scoring_config_path)
+
+        logger.info("开始进行卡片分数推理")
+        center_data = defect_service.defect_inference("pokemon_card_center", image_bytes)
+
+        if is_reflect_card:
+            if score_type == 'front_corner_edge':
+                defect_data = defect_service.defect_inference('pokemon_front_corner_reflect_defect', image_bytes)
+            elif score_type == 'front_face':
+                return {"result": "目前缺少该模型"}
+            elif score_type == 'back_corner_edge':
+                defect_data = defect_service.defect_inference('pokemon_back_corner_defect', image_bytes)
+            elif score_type == 'back_face':
+                return {"result": "目前缺少该模型"}
+            else:
+                return {}
+        else:
+            if score_type == 'front_corner_edge':
+                defect_data = defect_service.defect_inference('pokemon_front_corner_no_reflect_defect', image_bytes)
+            elif score_type == 'front_face':
+                defect_data = defect_service.defect_inference('pokemon_front_face_no_reflect_defect', image_bytes)
+            elif score_type == 'back_corner_edge':
+                defect_data = defect_service.defect_inference('pokemon_back_corner_defect', image_bytes)
+            elif score_type == 'back_face':
+                return {"result": "目前缺少该模型"}
+            else:
+                return {}
+
+        logger.info("模型推理结束, 开始计算分数")
+        if score_type == 'front_corner_edge' or score_type == 'front_face':
+            center_score_data = card_scorer.calculate_centering_score('front', center_data, True)
+        else:
+            center_score_data = card_scorer.calculate_centering_score('back', center_data, True)
+
+        if score_type == 'front_corner_edge':
+            # 先计算角的分数, 会把分数写入json, 然后传入刚写好的, 继续写边的分数
+            corner_score_data = card_scorer.calculate_defect_score('corner', 'front', defect_data, True)
+            defect_score_data = card_scorer.calculate_defect_score('edge', 'front', corner_score_data, True)
+        elif score_type == 'front_face':
+            defect_score_data = card_scorer.calculate_defect_score('face', 'front', defect_data, True)
+        elif score_type == 'back_corner_edge':
+            corner_score_data = card_scorer.calculate_defect_score('corner', 'back', defect_data, True)
+            defect_score_data = card_scorer.calculate_defect_score('edge', 'back', corner_score_data, True)
+        elif score_type == 'back_face':
+            defect_score_data = card_scorer.calculate_defect_score('face', 'back', defect_data, True)
+
+        result_json = formate_one_card_result(center_score_data, defect_score_data)
+
+        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

+ 0 - 96
app/utils/CardScorer.py

@@ -1,96 +0,0 @@
-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)

+ 0 - 0
app/utils/AnalyzeCenter.py → app/utils/defect_inference/AnalyzeCenter.py


+ 0 - 0
app/utils/CardDefectAggregator.py → app/utils/defect_inference/CardDefectAggregator.py


+ 0 - 0
app/utils/ClassifyEdgeCorner.py → app/utils/defect_inference/ClassifyEdgeCorner.py


+ 0 - 0
app/utils/defect_inference/__init__.py


+ 0 - 0
app/utils/arean_anylize_draw.py → app/utils/defect_inference/arean_anylize_draw.py


+ 15 - 3
app/utils/json_data_formate.py

@@ -3,7 +3,7 @@ import json
 
 def formate_center_data(center_result, inner_data: dict, outer_data: dict):
     data = {
-        "inference_result": {
+        "center_result": {
             "center_inference": {
                 "angel_diff": center_result[2],
                 "center_left": center_result[0][0],
@@ -13,8 +13,8 @@ def formate_center_data(center_result, inner_data: dict, outer_data: dict):
             }
         }
     }
-    data['inference_result']['inner_box'] = inner_data
-    data['inference_result']['outer_box'] = outer_data
+    data['center_result']['inner_box'] = inner_data
+    data['center_result']['outer_box'] = outer_data
     return data
 
 
@@ -24,6 +24,18 @@ def formate_face_data(area_json: dict):
         defect['defect_type'] = "face"
     return area_json
 
+
+def formate_one_card_result(center_result: dict, defect_result: dict):
+    data = {
+        "img_id": 2,
+        "img_url": "https://123.jpg",
+        "result": {
+            "center_result": center_result,
+            "defect_result": defect_result
+        }
+    }
+    return data
+
 # if __name__ == '__main__':
 #     json_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\_temp_work\pokemon_front_face_no_reflect_defect-area_result.json"
 #     with open(json_path, 'r') as f:

+ 185 - 0
app/utils/score_inference/CardScorer.py

@@ -0,0 +1,185 @@
+import json
+from typing import List, Dict, Any, Union
+
+
+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,
+                               card_defect_type: str,
+                               card_aspect: str,
+                               defect_data: Dict,
+                               is_write_score: bool = False) -> Union[float, dict]:
+        """
+        一个通用的缺陷计分函数,用于计算角、边、表面的加权分数。
+        card_defect_type: 'corner', 'edge', 'face'
+        card_aspect: 为 front或 back
+        is_write_score: 是否将分数写入json并返回
+        """
+        if card_defect_type != "corner" and card_defect_type != "edge" and card_defect_type != "face":
+            raise TypeError("calculate_centering_score:card_type 只能为 'corner', 'edge', 'face'")
+        if card_aspect != "front" and card_aspect != "back":
+            raise TypeError("calculate_defect_score:card_type 只能为 front 或 back")
+
+        aspect_config = self.config[card_defect_type]
+        total_deduction = 0.0
+        weighted_scores = {}
+
+        # 1. 计算每种缺陷类型的总扣分
+        for defect in defect_data['defects']:
+            if defect['defect_type'] != card_defect_type:
+                continue
+
+            if card_defect_type == 'corner' or card_defect_type == 'edge':
+                if defect['label'] in ['wear', 'wear_and_impact', 'wear_and_stain']:
+                    defect_type = "wear_area"
+                elif defect['label'] in ['impact', 'damaged']:
+                    defect_type = "loss_area"
+                else:
+                    raise TypeError(f"数据缺陷类型不存在: {defect['label']}")
+            else:
+                if defect['label'] in ['scratch']:
+                    defect_type = "scratch_length"
+                elif defect['label'] in ['pit']:
+                    defect_type = "pit_area"
+                elif defect['label'] in ['stain']:
+                    defect_type = "stain_area"
+                else:
+                    raise TypeError(f"数据缺陷类型不存在: {defect['label']}")
+
+            rules = aspect_config['rules'][defect_type]
+            # 对于划痕取长度, 其他取面积
+            if defect_type == "scratch_length":
+                area_mm = max(defect['width'], defect['height'])
+            else:
+                area_mm = defect['actual_area']
+            # 累加所有同类型缺陷的扣分
+            if defect_type not in weighted_scores.keys():
+                weighted_scores[defect_type] = 0
+
+            # 计算单个缺陷扣分
+            the_score = self._get_score_from_tiers(area_mm, rules)
+            print(f"[{card_defect_type}, {defect_type}]: {area_mm}, {the_score}")
+            weighted_scores[defect_type] += the_score
+
+            # 将分数写入json
+            if is_write_score:
+                defect['score'] = the_score
+
+        # 2. 根据权重/系数计算最终扣分
+        weights = aspect_config.get(f"{card_aspect}_weights") or aspect_config.get("coefficients")
+        if not weights:
+            raise ValueError(f"在配置中未找到 '{card_defect_type}' 的权重/系数")
+
+        print(weighted_scores)
+        for defect_type, score in weighted_scores.items():
+            total_deduction += score * weights.get(defect_type, 1.0)
+
+        final_weights = aspect_config["final_weights"][card_aspect]
+        final_score = total_deduction * final_weights
+        print(f"final weights: {final_weights}, final score: {final_score}")
+
+        if is_write_score:
+            defect_data[f'{card_aspect}_{card_defect_type}_score'] = final_score
+            return defect_data
+        else:
+            return final_score
+
+    def calculate_centering_score(self,
+                                  card_aspect: str,
+                                  center_data: dict,
+                                  is_write_score: bool = False) -> Union[float, dict]:
+        """
+        计算居中度分数。
+        card_type 为 front或 back
+        is_write_score: 是否将分数写入json并返回
+        """
+        if card_aspect != "front" and card_aspect != "back":
+            raise TypeError("calculate_centering_score:card_type 只能为 front 或 back")
+
+        centering_config = self.config['centering'][card_aspect]
+        rules = centering_config['rules']
+        coefficients = centering_config['coefficients']
+
+        center_left = center_data['center_result']['center_inference']['center_left']
+        center_right = center_data['center_result']['center_inference']['center_right']
+        center_top = center_data['center_result']['center_inference']['center_top']
+        center_bottom = center_data['center_result']['center_inference']['center_bottom']
+
+        # 将比例转换为用于查找规则的单个最大值
+        h_lookup_val = max(center_left, center_right)
+        v_lookup_val = max(center_top, center_bottom)
+
+        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)
+        final_weight = self.config['centering']["final_weights"][card_aspect]
+        final_score = (h_deduction + v_deduction) * final_weight
+
+        print(f"final weight: {final_weight}, final score: {final_score}")
+
+        if is_write_score:
+            center_data[f'{card_aspect}_score'] = final_score
+            return center_data
+        else:
+            return final_score
+
+
+if __name__ == '__main__':
+    # 1. 初始化评分器,加载规则
+    scorer = CardScorer(r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\app\core\scoring_config.json")
+    # rulers = scorer.config['corners']['rules']['wear_area']
+    #
+    # score = scorer._get_score_from_tiers(0.06, rulers)
+    # print(score)
+    # print()
+
+    # 居中分数
+    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_data = scorer.calculate_centering_score("front", center_data, True)
+    print(center_data)
+
+
+    # 边角分数
+    edge_corner_data_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\_temp_work\pokemon_front_corner_no_reflect_defect-corner_result.json"
+    with open(edge_corner_data_path, 'r', encoding='utf-8') as f:
+        edge_corner_data = json.load(f)
+
+    corner_data = scorer.calculate_defect_score("corner", 'front', edge_corner_data, True)
+    print(corner_data)
+
+    score = scorer.calculate_defect_score("edge", 'front', edge_corner_data, True)
+    print(score)
+
+    # 面分数
+    face_data_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\_temp_work\pokemon_front_face_no_reflect_defect-face_result.json"
+    with open(face_data_path, 'r', encoding='utf-8') as f:
+        face_data = json.load(f)
+
+    score = scorer.calculate_defect_score("face", 'front', face_data, True)
+    print(score)

+ 0 - 0
app/utils/score_inference/__init__.py