Bladeren bron

card query加入各个类型的详细分数

AnlaAnla 1 maand geleden
bovenliggende
commit
95f47eb43b
6 gewijzigde bestanden met toevoegingen van 172 en 59 verwijderingen
  1. 1 0
      .idea/encodings.xml
  2. 2 3
      Test/test01.py
  3. 3 36
      app/api/cards.py
  4. 1 18
      app/api/images.py
  5. 144 0
      app/utils/card_score_calculate.py
  6. 21 2
      app/utils/scheme.py

+ 1 - 0
.idea/encodings.xml

@@ -5,6 +5,7 @@
     <file url="file://$PROJECT_DIR$/Test/test01.py" charset="GBK" />
     <file url="file://$PROJECT_DIR$/app/api/cards.py" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/app/api/images.py" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/app/utils/card_score_calculate.py" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/app/utils/scheme.py" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/run.py" charset="UTF-8" />
     <file url="PROJECT" charset="GBK" />

+ 2 - 3
Test/test01.py

@@ -1,7 +1,6 @@
 import requests
 
 
-
 def send(url):
     # 请求头 (headers)
     headers = {
@@ -34,6 +33,6 @@ def send(url):
 
 
 if __name__ == '__main__':
-    # base_url = 'http://127.0.0.1:7745/api/cards/query/9'
-    base_url = 'http://192.168.31.243:7745/api/cards/query/3'
+    base_url = 'http://127.0.0.1:7745/api/cards/query/9'
+    # base_url = 'http://192.168.31.243:7745/api/cards/query/3'
     send(base_url)

+ 3 - 36
app/api/cards.py

@@ -7,6 +7,7 @@ from mysql.connector.pooling import PooledMySQLConnection
 from app.core.config import settings
 from app.core.logger import get_logger
 from app.core.database_loader import get_db_connection
+from app.utils.card_score_calculate import card_score_calculate
 from app.utils.scheme import CardDetailResponse, CardImageResponse, CardListDetailResponse
 
 logger = get_logger(__name__)
@@ -67,42 +68,8 @@ def get_card_details(id: int, db_conn: PooledMySQLConnection = db_dependency):
         images = [CardImageResponse.model_validate(row) for row in image_records]
 
         # 计算总分数(只有当图片数量为 4 时才计算)
-        # 初始化
-        card_data["detection_score"] = None
-        card_data["modified_score"] = None
-        if len(images) == 4:
-            try:
-                # ---------- detection_score ----------
-                detection_score = 10.0
-                for img in images:
-                    try:
-                        add_val = img.detection_json.get("result", {}).get("_used_compute_deduct_score", 0)
-                        detection_score += float(add_val or 0)
-                    except Exception as e:
-                        logger.warning(f"解析 detection_json 分数失败 (image_id={img.id}): {e}")
-                card_data["detection_score"] = detection_score
-
-                # ---------- modified_score ----------
-                all_modified_none = all(img.modified_json is None for img in images)
-                if not all_modified_none:
-                    modified_score = 10.0
-                    for img in images:
-                        src = img.modified_json if img.modified_json is not None else img.detection_json
-                        try:
-                            add_val = src.get("result", {}).get("_used_compute_deduct_score", 0)
-                            modified_score += float(add_val or 0)
-                        except Exception as e:
-                            logger.warning(f"解析 modified_json 分数失败 (image_id={img.id}): {e}")
-                    card_data["modified_score"] = modified_score
-                else:
-                    card_data["modified_score"] = None
-
-            except Exception as e:
-                logger.error(f"计算分数过程异常: {e}")
-
-        # 组合成最终响应
-        card_response = CardDetailResponse.model_validate(card_data)
-        card_response.images = images
+        card_response = card_score_calculate(card_data, images)
+
         return card_response
 
     except Exception as e:

+ 1 - 18
app/api/images.py

@@ -3,7 +3,6 @@ import uuid
 import json
 import requests
 from typing import Optional, Dict, Any
-from enum import Enum
 from fastapi import APIRouter, File, UploadFile, Depends, HTTPException, Form, Path
 from fastapi.concurrency import run_in_threadpool
 from fastapi.responses import JSONResponse, FileResponse
@@ -13,29 +12,13 @@ from mysql.connector import IntegrityError
 from app.core.config import settings
 from app.core.logger import get_logger
 from app.utils.scheme import CardImageResponse, ImageJsonPairResponse
+from app.utils.scheme import ImageType, IMAGE_TYPE_TO_SCORE_TYPE
 from app.core.database_loader import get_db_connection
 
 logger = get_logger(__name__)
 router = APIRouter()
 db_dependency = Depends(get_db_connection)
 
-
-class ImageType(str, Enum):
-    front_face = "front_face"
-    back_face = "back_face"
-    front_edge = "front_edge"
-    back_edge = "back_edge"
-
-
-# "图片类型和计算分数分数类型映射表"
-IMAGE_TYPE_TO_SCORE_TYPE = {
-    "front_face": "front_face",
-    "back_face": "back_face",
-    "front_edge": "front_corner_edge",
-    "back_edge": "back_corner_edge",
-}
-
-
 @router.post("/insert/{card_id}", response_model=CardImageResponse, status_code=201,
              summary="为卡牌上传并关联一张图片")
 async def upload_image_for_card(

+ 144 - 0
app/utils/card_score_calculate.py

@@ -0,0 +1,144 @@
+from app.utils.scheme import CardDetailResponse, ImageType
+from app.core.logger import get_logger
+from typing import List
+
+logger = get_logger(__name__)
+
+
+def card_score_calculate(card_data: dict, images: List) -> CardDetailResponse:
+    card_data["detection_score"] = None
+    card_data["modified_score"] = None
+    card_data["detection_score_detail"] = {}
+    card_data["modified_score_detail"] = {}
+    if len(images) == 4:
+        try:
+            # ---------- detection_score ----------
+            detection_score = 10.0
+            detection_center_score = 10.0
+            detection_corner_score = 10.0
+            detection_edge_score = 10.0
+            detection_face_score = 10.0
+            for img in images:
+                try:
+                    # 总分的计算
+                    add_val = img.detection_json.get("result", {}).get("_used_compute_deduct_score", 0)
+                    detection_score += float(add_val or 0)
+
+                    # 累加不同类型的扣分项
+                    if img.image_type == ImageType.front_edge:
+                        center_reduct_val = img.detection_json.get("result", {}).get("center_result", {}).get(
+                            "deduct_score", 0)
+                        corner_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "front_corner_deduct_score", 0)
+                        edge_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "front_edge_deduct_score", 0)
+
+                        detection_center_score += float(center_reduct_val or 0)
+                        detection_corner_score += float(corner_reduct_val or 0)
+                        detection_edge_score += float(edge_reduct_val or 0)
+                    elif img.image_type == ImageType.back_edge:
+                        center_reduct_val = img.detection_json.get("result", {}).get("center_result", {}).get(
+                            "deduct_score", 0
+                        )
+                        corner_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "back_corner_deduct_score", 0)
+                        edge_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "back_edge_deduct_score", 0)
+
+                        detection_center_score += float(center_reduct_val or 0)
+                        detection_corner_score += float(corner_reduct_val or 0)
+                        detection_edge_score += float(edge_reduct_val or 0)
+                    elif img.image_type == ImageType.front_face:
+                        face_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "front_face_deduct_score", 0)
+
+                        detection_face_score += float(face_reduct_val or 0)
+                    elif img.image_type == ImageType.back_face:
+                        face_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
+                            "back_face_deduct_score", 0)
+
+                        detection_face_score += float(face_reduct_val or 0)
+
+                except Exception as e:
+                    logger.warning(f"解析 detection_json 分数失败 (image_id={img.id}): {e}")
+            card_data["detection_score"] = detection_score
+            card_data["detection_score_detail"]["detection_center_score"] = detection_center_score
+            card_data["detection_score_detail"]["detection_corner_score"] = detection_corner_score
+            card_data["detection_score_detail"]["detection_edge_score"] = detection_edge_score
+            card_data["detection_score_detail"]["detection_face_score"] = detection_face_score
+
+            # ---------- modified_score ----------
+            modified_score = 10.0
+            modified_center_score = 10.0
+            modified_corner_score = 10.0
+            modified_edge_score = 10.0
+            modified_face_score = 10.0
+
+            all_modified_none = all(img.modified_json is None for img in images)
+            if not all_modified_none:
+
+                for img in images:
+                    src = img.modified_json if img.modified_json is not None else img.detection_json
+                    try:
+                        # 总分的计算
+                        add_val = src.get("result", {}).get("_used_compute_deduct_score", 0)
+                        modified_score += float(add_val or 0)
+
+                        # 累加不同修改后数据类型的扣分项
+                        if img.image_type == ImageType.front_edge:
+                            center_reduct_val = src.get("result", {}).get("center_result", {}).get(
+                                "deduct_score", 0)
+                            corner_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "front_corner_deduct_score", 0)
+                            edge_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "front_edge_deduct_score", 0)
+
+                            modified_center_score += float(center_reduct_val or 0)
+                            modified_corner_score += float(corner_reduct_val or 0)
+                            modified_edge_score += float(edge_reduct_val or 0)
+                        elif img.image_type == ImageType.back_edge:
+                            center_reduct_val = src.get("result", {}).get("center_result", {}).get(
+                                "deduct_score", 0
+                            )
+                            corner_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "back_corner_deduct_score", 0)
+                            edge_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "back_edge_deduct_score", 0)
+
+                            modified_center_score += float(center_reduct_val or 0)
+                            modified_corner_score += float(corner_reduct_val or 0)
+                            modified_edge_score += float(edge_reduct_val or 0)
+                        elif img.image_type == ImageType.front_face:
+                            face_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "front_face_deduct_score", 0)
+
+                            modified_face_score += float(face_reduct_val or 0)
+                        elif img.image_type == ImageType.back_face:
+                            face_reduct_val = src.get("result", {}).get("defect_result", {}).get(
+                                "back_face_deduct_score", 0)
+
+                            modified_face_score += float(face_reduct_val or 0)
+
+                    except Exception as e:
+                        logger.warning(f"解析 modified_json 分数失败 (image_id={img.id}): {e}")
+                card_data["modified_score"] = modified_score
+
+                card_data["modified_score_detail"]["modified_center_score"] = modified_center_score
+                card_data["modified_score_detail"]["modified_corner_score"] = modified_corner_score
+                card_data["modified_score_detail"]["modified_edge_score"] = modified_edge_score
+                card_data["modified_score_detail"]["modified_face_score"] = modified_face_score
+            else:
+                card_data["modified_score"] = None
+                card_data["modified_score_detail"]["modified_center_score"] = None
+                card_data["modified_score_detail"]["modified_corner_score"] = None
+                card_data["modified_score_detail"]["modified_edge_score"] = None
+                card_data["modified_score_detail"]["modified_face_score"] = None
+
+        except Exception as e:
+            logger.error(f"计算分数过程异常: {e}")
+
+    # 组合成最终响应
+    card_response = CardDetailResponse.model_validate(card_data)
+    card_response.images = images
+
+    return card_response

