card_score_calculate.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. from app.utils.scheme import ImageType, CardImageResponse
  2. from app.core.logger import get_logger
  3. from typing import List, Dict, Any, Optional
  4. logger = get_logger(__name__)
  5. def calculate_scores_from_images(images: List[CardImageResponse]) -> Dict[str, Any]:
  6. """
  7. 根据图片计算分数(兼容 14 图与历史 8 图)。
  8. - 必要条件:front_ring + back_ring 存在
  9. - face 分数来源:同面 stripe(1~4) / coaxial / fusion,按可用图累加
  10. - 不再依赖 coaxial 必须存在
  11. """
  12. scores = {
  13. "detection_score": None,
  14. "modified_score": None,
  15. "detection_score_detail": {
  16. "detection_center_score": None,
  17. "detection_corner_score": None,
  18. "detection_edge_score": None,
  19. "detection_face_score": None
  20. },
  21. "modified_score_detail": {
  22. "modified_center_score": None,
  23. "modified_corner_score": None,
  24. "modified_edge_score": None,
  25. "modified_face_score": None
  26. },
  27. "is_edited": False,
  28. }
  29. def _as_float(value: Any) -> float:
  30. try:
  31. return float(value or 0)
  32. except (TypeError, ValueError):
  33. return 0.0
  34. def _get_reducts(src: Dict[str, Any], side: str) -> Dict[str, float]:
  35. defect_result = src.get("result", {}).get("defect_result", {})
  36. center_result = src.get("result", {}).get("center_result", {})
  37. return {
  38. "total": _as_float(src.get("result", {}).get("_used_compute_deduct_score", 0)),
  39. "center": _as_float(center_result.get("deduct_score", 0)),
  40. "corner": _as_float(defect_result.get(f"{side}_corner_deduct_score", 0)),
  41. "edge": _as_float(defect_result.get(f"{side}_edge_deduct_score", 0)),
  42. "face": _as_float(defect_result.get(f"{side}_face_deduct_score", 0)),
  43. }
  44. front_ring: Optional[CardImageResponse] = None
  45. back_ring: Optional[CardImageResponse] = None
  46. front_face_imgs: List[CardImageResponse] = []
  47. back_face_imgs: List[CardImageResponse] = []
  48. for img in images:
  49. image_type = img.image_type
  50. if image_type == ImageType.front_ring:
  51. front_ring = img
  52. elif image_type == ImageType.back_ring:
  53. back_ring = img
  54. if image_type in [
  55. ImageType.front_stripe1, ImageType.front_stripe2,
  56. ImageType.front_stripe3, ImageType.front_stripe4,
  57. ImageType.front_coaxial, ImageType.front_fusion,
  58. ]:
  59. front_face_imgs.append(img)
  60. elif image_type in [
  61. ImageType.back_stripe1, ImageType.back_stripe2,
  62. ImageType.back_stripe3, ImageType.back_stripe4,
  63. ImageType.back_coaxial, ImageType.back_fusion,
  64. ]:
  65. back_face_imgs.append(img)
  66. # ring 是当前模型计算中心/角/边的必要数据
  67. if not front_ring or not back_ring:
  68. return scores
  69. try:
  70. # ---------- detection_score ----------
  71. detection_score = 10.0
  72. detection_center_score = 10.0
  73. detection_corner_score = 10.0
  74. detection_edge_score = 10.0
  75. detection_face_score = 10.0
  76. for ring_img, side in ((front_ring, "front"), (back_ring, "back")):
  77. try:
  78. reducts = _get_reducts(ring_img.detection_json or {}, side)
  79. detection_score += reducts["total"]
  80. detection_center_score += reducts["center"]
  81. detection_corner_score += reducts["corner"]
  82. detection_edge_score += reducts["edge"]
  83. detection_face_score += reducts["face"]
  84. except Exception as e:
  85. logger.warning(f"解析 detection_json 分数失败 (image_id={ring_img.id}): {e}")
  86. # 同面 face 辅助图(stripe/coaxial/fusion)叠加 face 与 total
  87. for side, face_imgs in (("front", front_face_imgs), ("back", back_face_imgs)):
  88. for img in face_imgs:
  89. try:
  90. reducts = _get_reducts(img.detection_json or {}, side)
  91. detection_score += reducts["total"]
  92. detection_face_score += reducts["face"]
  93. except Exception as e:
  94. logger.warning(f"解析 detection_json 分数失败 (image_id={img.id}): {e}")
  95. scores["detection_score"] = detection_score
  96. scores["detection_score_detail"] = {
  97. "detection_center_score": detection_center_score,
  98. "detection_corner_score": detection_corner_score,
  99. "detection_edge_score": detection_edge_score,
  100. "detection_face_score": detection_face_score,
  101. }
  102. # ---------- modified_score ----------
  103. modified_score = 10.0
  104. modified_center_score = 10.0
  105. modified_corner_score = 10.0
  106. modified_edge_score = 10.0
  107. modified_face_score = 10.0
  108. all_score_images = [front_ring, back_ring] + front_face_imgs + back_face_imgs
  109. is_edited = any(img.modified_json is not None for img in all_score_images if img is not None)
  110. scores["is_edited"] = is_edited
  111. if is_edited:
  112. for ring_img, side in ((front_ring, "front"), (back_ring, "back")):
  113. src = ring_img.modified_json if ring_img.modified_json is not None else ring_img.detection_json
  114. try:
  115. reducts = _get_reducts(src or {}, side)
  116. modified_score += reducts["total"]
  117. modified_center_score += reducts["center"]
  118. modified_corner_score += reducts["corner"]
  119. modified_edge_score += reducts["edge"]
  120. modified_face_score += reducts["face"]
  121. except Exception as e:
  122. logger.warning(f"解析 modified_json 分数失败 (image_id={ring_img.id}): {e}")
  123. for side, face_imgs in (("front", front_face_imgs), ("back", back_face_imgs)):
  124. for img in face_imgs:
  125. src = img.modified_json if img.modified_json is not None else img.detection_json
  126. try:
  127. reducts = _get_reducts(src or {}, side)
  128. modified_score += reducts["total"]
  129. modified_face_score += reducts["face"]
  130. except Exception as e:
  131. logger.warning(f"解析 modified_json 分数失败 (image_id={img.id}): {e}")
  132. scores["modified_score"] = modified_score
  133. scores["modified_score_detail"] = {
  134. "modified_center_score": modified_center_score,
  135. "modified_corner_score": modified_corner_score,
  136. "modified_edge_score": modified_edge_score,
  137. "modified_face_score": modified_face_score,
  138. }
  139. except Exception as e:
  140. logger.error(f"计算分数过程异常: {e}")
  141. return scores