Explorar o código

配置报错, 和重计算外框的漂移问题

AnlaAnla hai 2 semanas
pai
achega
c6f01d5c61
Modificáronse 4 ficheiros con 43 adicións e 18 borrados
  1. 13 0
      app/api/config_api.py
  2. 1 0
      app/core/config.py
  3. 1 0
      app/main.py
  4. 28 18
      app/utils/defect_inference/AnalyzeCenter.py

+ 13 - 0
app/api/config_api.py

@@ -1,6 +1,9 @@
+import os.path
+
 from fastapi import APIRouter, File, Body, HTTPException, status
 from fastapi import APIRouter, File, Body, HTTPException, status
 from fastapi.responses import FileResponse, JSONResponse
 from fastapi.responses import FileResponse, JSONResponse
 from ..core.config import settings
 from ..core.config import settings
+import datetime
 import json
 import json
 from app.core.logger import get_logger
 from app.core.logger import get_logger
 
 
@@ -176,6 +179,16 @@ async def update_scoring_config(new_config: dict = Body(...)):
         with open(settings.SCORE_CONFIG_PATH, 'w', encoding='utf-8') as f:
         with open(settings.SCORE_CONFIG_PATH, 'w', encoding='utf-8') as f:
             json.dump(new_config, f, indent=2, ensure_ascii=False)
             json.dump(new_config, f, indent=2, ensure_ascii=False)
         logger.info("评分配置文件已成功更新。")
         logger.info("评分配置文件已成功更新。")