+ 21 - 2
app/utils/scheme.py

@@ -3,6 +3,23 @@ from datetime import datetime
 from pathlib import Path
 from typing import Optional, Dict, Any, List
 from pydantic import BaseModel, field_validator
+from enum import Enum
+
+
+class ImageType(str, Enum):
+    front_face = "front_face"
+    back_face = "back_face"
+    front_edge = "front_edge"
+    back_edge = "back_edge"
+
+
+# "图片类型和计算分数分数类型映射表"
+IMAGE_TYPE_TO_SCORE_TYPE = {
+    "front_face": "front_face",
+    "back_face": "back_face",
+    "front_edge": "front_corner_edge",
+    "back_edge": "back_corner_edge",
+}
 
 
 # --- Pydantic 数据模型 ---
@@ -43,6 +60,8 @@ class CardDetailResponse(BaseModel):
     updated_at: datetime
     detection_score: Optional[float] = None
     modified_score: Optional[float] = None
+    detection_score_detail: Optional[Dict[str, Any]] = None
+    modified_score_detail: Optional[Dict[str, Any]] = None
     images: List[CardImageResponse] = []
 
     class Config:
@@ -73,10 +92,10 @@ class ImageJsonPairResponse(BaseModel):
 
 class CardListDetailResponse(BaseModel):
     """为新的卡牌列表接口定义的响应模型 (主键为 id)"""
-    id: int  # 原 card_id
+    id: int
     card_name: Optional[str] = None
     created_at: datetime
     updated_at: datetime
 
     class Config:
-        from_attributes = True
+        from_attributes = True