Эх сурвалжийг харах

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

AnlaAnla 1 сар өмнө
parent
commit
95f47eb43b

+ 1 - 0
.idea/encodings.xml

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

+ 2 - 3
Test/test01.py

@@ -1,7 +1,6 @@
 import requests
 import requests
 
 
 
 
-
 def send(url):
 def send(url):
     # 请求头 (headers)
     # 请求头 (headers)
     headers = {
     headers = {
@@ -34,6 +33,6 @@ def send(url):
 
 
 
 
 if __name__ == '__main__':
 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)
     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.config import settings
 from app.core.logger import get_logger
 from app.core.logger import get_logger
 from app.core.database_loader import get_db_connection
 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
 from app.utils.scheme import CardDetailResponse, CardImageResponse, CardListDetailResponse
 
 
 logger = get_logger(__name__)
 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]
         images = [CardImageResponse.model_validate(row) for row in image_records]
 
 
         # 计算总分数(只有当图片数量为 4 时才计算)
         # 计算总分数(只有当图片数量为 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
         return card_response
 
 
     except Exception as e:
     except Exception as e:

+ 1 - 18
app/api/images.py

@@ -3,7 +3,6 @@ import uuid
 import json
 import json
 import requests
 import requests
 from typing import Optional, Dict, Any
 from typing import Optional, Dict, Any
-from enum import Enum
 from fastapi import APIRouter, File, UploadFile, Depends, HTTPException, Form, Path
 from fastapi import APIRouter, File, UploadFile, Depends, HTTPException, Form, Path
 from fastapi.concurrency import run_in_threadpool
 from fastapi.concurrency import run_in_threadpool
 from fastapi.responses import JSONResponse, FileResponse
 from fastapi.responses import JSONResponse, FileResponse
@@ -13,29 +12,13 @@ from mysql.connector import IntegrityError
 from app.core.config import settings
 from app.core.config import settings
 from app.core.logger import get_logger
 from app.core.logger import get_logger
 from app.utils.scheme import CardImageResponse, ImageJsonPairResponse
 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
 from app.core.database_loader import get_db_connection
 
 
 logger = get_logger(__name__)
 logger = get_logger(__name__)
 router = APIRouter()
 router = APIRouter()
 db_dependency = Depends(get_db_connection)
 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,
 @router.post("/insert/{card_id}", response_model=CardImageResponse, status_code=201,
              summary="为卡牌上传并关联一张图片")
              summary="为卡牌上传并关联一张图片")
 async def upload_image_for_card(
 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 pathlib import Path
 from typing import Optional, Dict, Any, List
 from typing import Optional, Dict, Any, List
 from pydantic import BaseModel, field_validator
 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 数据模型 ---
 # --- Pydantic 数据模型 ---
@@ -43,6 +60,8 @@ class CardDetailResponse(BaseModel):
     updated_at: datetime
     updated_at: datetime
     detection_score: Optional[float] = None
     detection_score: Optional[float] = None
     modified_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] = []
     images: List[CardImageResponse] = []
 
 
     class Config:
     class Config:
@@ -73,10 +92,10 @@ class ImageJsonPairResponse(BaseModel):
 
 
 class CardListDetailResponse(BaseModel):
 class CardListDetailResponse(BaseModel):
     """为新的卡牌列表接口定义的响应模型 (主键为 id)"""
     """为新的卡牌列表接口定义的响应模型 (主键为 id)"""
-    id: int  # 原 card_id
+    id: int
     card_name: Optional[str] = None
     card_name: Optional[str] = None
     created_at: datetime
     created_at: datetime
     updated_at: datetime
     updated_at: datetime
 
 
     class Config:
     class Config:
-        from_attributes = True
+        from_attributes = True