|
@@ -1,14 +1,16 @@
|
|
|
from app.utils.scheme import ImageType, CardImageResponse
|
|
from app.utils.scheme import ImageType, CardImageResponse
|
|
|
from app.core.logger import get_logger
|
|
from app.core.logger import get_logger
|
|
|
-from typing import List, Dict, Any
|
|
|
|
|
|
|
+from typing import List, Dict, Any, Optional
|
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, Any]:
|
|
def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, Any]:
|
|
|
"""
|
|
"""
|
|
|
- 根据图片计算分数。
|
|
|
|
|
- 已更新为新的类型名称: front_coaxial, front_ring 等。
|
|
|
|
|
|
|
+ 根据图片计算分数(兼容 14 图与历史 8 图)。
|
|
|
|
|
+ - 必要条件:front_ring + back_ring 存在
|
|
|
|
|
+ - face 分数来源:同面 stripe(1~4) / coaxial / fusion,按可用图累加
|
|
|
|
|
+ - 不再依赖 coaxial 必须存在
|
|
|
"""
|
|
"""
|
|
|
scores = {
|
|
scores = {
|
|
|
"detection_score": None,
|
|
"detection_score": None,
|
|
@@ -28,13 +30,50 @@ def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, A
|
|
|
"is_edited": False,
|
|
"is_edited": False,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- # 过滤掉灰度图,只计算主4张图
|
|
|
|
|
- valid_images = [img for img in images if img.image_type in [
|
|
|
|
|
- ImageType.front_coaxial, ImageType.back_coaxial,
|
|
|
|
|
- ImageType.front_ring, ImageType.back_ring
|
|
|
|
|
- ]]
|
|
|
|
|
|
|
+ def _as_float(value: Any) -> float:
|
|
|
|
|
+ try:
|
|
|
|
|
+ return float(value or 0)
|
|
|
|
|
+ except (TypeError, ValueError):
|
|
|
|
|
+ return 0.0
|
|
|
|
|
+
|
|
|
|
|
+ def _get_reducts(src: Dict[str, Any], side: str) -> Dict[str, float]:
|
|
|
|
|
+ defect_result = src.get("result", {}).get("defect_result", {})
|
|
|
|
|
+ center_result = src.get("result", {}).get("center_result", {})
|
|
|
|
|
+ return {
|
|
|
|
|
+ "total": _as_float(src.get("result", {}).get("_used_compute_deduct_score", 0)),
|
|
|
|
|
+ "center": _as_float(center_result.get("deduct_score", 0)),
|
|
|
|
|
+ "corner": _as_float(defect_result.get(f"{side}_corner_deduct_score", 0)),
|
|
|
|
|
+ "edge": _as_float(defect_result.get(f"{side}_edge_deduct_score", 0)),
|
|
|
|
|
+ "face": _as_float(defect_result.get(f"{side}_face_deduct_score", 0)),
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if len(valid_images) != 4:
|
|
|
|
|
|
|
+ front_ring: Optional[CardImageResponse] = None
|
|
|
|
|
+ back_ring: Optional[CardImageResponse] = None
|
|
|
|
|
+ front_face_imgs: List[CardImageResponse] = []
|
|
|
|
|
+ back_face_imgs: List[CardImageResponse] = []
|
|
|
|
|
+
|
|
|
|
|
+ for img in images:
|
|
|
|
|
+ image_type = img.image_type
|
|
|
|
|
+ if image_type == ImageType.front_ring:
|
|
|
|
|
+ front_ring = img
|
|
|
|
|
+ elif image_type == ImageType.back_ring:
|
|
|
|
|
+ back_ring = img
|
|
|
|
|
+
|
|
|
|
|
+ if image_type in [
|
|
|
|
|
+ ImageType.front_stripe1, ImageType.front_stripe2,
|
|
|
|
|
+ ImageType.front_stripe3, ImageType.front_stripe4,
|
|
|
|
|
+ ImageType.front_coaxial, ImageType.front_fusion,
|
|
|
|
|
+ ]:
|
|
|
|
|
+ front_face_imgs.append(img)
|
|
|
|
|
+ elif image_type in [
|
|
|
|
|
+ ImageType.back_stripe1, ImageType.back_stripe2,
|
|
|
|
|
+ ImageType.back_stripe3, ImageType.back_stripe4,
|
|
|
|
|
+ ImageType.back_coaxial, ImageType.back_fusion,
|
|
|
|
|
+ ]:
|
|
|
|
|
+ back_face_imgs.append(img)
|
|
|
|
|
+
|
|
|
|
|
+ # ring 是当前模型计算中心/角/边的必要数据
|
|
|
|
|
+ if not front_ring or not back_ring:
|
|
|
return scores
|
|
return scores
|
|
|
|
|
|
|
|
try:
|
|
try:
|
|
@@ -45,53 +84,26 @@ def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, A
|
|
|
detection_edge_score = 10.0
|
|
detection_edge_score = 10.0
|
|
|
detection_face_score = 10.0
|
|
detection_face_score = 10.0
|
|
|
|
|
|
|
|
- for img in valid_images:
|
|
|
|
|
|
|
+ for ring_img, side in ((front_ring, "front"), (back_ring, "back")):
|
|
|
try:
|
|
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_ring:
|
|
|
|
|
- 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)
|
|
|
|
|
- face_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
|
|
|
|
|
- "front_face_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)
|
|
|
|
|
- detection_face_score += float(face_reduct_val or 0)
|
|
|
|
|
-
|
|
|
|
|
- elif img.image_type == ImageType.back_ring:
|
|
|
|
|
- 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)
|
|
|
|
|
- face_reduct_val = img.detection_json.get("result", {}).get("defect_result", {}).get(
|
|
|
|
|
- "back_face_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)
|
|
|
|
|
- detection_face_score += float(face_reduct_val or 0)
|
|
|
|
|
-
|
|
|
|
|
- elif img.image_type == ImageType.front_coaxial:
|
|
|
|
|
- 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_coaxial: # 原 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)
|
|
|
|
|
-
|
|
|
|
|
|
|
+ reducts = _get_reducts(ring_img.detection_json or {}, side)
|
|
|
|
|
+ detection_score += reducts["total"]
|
|
|
|
|
+ detection_center_score += reducts["center"]
|
|
|
|
|
+ detection_corner_score += reducts["corner"]
|
|
|
|
|
+ detection_edge_score += reducts["edge"]
|
|
|
|
|
+ detection_face_score += reducts["face"]
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
- logger.warning(f"解析 detection_json 分数失败 (image_id={img.id}): {e}")
|
|
|
|
|
|
|
+ logger.warning(f"解析 detection_json 分数失败 (image_id={ring_img.id}): {e}")
|
|
|
|
|
+
|
|
|
|
|
+ # 同面 face 辅助图(stripe/coaxial/fusion)叠加 face 与 total
|
|
|
|
|
+ for side, face_imgs in (("front", front_face_imgs), ("back", back_face_imgs)):
|
|
|
|
|
+ for img in face_imgs:
|
|
|
|
|
+ try:
|
|
|
|
|
+ reducts = _get_reducts(img.detection_json or {}, side)
|
|
|
|
|
+ detection_score += reducts["total"]
|
|
|
|
|
+ detection_face_score += reducts["face"]
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.warning(f"解析 detection_json 分数失败 (image_id={img.id}): {e}")
|
|
|
|
|
|
|
|
scores["detection_score"] = detection_score
|
|
scores["detection_score"] = detection_score
|
|
|
scores["detection_score_detail"] = {
|
|
scores["detection_score_detail"] = {
|
|
@@ -108,53 +120,32 @@ def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, A
|
|
|
modified_edge_score = 10.0
|
|
modified_edge_score = 10.0
|
|
|
modified_face_score = 10.0
|
|
modified_face_score = 10.0
|
|
|
|
|
|
|
|
- is_edited = any(img.modified_json is not None for img in valid_images)
|
|
|
|
|
|
|
+ all_score_images = [front_ring, back_ring] + front_face_imgs + back_face_imgs
|
|
|
|
|
+ is_edited = any(img.modified_json is not None for img in all_score_images if img is not None)
|
|
|
scores["is_edited"] = is_edited
|
|
scores["is_edited"] = is_edited
|
|
|
|
|
|
|
|
if is_edited:
|
|
if is_edited:
|
|
|
- for img in valid_images:
|
|
|
|
|
- src = img.modified_json if img.modified_json is not None else img.detection_json
|
|
|
|
|
|
|
+ for ring_img, side in ((front_ring, "front"), (back_ring, "back")):
|
|
|
|
|
+ src = ring_img.modified_json if ring_img.modified_json is not None else ring_img.detection_json
|
|
|
try:
|
|
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_ring:
|
|
|
|
|
- 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)
|
|
|
|
|
- face_reduct_val = src.get("result", {}).get("defect_result", {}).get("front_face_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)
|
|
|
|
|
- modified_face_score += float(face_reduct_val or 0)
|
|
|
|
|
- elif img.image_type == ImageType.back_ring:
|
|
|
|
|
- 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)
|
|
|
|
|
- face_reduct_val = src.get("result", {}).get("defect_result", {}).get("back_face_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)
|
|
|
|
|
- modified_face_score += float(face_reduct_val or 0)
|
|
|
|
|
- elif img.image_type == ImageType.front_coaxial:
|
|
|
|
|
- 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_coaxial:
|
|
|
|
|
- face_reduct_val = src.get("result", {}).get("defect_result", {}).get("back_face_deduct_score",
|
|
|
|
|
- 0)
|
|
|
|
|
- modified_face_score += float(face_reduct_val or 0)
|
|
|
|
|
-
|
|
|
|
|
|
|
+ reducts = _get_reducts(src or {}, side)
|
|
|
|
|
+ modified_score += reducts["total"]
|
|
|
|
|
+ modified_center_score += reducts["center"]
|
|
|
|
|
+ modified_corner_score += reducts["corner"]
|
|
|
|
|
+ modified_edge_score += reducts["edge"]
|
|
|
|
|
+ modified_face_score += reducts["face"]
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
- logger.warning(f"解析 modified_json 分数失败 (image_id={img.id}): {e}")
|
|
|
|
|
|
|
+ logger.warning(f"解析 modified_json 分数失败 (image_id={ring_img.id}): {e}")
|
|
|
|
|
+
|
|
|
|
|
+ for side, face_imgs in (("front", front_face_imgs), ("back", back_face_imgs)):
|
|
|
|
|
+ for img in face_imgs:
|
|
|
|
|
+ src = img.modified_json if img.modified_json is not None else img.detection_json
|
|
|
|
|
+ try:
|
|
|
|
|
+ reducts = _get_reducts(src or {}, side)
|
|
|
|
|
+ modified_score += reducts["total"]
|
|
|
|
|
+ modified_face_score += reducts["face"]
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.warning(f"解析 modified_json 分数失败 (image_id={img.id}): {e}")
|
|
|
|
|
|
|
|
scores["modified_score"] = modified_score
|
|
scores["modified_score"] = modified_score
|
|
|
scores["modified_score_detail"] = {
|
|
scores["modified_score_detail"] = {
|