+
+        logger.info("保存备份")
+        formatted_time = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
+        backup_name = f"scors_backup_{formatted_time}.json"
+        temp_path = os.path.join(settings.SCORE_BACKUP_PATH, backup_name)
+        with open(temp_path, 'w', encoding='utf-8') as f:
+            json.dump(new_config, f, indent=2, ensure_ascii=False)
+        logger.info("配置备份结束")
+
+
         return JSONResponse(
         return JSONResponse(
             status_code=status.HTTP_200_OK,
             status_code=status.HTTP_200_OK,
             content={"message": "配置已成功更新"}
             content={"message": "配置已成功更新"}

+ 1 - 0
app/core/config.py

@@ -21,6 +21,7 @@ class Settings:
 
 
     TEMP_WORK_DIR = BASE_PATH / "_temp_work"
     TEMP_WORK_DIR = BASE_PATH / "_temp_work"
     SCORE_CONFIG_PATH = BASE_PATH / "app/core/scoring_config.json"
     SCORE_CONFIG_PATH = BASE_PATH / "app/core/scoring_config.json"
+    SCORE_BACKUP_PATH = BASE_PATH / "score_config_backup"
 
 
     # 图片像素与真实图片缩放比例
     # 图片像素与真实图片缩放比例
     PIXEL_RESOLUTION = 24.54
     PIXEL_RESOLUTION = 24.54

+ 1 - 0
app/main.py

@@ -21,6 +21,7 @@ async def lifespan(main_app: FastAPI):
     print("--- 应用启动 ---")
     print("--- 应用启动 ---")
     # --- 文件和目录准备 ---
     # --- 文件和目录准备 ---
     os.makedirs(settings.TEMP_WORK_DIR, exist_ok=True)
     os.makedirs(settings.TEMP_WORK_DIR, exist_ok=True)
+    os.makedirs(settings.SCORE_BACKUP_PATH, exist_ok=True)
 
 
     # --- 模型加载 ---
     # --- 模型加载 ---
     load_models()
     load_models()

+ 28 - 18
app/utils/defect_inference/AnalyzeCenter.py

@@ -224,27 +224,37 @@ def analyze_centering_rect(inner_points: Union[str, List], outer_points: Union[s
     if isinstance(outer_points, str):
     if isinstance(outer_points, str):
         outer_points = get_rect_from_file(outer_points)
         outer_points = get_rect_from_file(outer_points)
 
 
-    # 转换为 numpy 数组
-    inner_contour = np.array(inner_points, dtype=np.int32)
-    outer_contour = np.array(outer_points, dtype=np.int32)
+    # --- 1. 转换为 float32 数组,保留精度 ---
+    inner_contour = np.array(inner_points, dtype=np.float32)
+    outer_contour = np.array(outer_points, dtype=np.float32)
+
+    # --- 2. 手动计算 float 级别的 boundingRect ---
+    def get_float_bounding_rect(points):
+        # points shape: (N, 2)
+        x_min = np.min(points[:, 0])
+        y_min = np.min(points[:, 1])
+        x_max = np.max(points[:, 0])
+        y_max = np.max(points[:, 1])
+
+        w = x_max - x_min
+        h = y_max - y_min
+        return x_min, y_min, w, h
 
 
-    # --- 1. 获取横平竖直的矩形参数 (x, y, w, h) ---
-    # 即使传入的是4个点,用 boundingRect 也能确保取出准确的边界
-    ix, iy, iw, ih = cv2.boundingRect(inner_contour)
-    ox, oy, ow, oh = cv2.boundingRect(outer_contour)
+    ix, iy, iw, ih = get_float_bounding_rect(inner_contour)
+    ox, oy, ow, oh = get_float_bounding_rect(outer_contour)
 
 
     # 构造标准的4点格式返回 (保持和 analyze_centering_rotated 输出一致)
     # 构造标准的4点格式返回 (保持和 analyze_centering_rotated 输出一致)
     def get_box_corners(x, y, w, h):
     def get_box_corners(x, y, w, h):
         return [[x, y], [x + w, y], [x + w, y + h], [x, y + h]]
         return [[x, y], [x + w, y], [x + w, y + h], [x, y + h]]
 
 
-    inner_box_corners_int = get_box_corners(ix, iy, iw, ih)
-    outer_box_corners_int = get_box_corners(ox, oy, ow, oh)
+    inner_box_corners_float = get_box_corners(ix, iy, iw, ih)
+    outer_box_corners_float = get_box_corners(ox, oy, ow, oh)
 
 
-    print("\n--- 基于修正矩形(横平竖直)的分析 ---")
-    print(f"内框: x={ix}, y={iy}, w={iw}, h={ih}")
-    print(f"外框: x={ox}, y={oy}, w={ow}, h={oh}")
+    print("\n--- 基于修正矩形(横平竖直, Float精度)的分析 ---")
+    print(f"内框: x={ix:.2f}, y={iy:.2f}, w={iw:.2f}, h={ih:.2f}")
+    print(f"外框: x={ox:.2f}, y={oy:.2f}, w={ow:.2f}, h={oh:.2f}")
 
 
-    # --- 2. 计算边距 (Margins) ---
+    # --- 3. 计算边距 (Margins) ---
     # 图像坐标系:x向右增加,y向下增加
     # 图像坐标系:x向右增加,y向下增加
 
 
     # 左边距:内框左边 - 外框左边
     # 左边距:内框左边 - 外框左边
@@ -257,7 +267,7 @@ def analyze_centering_rect(inner_points: Union[str, List], outer_points: Union[s
     # 下边距:外框下边(y+h) - 内框下边(y+h)
     # 下边距:外框下边(y+h) - 内框下边(y+h)
     margin_bottom = (oy + oh) - (iy + ih)
     margin_bottom = (oy + oh) - (iy + ih)
 
 
-    # --- 3. 计算百分比 ---
+    # --- 4. 计算百分比 ---
     total_horizontal_margin = margin_left + margin_right
     total_horizontal_margin = margin_left + margin_right
     total_vertical_margin = margin_top + margin_bottom
     total_vertical_margin = margin_top + margin_bottom
 
 
@@ -266,17 +276,17 @@ def analyze_centering_rect(inner_points: Union[str, List], outer_points: Union[s
     top_percent = 50.0
     top_percent = 50.0
     bottom_percent = 50.0
     bottom_percent = 50.0
 
 
-    if total_horizontal_margin > 0:
+    if total_horizontal_margin > 0.0001: # 避免除零
         left_percent = (margin_left / total_horizontal_margin) * 100
         left_percent = (margin_left / total_horizontal_margin) * 100
         right_percent = (margin_right / total_horizontal_margin) * 100
         right_percent = (margin_right / total_horizontal_margin) * 100
         print(f"水平边距分布: 左 {left_percent:.1f}% | 右 {right_percent:.1f}%")
         print(f"水平边距分布: 左 {left_percent:.1f}% | 右 {right_percent:.1f}%")
 
 
-    if total_vertical_margin > 0:
+    if total_vertical_margin > 0.0001:
         top_percent = (margin_top / total_vertical_margin) * 100
         top_percent = (margin_top / total_vertical_margin) * 100
         bottom_percent = (margin_bottom / total_vertical_margin) * 100
         bottom_percent = (margin_bottom / total_vertical_margin) * 100
         print(f"垂直边距分布: 上 {top_percent:.1f}% | 下 {bottom_percent:.1f}%")
         print(f"垂直边距分布: 上 {top_percent:.1f}% | 下 {bottom_percent:.1f}%")
 
 
-    # --- 4. 角度差异 ---
+    # --- 5. 角度差异 ---
     # 因为已经是横平竖直的矩形,角度差默认为 0
     # 因为已经是横平竖直的矩形,角度差默认为 0
     angle_diff = 0.0
     angle_diff = 0.0
 
 
@@ -284,7 +294,7 @@ def analyze_centering_rect(inner_points: Union[str, List], outer_points: Union[s
     # ((左%, 右%), (上%, 下%), 角度差), 内框点集, 外框点集
     # ((左%, 右%), (上%, 下%), 角度差), 内框点集, 外框点集
     return ((left_percent, right_percent),
     return ((left_percent, right_percent),
             (top_percent, bottom_percent),
             (top_percent, bottom_percent),
-            angle_diff), inner_box_corners_int, outer_box_corners_int
+            angle_diff), inner_box_corners_float, outer_box_corners_float
 
 
 
 
 def formate_center_data(center_result,
 def formate_center_data(center_result,