AnlaAnla 3 сар өмнө
parent
commit
a837961b76

+ 0 - 0
Model/back_defect.pth → Model/pokemon_back_defect.pth


BIN
Model/inner_box.pth → Model/pokemon_inner_box.pth


BIN
Model/outer_box.pth → Model/pokemon_no_reflect_front_defect.pth


BIN
Model/pokemon_outer_box.pth


BIN
Model/no_reflect_front_defect.pth → Model/pokemon_reflect_front_defect.pth


+ 63 - 0
Test/draw_potin.py

@@ -0,0 +1,63 @@
+from app.utils.handle_result import process_detection_result
+import cv2
+import matplotlib.pyplot as plt
+import json
+
+
+# 示例使用
+if __name__ == "__main__":
+    img_path = r"C:\Users\wow38\Pictures\WhimsicottUnifiedMinds144.jpg"
+    json_data_path = r"C:\Users\wow38\Pictures\123.json"
+
+    with open(json_data_path, "r") as f:
+        json_data = json.load(f)
+
+    image = cv2.imread(img_path)
+
+    # 为不同类别设置不同颜色
+    label_colors = {
+        'baseboard': (0, 255, 0),
+    }
+
+    result = process_detection_result(image, json_data, label_colors)
+
+    # 显示结果
+    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
+    plt.show()
+
+    # cv2.imshow("Result", result)
+    # cv2.waitKey(0)
+    # cv2.destroyAllWindows()
+
+
+    # # 加载示例图像
+    # image = cv2.imread("example.jpg")
+    #
+    # # 为不同类别设置不同颜色
+    # label_colors = {
+    #     'baseboard': (0, 255, 0),
+    # }
+    #
+    # # 示例检测结果
+    # detection_result = {
+    #     'num': 1,
+    #     'cls': [1],
+    #     'names': ['baseboard'],
+    #     'conf': 0.9966249431977074,
+    #     'shapes': [{
+    #         'class_num': 1,
+    #         'label': 'baseboard',
+    #         'probability': 0.9966249431977074,
+    #         'points': [[5, 171], [4, 172], [0, 172], [0, 487], [34, 487],
+    #                    # ... 其他点 ...
+    #                    [1019, 172], [1018, 171]]
+    #     }]
+    # }
+    #
+    # # 处理图像
+    # result = process_detection_result(image, detection_result, label_colors)
+    #
+    # # 显示结果
+    # cv2.imshow("Result", result)
+    # cv2.waitKey(0)
+    # cv2.destroyAllWindows()

+ 94 - 0
Test/model_test01.py

@@ -0,0 +1,94 @@
+import os
+from pathlib import Path
+from app.utils.fry_bisenetv2_predictor_V04_250819 import FryBisenetV2Predictor
+
+BASE_PATH = Path(__file__).parent.parent.absolute()
+# model_inner_box_path = BASE_PATH / "Model/pokemon_inner_box.pth"
+# model_outer_box_path = BASE_PATH / "Model/pokemon_outer_box.pth"
+
+
+def _test_pokemon_inner_box(model_path=None,
+                            real_seg_class_dict = {1: 'inner_box'},
+imgSize_train_dict = {'width': 1280, 'height': 1280}
+                            ):
+    # 配置参数
+    input_channels = 3
+
+    real_seg_class_dict = {1: 'inner_box'}
+
+    # 为不同类别设置不同颜色(可选)
+    label_colors_dict = {
+        'outer_box': (255, 0, 0),
+    }
+
+    imgSize_train_dict = {'width': 1280, 'height': 1280}
+    confidence = 0.5
+
+    # 创建预测器
+    predictor = FryBisenetV2Predictor(
+        pth_path=str(model_path),
+        real_seg_class_dict=real_seg_class_dict,
+        imgSize_train_dict=imgSize_train_dict,
+        confidence=confidence,
+        label_colors_dict=label_colors_dict,
+        input_channels=input_channels,
+    )
+
+    # 单张图片预测
+    print("=== 单张图片预测 ===")
+    now_img_path = r"C:\Code\ML\Project\StitchImageServer\temp\output\0_half_importance_add_weight\final_stitched_image.jpg"
+    answer_json_dir_str = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\inner"
+
+    result = predictor.predict_single_image(
+        img_path=now_img_path,
+        save_visualization=True,
+        save_json=True,
+        answer_json_dir_str=answer_json_dir_str
+    )
+
+
+if __name__ == '__main__':
+    config = {
+        "pokemon_outer_box": {
+            "pth_path": "Model/pokemon_outer_box.pth",
+            "class_dict": {1: 'outer_box'},
+            "img_size": {'width': 1280, 'height': 1280},
+            "confidence": 0.5,
+            "input_channels": 3,
+        },
+        "pokemon_inner_box": {
+            "pth_path": "Model/pokemon_inner_box.pth",
+            "class_dict": {1: 'inner_box'},
+            "img_size": {'width': 1280, 'height': 1280},
+            "confidence": 0.5,
+            "input_channels": 3,
+        },
+        "pokemon_back_defect": {
+            "pth_path": "Model/pokemon_back_defect.pth",
+            "class_dict": {
+                1: 'wear', 2: 'wear_and_impact', 3: 'impact',
+                4: 'damaged', 5: 'wear_and_stain',
+            },
+            "img_size": {'width': 512, 'height': 512},
+            "confidence": 0.5,
+            "input_channels": 3,
+        },
+        "pokemon_reflect_front_defect": {
+            "pth_path": "Model/pokemon_reflect_front_defect.pth",
+            "class_dict": {"1": "impact",
+                           "2": "wear_and_impact",
+                           "3": "wear"},
+            "img_size": {'width': 512, 'height': 512},
+            "confidence": 0.5,
+            "input_channels": 3,
+        },
+        "pokemon_no_reflect_front_defect": {
+            "pth_path": "Model/pokemon_reflect_front_defect.pth",
+            "class_dict": {1: 'scratch',
+                           2: 'pit',
+                           3: 'stain'},
+            "img_size": {'width': 512, 'height': 512},
+            "confidence": 0.5,
+            "input_channels": 3,
+        }}
+    _test_pokemon_inner_box()

+ 17 - 9
app/core/config.py

@@ -18,22 +18,22 @@ class Settings:
     # 使用一个字典来管理所有卡片检测模型
     # key (如 'outer_box') 将成为 API 路径中的 {inference_type}
     CARD_MODELS_CONFIG: Dict[str, CardModelConfig] = {
-        "outer_box": {
-            "pth_path": "Model/outer_box.pth",
+        "pokemon_outer_box": {
+            "pth_path": "Model/pokemon_outer_box.pth",
             "class_dict": {1: 'outer_box'},
             "img_size": {'width': 1280, 'height': 1280},
             "confidence": 0.5,
             "input_channels": 3,
         },
-        "inner_box": {
-            "pth_path": "Model/inner_box.pth",
+        "pokemon_inner_box": {
+            "pth_path": "Model/pokemon_inner_box.pth",
             "class_dict": {1: 'inner_box'},
             "img_size": {'width': 1280, 'height': 1280},
             "confidence": 0.5,
             "input_channels": 3,
         },
-        "back_defect": {
-            "pth_path": "Model/back_defect.pth",
+        "pokemon_back_defect": {
+            "pth_path": "Model/pokemon_back_defect.pth",
             "class_dict": {
                 1: 'wear', 2: 'wear_and_impact', 3: 'impact',
                 4: 'damaged', 5: 'wear_and_stain',
@@ -42,8 +42,17 @@ class Settings:
             "confidence": 0.5,
             "input_channels": 3,
         },
-        "no_reflect_front_defect": {
-            "pth_path": "Model/no_reflect_front_defect.pth",
+        "pokemon_reflect_front_defect": {
+            "pth_path": "Model/pokemon_reflect_front_defect.pth",
+            "class_dict": {"1": "impact",
+                           "2": "wear_and_impact",
+                           "3": "wear"},
+            "img_size": {'width': 512, 'height': 512},
+            "confidence": 0.5,
+            "input_channels": 3,
+        },
+        "pokemon_no_reflect_front_defect": {
+            "pth_path": "Model/pokemon_reflect_front_defect.pth",
             "class_dict": {1: 'scratch',
                            2: 'pit',
                            3: 'stain'},
@@ -51,7 +60,6 @@ class Settings:
             "confidence": 0.5,
             "input_channels": 3,
         }
-
     }
 
 

+ 1 - 1
app/core/model_loader.py

@@ -1,6 +1,6 @@
 from typing import Dict
 from .config import settings
-from ..utils.fry_bisenetv2_predictor_V01_250811 import FryBisenetV2Predictor
+from ..utils.fry_bisenetv2_predictor_V04_250819 import FryBisenetV2Predictor
 
 # 全局的模型预测器字典
 predictors: Dict[str, FryBisenetV2Predictor] = {}

+ 27 - 27
app/utils/backbone.py

@@ -1,5 +1,6 @@
 import torch
 import torch.nn as nn
+import time
 
 
 class ConvBNReLU(nn.Module):
@@ -427,34 +428,33 @@ class OhemCELoss(nn.Module):
         return loss_hard_mean
 
 
-# if __name__ == "__main__":
-#
-#     # ==========================================================
-#     # 支持不同输入通道的bisenetv2
-#     # ==========================================================
-#
-#     input_channels = 7
-#
-#     x = torch.randn(2, input_channels, 256, 256).cuda()
-#     # x = torch.randn(2, 3, 224, 224).cuda()
-#     print("=============输入:=============")
-#     print(x.shape)
-#
-#     model = BiSeNetV2(n_classes=19,input_channels=7)
-#
-#     device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
-#     print(device)
-#     model = model.to(device)
-#
-#     netBeforeTime = time.time()
-#     outs = model(x)
-#     netEndTime = time.time()
-#     print("模型推理花费时间:",netEndTime-netBeforeTime)
-#     print("=============输出:=============")
-#     for out in outs:
-#         print(out.size())
-#     #  print(logits.size())
+if __name__ == "__main__":
 
+    # ==========================================================
+    # 支持不同输入通道的bisenetv2
+    # ==========================================================
+
+    input_channels = 7
+
+    x = torch.randn(2, input_channels, 256, 256).cuda()
+    # x = torch.randn(2, 3, 224, 224).cuda()
+    print("=============输入:=============")
+    print(x.shape)
+
+    model = BiSeNetV2(n_classes=19, input_channels=7)
+
+    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+    print(device)
+    model = model.to(device)
+
+    netBeforeTime = time.time()
+    outs = model(x)
+    netEndTime = time.time()
+    print("模型推理花费时间:", netEndTime - netBeforeTime)
+    print("=============输出:=============")
+    for out in outs:
+        print(out.size())
+    #  print(logits.size())
 
 """
 =============输入:=============

+ 7 - 4
app/utils/create_predict_result.py

@@ -1,12 +1,13 @@
+import copy
 import numpy as np
 import cv2
 from pathlib import Path
 import time
 
-from app.utils.data_augmentation import LetterBox
 
+from app.utils.data_augmentation import LetterBox
 
-def point_mapTo_originImg(originImgSize, imgSize_train, now_point):
+def point_mapTo_originImg(originImgSize,imgSize_train, now_point):
     letterBox = LetterBox(imgSize_train)
     rect_dict = letterBox.get_offset(originImgSize)
 
@@ -21,9 +22,10 @@ def point_mapTo_originImg(originImgSize, imgSize_train, now_point):
     return new_point
 
 
-def create_result_singleImg(segClassDict, now_ansImgDict, originImgSize, imgSize_train, confidence=0.5):
+def create_result_singleImg(segClassDict,now_ansImgDict, originImgSize, imgSize_train,confidence = 0.5):
     """ansImg_list.append({"ans_img":ansImg,"probs":probs,"file_name":file_name})"""
 
+
     label = now_ansImgDict['ans_img']
     probs = now_ansImgDict['probs']
     file_name = now_ansImgDict['file_name']
@@ -97,7 +99,7 @@ def create_result_singleImg(segClassDict, now_ansImgDict, originImgSize, imgSize
                             nowPoint = externalContour[i]
                             nowPoint_list = nowPoint[0].tolist()
                             # 点要放到到原图上面
-                            new_point = point_mapTo_originImg(originImgSize, imgSize_train, nowPoint_list)
+                            new_point = point_mapTo_originImg(originImgSize,imgSize_train, nowPoint_list)
 
                             nowPntList.append(new_point)
 
@@ -115,3 +117,4 @@ def create_result_singleImg(segClassDict, now_ansImgDict, originImgSize, imgSize
 
     per_result['num'] = len(per_result['shapes'])
     return per_result
+

+ 9 - 21
app/utils/data_augmentation.py

@@ -1,14 +1,10 @@
-import copy
-import random
-import numpy as np
-import math
-import cv2
 import numpy as np
 import math
 import cv2
 
+
 class LetterBox(object):
-    def __init__(self, size={'width':640,'height':640},  auto=False, stride=32,*args, **kwargs):
+    def __init__(self, size={'width': 640, 'height': 640}, auto=False, stride=32, *args, **kwargs):
         # 需要调整的额size
         self.size = size
         self.h = size["height"]
@@ -16,7 +12,6 @@ class LetterBox(object):
         self.auto = auto  # pass max size integer, automatically solve for short side using stride
         self.stride = stride  # used with auto
 
-
     def __call__(self, im_lb):
         imgList = im_lb['imgList']
         lb = im_lb['lb']
@@ -35,9 +30,7 @@ class LetterBox(object):
         returnObj = dict(imgList=ans_imgList, lb=ans_lb)
         return returnObj
 
-
-
-    def handle_imgList(self,imgList):
+    def handle_imgList(self, imgList):
         # 处理图片
         ans_imgList = []
         for per_img in imgList:
@@ -45,7 +38,7 @@ class LetterBox(object):
             ans_imgList.append(ans_img)
         return ans_imgList
 
-    def get_offset(self,originImgSize={'width':4096,'height':7000}):
+    def get_offset(self, originImgSize={'width': 4096, 'height': 7000}):
 
         # _240429_1543_
         # [特别注意]:ResizeBeforeLetterbox中重写了这个逻辑
@@ -84,8 +77,7 @@ class LetterBox(object):
 
             return before_letterbox_dict
 
-
-        before_letterbox_dict = fry_resize_realParams(originH,originW,dstH,dstW)
+        before_letterbox_dict = fry_resize_realParams(originH, originW, dstH, dstW)
 
         rect_dict = {}
         rect_dict['x'] = before_letterbox_dict['pad_left']
@@ -95,7 +87,6 @@ class LetterBox(object):
         rect_dict['ratio'] = before_letterbox_dict['ratio']
         return rect_dict
 
-
     def handle_single_img(self, im):
         assert len(im.shape) == 3, "im 必须是3维的"
         assert (im.shape[2] == 1) or (im.shape[2] == 3), "im 的通道数必须是一个通道或者三个通道"
@@ -109,14 +100,14 @@ class LetterBox(object):
 
         # 这里弄成0没有关系,因为均值是0方差是1
         # 还是都弄成114吧
-        if im.shape[2]==3:
+        if im.shape[2] == 3:
             im_out = np.full((self.h, self.w, 3), 114, dtype=im.dtype)
-        elif im.shape[2]==1:
+        elif im.shape[2] == 1:
             im_out = np.full((self.h, self.w, 1), 114, dtype=im.dtype)
         else:
             raise ValueError("图片的通道数异常")
 
-        if im.shape[2]==1:
+        if im.shape[2] == 1:
             gray_image_hw1 = im
             gray_image_hw = np.squeeze(gray_image_hw1, axis=-1)
             singleImg = gray_image_hw
@@ -125,20 +116,17 @@ class LetterBox(object):
 
         originImg_resized = cv2.resize(singleImg, (w, h), interpolation=cv2.INTER_LINEAR)
 
-
-        if len(originImg_resized.shape)==2:
+        if len(originImg_resized.shape) == 2:
             newSingleImg2D = originImg_resized
             newSingleImg3D = np.expand_dims(newSingleImg2D, axis=-1)
             newSingleImg = newSingleImg3D
         else:
             newSingleImg = originImg_resized
 
-
         im_out[top:top + h, left:left + w] = newSingleImg
 
         return im_out
 
-
     def handle_single_label(self, im):
         assert len(im.shape) == 2, "label 必须是2维的"
 

+ 161 - 125
app/utils/fry_bisenetv2_predictor_V01_250811.py → app/utils/fry_bisenetv2_predictor_V04_250819.py

@@ -1,6 +1,7 @@
 import numpy as np
 import json
 import torch
+import datetime
 import torch.nn as nn
 import cv2
 from pathlib import Path
@@ -260,51 +261,14 @@ class FryBisenetV2Predictor:
         with open(json_path, 'w', encoding='utf-8') as f:
             json.dump(json_result, f, ensure_ascii=False, indent=2)
 
-    def predict_from_image(self, img_bgr: np.ndarray) -> Dict:
-        """
-        直接从解码后的图像数据(numpy数组)进行预测。
-
-        Args:
-            img_bgr: BGR格式的图像,作为一个numpy数组。
-
-        Returns:
-            预测结果字典。
-        """
-        # 检查通道数是否匹配
-        shape = img_bgr.shape
-        image_channel = shape[2] if len(shape) == 3 else 1
-        if image_channel != self.input_channels:
-            raise ValueError(
-                f"输入图片的通道数和模型不匹配:image_channel:{image_channel},input_channels:{self.input_channels}")
-
-        # 获取原始图片尺寸
-        height, width = img_bgr.shape[:2]
-        originImgSize = {'width': width, 'height': height}
-
-        # 预处理
-        imgTensor_CHW_norm = predict_preprocess(img_bgr, self.imgSize_train_dict)
-
-        # 预测
-        ansImgDict = self._predict_tensor(imgTensor_CHW_norm)
-
-        # 创建结果
-        per_img_seg_result = create_result_singleImg(
-            self.seg_class_dict,
-            ansImgDict,
-            originImgSize,
-            self.imgSize_train_dict,
-            confidence=self.confidence
-        )
-
-        return per_img_seg_result
-
-    def predict_single_image(self,
-                             img_path: str,
-                             save_visualization: bool = True,
-                             save_json: bool = True,
-                             answer_json_dir: Optional[str] = None,
-                             input_channels=3
-                             ) -> Dict:
+    def predict_single_image_np(self,
+                                img_bgr: np.ndarray,
+                                image_path_str: str = None,
+                                save_visualization: bool = True,
+                                save_json: bool = True,
+                                answer_json_dir_str: Optional[str] = None,
+                                input_channels=3
+                                ) -> Dict:
         """
         预测单张图片
 
@@ -312,20 +276,20 @@ class FryBisenetV2Predictor:
             img_path: 图片路径
             save_visualization: 是否保存可视化结果
             save_json: 是否保存JSON结果
-            answer_json_dir: JSON结果保存目录
+            answer_json_dir_str: JSON结果保存目录
 
         Returns:
             预测结果字典
         """
+        if image_path_str is None:
+            timestamp = datetime.now().strftime('%y%m%d_%H%M%S_%f')
+            image_path_real_str = f"{timestamp}.jpg"
+        else:
+            image_path_real_str = str(image_path_str)
 
-        img_path_obj = Path(img_path).resolve()
-        img_path_parent_obj = img_path_obj.parent
-        answer_json_dir_obj = Path(answer_json_dir).resolve()
+        img_path_real_obj = Path(image_path_real_str).resolve()
 
-        # 读取图片
-        img_bgr = cv2.imread(img_path)
-        if img_bgr is None:
-            raise ValueError(f"无法读取图片:{img_path}")
+        answer_json_dir_str_obj = Path(answer_json_dir_str).resolve()
 
         shape = img_bgr.shape
         image_channel = shape[2]
@@ -355,22 +319,27 @@ class FryBisenetV2Predictor:
         # 预测
         ansImgDict = self._predict_tensor(imgTensor_CHW_norm)
 
+        image_path_name = str(img_path_real_obj.name)
+
         # 创建结果
         per_img_seg_result = create_result_singleImg(
             self.seg_class_dict,
             ansImgDict,
             originImgSize,
             self.imgSize_train_dict,
-            confidence=self.confidence
+            confidence=self.confidence,
         )
 
         # 保存JSON结果
-        if save_json and answer_json_dir:
-            json_dir = Path(answer_json_dir)
+        if save_json and answer_json_dir_str:
+            json_dir = Path(answer_json_dir_str)
             json_dir.mkdir(parents=True, exist_ok=True)
 
+            if image_path_str is None:
+                cv2.imwrite(image_path_real_str, img_bgr)
+
             # 获取图片文件名(不含扩展名)
-            img_name = Path(img_path).stem
+            img_name = Path(img_path_real_obj).stem
             json_path = json_dir / f"{img_name}.json"
 
             self._save_result_json(per_img_seg_result, json_path)
@@ -379,18 +348,123 @@ class FryBisenetV2Predictor:
         # 保存可视化结果
         if save_visualization:
             result_img = process_detection_result(img_bgr, per_img_seg_result, self.label_colors_dict)
-            output_path = str(answer_json_dir_obj / f"{Path(img_path).stem}_result.jpg")
+            output_path = str(answer_json_dir_str_obj / f"{img_path_real_obj.name}")
 
             cv2.imwrite(output_path, result_img)
             fry_algo_print("成功", f"可视化结果已保存到:{output_path}")
 
         return per_img_seg_result
 
+    def _save_result_json(self, result: Dict, json_path: Path):
+        """
+        保存预测结果为JSON文件
+
+        Args:
+            result: 预测结果字典
+            json_path: JSON文件保存路径
+        """
+        # 将numpy数组转换为可序列化的格式
+        json_result = {}
+
+        for key, value in result.items():
+            if isinstance(value, np.ndarray):
+                json_result[key] = value.tolist()
+            elif isinstance(value, dict):
+                json_result[key] = {}
+                for k, v in value.items():
+                    if isinstance(v, np.ndarray):
+                        json_result[key][k] = v.tolist()
+                    else:
+                        json_result[key][k] = v
+            else:
+                json_result[key] = value
+
+        with open(json_path, 'w', encoding='utf-8') as f:
+            json.dump(json_result, f, ensure_ascii=False, indent=2)
+
+    def predict_from_image(self, img_bgr: np.ndarray) -> Dict:
+        """
+        直接从解码后的图像数据(numpy数组)进行预测。
+
+        Args:
+            img_bgr: BGR格式的图像,作为一个numpy数组。
+
+        Returns:
+            预测结果字典。
+        """
+        # 检查通道数是否匹配
+        shape = img_bgr.shape
+        image_channel = shape[2] if len(shape) == 3 else 1
+        if image_channel != self.input_channels:
+            raise ValueError(
+                f"输入图片的通道数和模型不匹配:image_channel:{image_channel},input_channels:{self.input_channels}")
+
+        # 获取原始图片尺寸
+        height, width = img_bgr.shape[:2]
+        originImgSize = {'width': width, 'height': height}
+
+        # 预处理
+        imgTensor_CHW_norm = predict_preprocess(img_bgr, self.imgSize_train_dict)
+
+        # 预测
+        ansImgDict = self._predict_tensor(imgTensor_CHW_norm)
+
+        # 创建结果
+        per_img_seg_result = create_result_singleImg(
+            self.seg_class_dict,
+            ansImgDict,
+            originImgSize,
+            self.imgSize_train_dict,
+            confidence=self.confidence
+        )
+
+        return per_img_seg_result
+
+    def predict_single_image(self,
+                             img_path: str,
+                             save_visualization: bool = True,
+                             save_json: bool = True,
+                             answer_json_dir_str: Optional[str] = None,
+                             input_channels=3
+                             ) -> Dict:
+        """
+        预测单张图片
+
+        Args:
+            img_path: 图片路径
+            save_visualization: 是否保存可视化结果
+            save_json: 是否保存JSON结果
+            answer_json_dir_str: JSON结果保存目录
+
+        Returns:
+            预测结果字典
+        """
+
+        img_path_obj = Path(img_path).resolve()
+        img_path_parent_obj = img_path_obj.parent
+        answer_json_dir_str_obj = Path(answer_json_dir_str).resolve()
+
+        # 读取图片
+        img_bgr = cv2.imread(str(img_path_obj))
+        if img_bgr is None:
+            raise ValueError(f"无法读取图片:{img_path}")
+
+        per_img_seg_result = self.predict_single_image_np(
+            img_bgr=img_bgr,
+            image_path_str=str(img_path_obj),
+            save_visualization=save_visualization,
+            save_json=save_json,
+            answer_json_dir_str=answer_json_dir_str,
+            input_channels=input_channels
+        )
+
+        return per_img_seg_result
+
     def predict_batch(self,
                       img_paths: List[str],
                       save_visualization: bool = True,
                       save_json: bool = True,
-                      answer_json_dir: Optional[str] = None,
+                      answer_json_dir_str: Optional[str] = None,
                       input_channels=3
                       ) -> List[Dict]:
         """
@@ -400,18 +474,18 @@ class FryBisenetV2Predictor:
             img_paths: 图片路径列表
             save_visualization: 是否保存可视化结果
             save_json: 是否保存JSON结果
-            answer_json_dir: JSON结果保存目录
+            answer_json_dir_str: JSON结果保存目录
             output_dir: 可视化结果保存目录
 
         Returns:
             所有图片的预测结果列表
         """
 
-        answer_json_dir_obj = Path(answer_json_dir).resolve()
+        answer_json_dir_str_obj = Path(answer_json_dir_str).resolve()
 
         results = []
 
-        Path(answer_json_dir).mkdir(parents=True, exist_ok=True)
+        Path(answer_json_dir_str).mkdir(parents=True, exist_ok=True)
 
         # 批量处理
         for i, img_path in enumerate(img_paths):
@@ -444,18 +518,22 @@ class FryBisenetV2Predictor:
                 # 预测
                 ansImgDict = self._predict_tensor(imgTensor_CHW_norm)
 
+                img_path_obj = Path(img_path).resolve()
+                image_path_name = str(img_path_obj.name)
+
                 # 创建结果
                 per_img_seg_result = create_result_singleImg(
                     self.seg_class_dict,
                     ansImgDict,
                     originImgSize,
                     self.imgSize_train_dict,
-                    confidence=self.confidence
+                    confidence=self.confidence,
+                    image_path_name=image_path_name
                 )
 
                 # 保存JSON结果
-                if save_json and answer_json_dir:
-                    json_dir = Path(answer_json_dir)
+                if save_json and answer_json_dir_str:
+                    json_dir = Path(answer_json_dir_str)
                     json_dir.mkdir(parents=True, exist_ok=True)
 
                     img_name = Path(img_path).stem
@@ -465,8 +543,7 @@ class FryBisenetV2Predictor:
                 # 保存可视化结果
                 if save_visualization:
                     result_img = process_detection_result(img_bgr, per_img_seg_result, self.label_colors_dict)
-
-                    output_path = answer_json_dir_obj / f"{Path(img_path).stem}_result.jpg"
+                    output_path = answer_json_dir_str_obj / f"{Path(img_path).name}"
 
                     cv2.imwrite(str(output_path), result_img)
 
@@ -483,14 +560,14 @@ class FryBisenetV2Predictor:
 def main():
     """使用示例"""
     # 配置参数
-    pth_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\Model\outer_box.pth"
+    pth_path = r"segmentation_bisenetv2.pth"
     input_channels = 3
 
     real_seg_class_dict = {1: 'outer_box'}
 
     # 为不同类别设置不同颜色(可选)
     label_colors_dict = {
-        'outer_box': (225, 0, 0),
+        'outer_box': (255, 0, 0),
     }
 
     imgSize_train_dict = {'width': 1280, 'height': 1280}
@@ -508,14 +585,14 @@ def main():
 
     # 单张图片预测
     print("=== 单张图片预测 ===")
-    now_img_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\img.png"
-    answer_json_dir = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\outer"
+    now_img_path = r"input_output\images\coaxis_0008.jpg"
+    answer_json_dir_str = r"input_output\images_answer_json_dir_str"
 
     result = predictor.predict_single_image(
         img_path=now_img_path,
         save_visualization=True,
         save_json=True,
-        answer_json_dir=answer_json_dir,
+        answer_json_dir_str=answer_json_dir_str,
         input_channels=input_channels,
     )
 
@@ -532,14 +609,14 @@ def main():
     #     img_paths=img_paths,
     #     save_visualization=True,
     #     save_json=True,
-    #     answer_json_dir=answer_json_dir,
+    #     answer_json_dir_str=answer_json_dir_str,
     #     input_channels=input_channels,
     # )
 
 
 def _test_pokemon_inner_box():
     # 配置参数
-    pth_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\Model\inner_box.pth"
+    pth_path = r"E:\_250807_训练好的导出的模型\_250808_1043_宝可梦内框训练效果还行\pth_and_images\segmentation_bisenetv2.pth"
     input_channels = 3
 
     real_seg_class_dict = {1: 'inner_box'}
@@ -564,20 +641,20 @@ def _test_pokemon_inner_box():
 
     # 单张图片预测
     print("=== 单张图片预测 ===")
-    now_img_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\img.png"
-    answer_json_dir = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\inner"
+    now_img_path = r"E:\_250807_训练好的导出的模型\_250808_1043_宝可梦内框训练效果还行\pth_and_images\images\diff_big_00065.jpg"
+    answer_json_dir_str = r"E:\_250807_训练好的导出的模型\_250808_1043_宝可梦内框训练效果还行\pth_and_images\images_answer"
 
     result = predictor.predict_single_image(
         img_path=now_img_path,
         save_visualization=True,
         save_json=True,
-        answer_json_dir=answer_json_dir
+        answer_json_dir_str=answer_json_dir_str
     )
 
 
 def _test_pokemon_back_edge():
     # 配置参数
-    pth_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\Model\back_defect.pth"
+    pth_path = r"E:\_250807_训练好的导出的模型\_250811_1104_宝可梦背面边角\pth_and_images\segmentation_bisenetv2.pth"
     input_channels = 3
 
     real_seg_class_dict = {
@@ -607,60 +684,19 @@ def _test_pokemon_back_edge():
 
     # 单张图片预测
     print("=== 单张图片预测 ===")
-    now_img_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\img_2.png"
-    answer_json_dir = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\defect"
+    now_img_path = r"E:\_250807_训练好的导出的模型\_250811_1104_宝可梦背面边角\pth_and_images\images\split\Pokémon_back_for_Edge_0001_bottom_grid_r0_c0.jpg"
+    answer_json_dir_str = r"E:\_250807_训练好的导出的模型\_250811_1104_宝可梦背面边角\pth_and_images\images_answer"
 
     result = predictor.predict_single_image(
         img_path=now_img_path,
         save_visualization=True,
         save_json=True,
-        answer_json_dir=answer_json_dir,
+        answer_json_dir_str=answer_json_dir_str,
         input_channels=input_channels
     )
 
-def _test_pokemon_no_reflect_front():
-    # 配置参数
-    pth_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\Model\no_reflect_front_defect.pth"
-    input_channels = 3
-
-    real_seg_class_dict = {
-        1: 'scratch',
-        2: 'pit',
-        3: 'stain'
-    }
-
-    # 为不同类别设置不同颜色(可选)
-    # label_colors_dict = {
-    #     'outer_box': (255, 0, 0),
-    # }
-
-    imgSize_train_dict = {'width': 512, 'height': 512}
-    confidence = 0.5
-
-    # 创建预测器
-    predictor = FryBisenetV2Predictor(
-        pth_path=pth_path,
-        real_seg_class_dict=real_seg_class_dict,
-        imgSize_train_dict=imgSize_train_dict,
-        confidence=confidence,
-        input_channels=input_channels,
-    )
-
-    # 单张图片预测
-    print("=== 单张图片预测 ===")
-    now_img_path = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\img_1.png"
-    answer_json_dir = r"C:\Code\ML\Project\CheckCardBoxAndDefectServer\temp\no_reflect_front_defect"
-
-    result = predictor.predict_single_image(
-        img_path=now_img_path,
-        save_visualization=True,
-        save_json=True,
-        answer_json_dir=answer_json_dir,
-        input_channels=input_channels
-    )
 
 if __name__ == "__main__":
-    # main()
-    # _test_pokemon_inner_box()
-    # _test_pokemon_back_edge()
-    _test_pokemon_no_reflect_front()
+    main()
+    # test_pokemon_inner_box()
+    # test_pokemon_back_edge()

+ 3 - 5
app/utils/handle_result.py

@@ -1,6 +1,6 @@
 import cv2
 import numpy as np
-from typing import List, Dict, Tuple, Union
+from typing import List, Dict, Tuple
 
 
 class ShapeDrawer:
@@ -123,8 +123,6 @@ def process_detection_result(image: np.ndarray,
     """
     result = image.copy()
 
-
-
     # 处理每个检测到的形状
     for shape in detection['shapes']:
         points = shape['points']
@@ -187,7 +185,7 @@ if __name__ == "__main__":
     }
 
     # 处理图像
-    result = process_detection_result(image, detection_result,label_colors)
+    result = process_detection_result(image, detection_result, label_colors)
 
     # 显示结果
     cv2.imshow("Result", result)
@@ -195,4 +193,4 @@ if __name__ == "__main__":
     cv2.destroyAllWindows()
 
     # 保存结果
-    # cv2.imwrite("result.jpg", result)
+    # cv2.imwrite("result.jpg", result)

+ 12 - 1
app/utils/predict_preprocess.py

@@ -1,16 +1,26 @@
+import copy
+import random
+import numpy as np
 import math
 import cv2
 import numpy as np
 import math
+
 import torch
 import torch.nn as nn
 import torchvision.transforms as transforms
 import cv2
+import __main__
+import sys
+import os
+import time
+
 
 from app.utils.data_augmentation import LetterBox
 
 
 def predict_preprocess(img_bgr, imgSize_train):
+
     device_str = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
     img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
@@ -23,7 +33,7 @@ def predict_preprocess(img_bgr, imgSize_train):
     imgTensor = torch.tensor(img_np, dtype=torch.float32, device=device_str)
 
     # 将所有元素值除以255,进行归一化
-    imgTensor = imgTensor * (1 / 255.0)
+    imgTensor = imgTensor * (1/255.0)
 
     # 把形状从[H, W, C] 改为 [C, H, W]
     imgTensor_CHW = imgTensor.permute(2, 0, 1)
@@ -34,3 +44,4 @@ def predict_preprocess(img_bgr, imgSize_train):
     imgTensor_CHW_norm = normaliz_operate_c3(imgTensor_CHW)
 
     return imgTensor_CHW_norm
+

+ 1 - 1
run.py

@@ -2,4 +2,4 @@ import uvicorn
 
 if __name__ == "__main__":
     print("http://127.0.0.1:7744/docs")
-    uvicorn.run("app.main:app", host="0.0.0.0", port=7744)
+    uvicorn.run("app.main:app", host="0.0.0.0", port=7744, reload=True)

+ 0 - 1786
temp/test_return.json

@@ -1,1786 +0,0 @@
-{
-  "img_id": 2,
-  "img_url": "https://archives.bulbagarden.net/media/upload/5/50/WhimsicottUnifiedMinds144.jpg",
-  "inference_result": {
-    "center_inference": {
-      "center_left": -0.1,
-      "center_bottom": 0.2,
-      "inner_box": {
-        "num": 1,
-        "cls": [
-          1
-        ],
-        "names": [
-          "inner_box"
-        ],
-        "conf": 0.9988297375720048,
-        "shapes": [
-          {
-            "class_num": 1,
-            "label": "inner_box",
-            "probability": 0.9988297375720048,
-            "points": [
-              [
-                1594,
-                184
-              ],
-              [
-                1592,
-                186
-              ],
-              [
-                1493,
-                186
-              ],
-              [
-                1491,
-                187
-              ],
-              [
-                1294,
-                187
-              ],
-              [
-                1293,
-                189
-              ],
-              [
-                1178,
-                189
-              ],
-              [
-                1176,
-                190
-              ],
-              [
-                1056,
-                190
-              ],
-              [
-                1054,
-                192
-              ],
-              [
-                958,
-                192
-              ],
-              [
-                957,
-                194
-              ],
-              [
-                790,
-                194
-              ],
-              [
-                789,
-                195
-              ],
-              [
-                590,
-                195
-              ],
-              [
-                589,
-                197
-              ],
-              [
-                445,
-                197
-              ],
-              [
-                443,
-                198
-              ],
-              [
-                440,
-                198
-              ],
-              [
-                440,
-                200
-              ],
-              [
-                437,
-                203
-              ],
-              [
-                437,
-                205
-              ],
-              [
-                432,
-                210
-              ],
-              [
-                432,
-                211
-              ],
-              [
-                430,
-                213
-              ],
-              [
-                430,
-                216
-              ],
-              [
-                429,
-                218
-              ],
-              [
-                429,
-                256
-              ],
-              [
-                430,
-                258
-              ],
-              [
-                430,
-                518
-              ],
-              [
-                432,
-                520
-              ],
-              [
-                432,
-                755
-              ],
-              [
-                434,
-                757
-              ],
-              [
-                434,
-                926
-              ],
-              [
-                435,
-                928
-              ],
-              [
-                435,
-                1050
-              ],
-              [
-                437,
-                1051
-              ],
-              [
-                437,
-                1214
-              ],
-              [
-                438,
-                1216
-              ],
-              [
-                438,
-                1347
-              ],
-              [
-                440,
-                1349
-              ],
-              [
-                440,
-                1547
-              ],
-              [
-                442,
-                1549
-              ],
-              [
-                442,
-                1688
-              ],
-              [
-                443,
-                1690
-              ],
-              [
-                443,
-                1782
-              ],
-              [
-                445,
-                1784
-              ],
-              [
-                445,
-                1808
-              ],
-              [
-                443,
-                1810
-              ],
-              [
-                445,
-                1811
-              ],
-              [
-                445,
-                1834
-              ],
-              [
-                443,
-                1835
-              ],
-              [
-                445,
-                1837
-              ],
-              [
-                445,
-                1926
-              ],
-              [
-                446,
-                1928
-              ],
-              [
-                446,
-                1931
-              ],
-              [
-                448,
-                1933
-              ],
-              [
-                448,
-                1936
-              ],
-              [
-                450,
-                1938
-              ],
-              [
-                450,
-                1939
-              ],
-              [
-                453,
-                1942
-              ],
-              [
-                454,
-                1942
-              ],
-              [
-                456,
-                1944
-              ],
-              [
-                458,
-                1944
-              ],
-              [
-                459,
-                1946
-              ],
-              [
-                462,
-                1946
-              ],
-              [
-                464,
-                1947
-              ],
-              [
-                518,
-                1947
-              ],
-              [
-                520,
-                1946
-              ],
-              [
-                614,
-                1946
-              ],
-              [
-                616,
-                1944
-              ],
-              [
-                766,
-                1944
-              ],
-              [
-                768,
-                1942
-              ],
-              [
-                934,
-                1942
-              ],
-              [
-                936,
-                1941
-              ],
-              [
-                1059,
-                1941
-              ],
-              [
-                1061,
-                1939
-              ],
-              [
-                1165,
-                1939
-              ],
-              [
-                1166,
-                1938
-              ],
-              [
-                1378,
-                1938
-              ],
-              [
-                1379,
-                1936
-              ],
-              [
-                1613,
-                1936
-              ],
-              [
-                1614,
-                1934
-              ],
-              [
-                1630,
-                1934
-              ],
-              [
-                1632,
-                1936
-              ],
-              [
-                1653,
-                1936
-              ],
-              [
-                1654,
-                1934
-              ],
-              [
-                1658,
-                1934
-              ],
-              [
-                1659,
-                1933
-              ],
-              [
-                1661,
-                1933
-              ],
-              [
-                1667,
-                1926
-              ],
-              [
-                1667,
-                1925
-              ],
-              [
-                1669,
-                1923
-              ],
-              [
-                1669,
-                1920
-              ],
-              [
-                1670,
-                1918
-              ],
-              [
-                1670,
-                1914
-              ],
-              [
-                1672,
-                1912
-              ],
-              [
-                1670,
-                1910
-              ],
-              [
-                1670,
-                1646
-              ],
-              [
-                1669,
-                1645
-              ],
-              [
-                1669,
-                1448
-              ],
-              [
-                1667,
-                1446
-              ],
-              [
-                1667,
-                1267
-              ],
-              [
-                1666,
-                1266
-              ],
-              [
-                1666,
-                1074
-              ],
-              [
-                1664,
-                1072
-              ],
-              [
-                1664,
-                962
-              ],
-              [
-                1662,
-                960
-              ],
-              [
-                1662,
-                842
-              ],
-              [
-                1661,
-                840
-              ],
-              [
-                1661,
-                672
-              ],
-              [
-                1659,
-                670
-              ],
-              [
-                1659,
-                507
-              ],
-              [
-                1658,
-                506
-              ],
-              [
-                1658,
-                405
-              ],
-              [
-                1656,
-                403
-              ],
-              [
-                1656,
-                269
-              ],
-              [
-                1654,
-                267
-              ],
-              [
-                1654,
-                202
-              ],
-              [
-                1653,
-                200
-              ],
-              [
-                1653,
-                195
-              ],
-              [
-                1650,
-                192
-              ],
-              [
-                1650,
-                190
-              ],
-              [
-                1648,
-                189
-              ],
-              [
-                1646,
-                189
-              ],
-              [
-                1643,
-                186
-              ],
-              [
-                1635,
-                186
-              ],
-              [
-                1634,
-                184
-              ]
-            ]
-          }
-        ]
-      },
-      "outer_box": {
-        "num": 1,
-        "cls": [
-          1
-        ],
-        "names": [
-          "outer_box"
-        ],
-        "conf": 0.9990946511284866,
-        "shapes": [
-          {
-            "class_num": 1,
-            "label": "outer_box",
-            "probability": 0.9990946511284866,
-            "points": [
-              [
-                1539,
-                134
-              ],
-              [
-                1538,
-                136
-              ],
-              [
-                1426,
-                136
-              ],
-              [
-                1424,
-                138
-              ],
-              [
-                1336,
-                138
-              ],
-              [
-                1334,
-                139
-              ],
-              [
-                1256,
-                139
-              ],
-              [
-                1254,
-                141
-              ],
-              [
-                1147,
-                141
-              ],
-              [
-                1146,
-                142
-              ],
-              [
-                981,
-                142
-              ],
-              [
-                979,
-                144
-              ],
-              [
-                854,
-                144
-              ],
-              [
-                853,
-                146
-              ],
-              [
-                643,
-                146
-              ],
-              [
-                642,
-                147
-              ],
-              [
-                517,
-                147
-              ],
-              [
-                515,
-                149
-              ],
-              [
-                429,
-                149
-              ],
-              [
-                427,
-                150
-              ],
-              [
-                422,
-                150
-              ],
-              [
-                421,
-                152
-              ],
-              [
-                416,
-                152
-              ],
-              [
-                414,
-                154
-              ],
-              [
-                413,
-                154
-              ],
-              [
-                411,
-                155
-              ],
-              [
-                410,
-                155
-              ],
-              [
-                408,
-                157
-              ],
-              [
-                406,
-                157
-              ],
-              [
-                405,
-                158
-              ],
-              [
-                403,
-                158
-              ],
-              [
-                398,
-                163
-              ],
-              [
-                397,
-                163
-              ],
-              [
-                390,
-                170
-              ],
-              [
-                390,
-                171
-              ],
-              [
-                386,
-                176
-              ],
-              [
-                386,
-                178
-              ],
-              [
-                382,
-                181
-              ],
-              [
-                382,
-                182
-              ],
-              [
-                381,
-                184
-              ],
-              [
-                381,
-                186
-              ],
-              [
-                379,
-                187
-              ],
-              [
-                379,
-                192
-              ],
-              [
-                378,
-                194
-              ],
-              [
-                378,
-                205
-              ],
-              [
-                376,
-                206
-              ],
-              [
-                376,
-                360
-              ],
-              [
-                378,
-                362
-              ],
-              [
-                378,
-                710
-              ],
-              [
-                379,
-                712
-              ],
-              [
-                379,
-                917
-              ],
-              [
-                381,
-                918
-              ],
-              [
-                381,
-                1093
-              ],
-              [
-                382,
-                1094
-              ],
-              [
-                382,
-                1250
-              ],
-              [
-                384,
-                1251
-              ],
-              [
-                384,
-                1365
-              ],
-              [
-                386,
-                1366
-              ],
-              [
-                386,
-                1494
-              ],
-              [
-                387,
-                1496
-              ],
-              [
-                387,
-                1634
-              ],
-              [
-                389,
-                1635
-              ],
-              [
-                389,
-                1744
-              ],
-              [
-                390,
-                1746
-              ],
-              [
-                390,
-                1867
-              ],
-              [
-                392,
-                1869
-              ],
-              [
-                392,
-                1941
-              ],
-              [
-                394,
-                1942
-              ],
-              [
-                394,
-                1954
-              ],
-              [
-                395,
-                1955
-              ],
-              [
-                395,
-                1960
-              ],
-              [
-                397,
-                1962
-              ],
-              [
-                397,
-                1965
-              ],
-              [
-                398,
-                1966
-              ],
-              [
-                398,
-                1968
-              ],
-              [
-                400,
-                1970
-              ],
-              [
-                400,
-                1971
-              ],
-              [
-                402,
-                1973
-              ],
-              [
-                402,
-                1974
-              ],
-              [
-                403,
-                1976
-              ],
-              [
-                403,
-                1978
-              ],
-              [
-                416,
-                1990
-              ],
-              [
-                418,
-                1990
-              ],
-              [
-                419,
-                1992
-              ],
-              [
-                421,
-                1992
-              ],
-              [
-                424,
-                1995
-              ],
-              [
-                426,
-                1995
-              ],
-              [
-                427,
-                1997
-              ],
-              [
-                430,
-                1997
-              ],
-              [
-                432,
-                1998
-              ],
-              [
-                434,
-                1998
-              ],
-              [
-                435,
-                2000
-              ],
-              [
-                438,
-                2000
-              ],
-              [
-                440,
-                2002
-              ],
-              [
-                448,
-                2002
-              ],
-              [
-                450,
-                2003
-              ],
-              [
-                526,
-                2003
-              ],
-              [
-                528,
-                2002
-              ],
-              [
-                622,
-                2002
-              ],
-              [
-                624,
-                2000
-              ],
-              [
-                779,
-                2000
-              ],
-              [
-                781,
-                1998
-              ],
-              [
-                848,
-                1998
-              ],
-              [
-                850,
-                1997
-              ],
-              [
-                939,
-                1997
-              ],
-              [
-                941,
-                1995
-              ],
-              [
-                1070,
-                1995
-              ],
-              [
-                1072,
-                1994
-              ],
-              [
-                1235,
-                1994
-              ],
-              [
-                1237,
-                1992
-              ],
-              [
-                1539,
-                1992
-              ],
-              [
-                1541,
-                1990
-              ],
-              [
-                1618,
-                1990
-              ],
-              [
-                1619,
-                1989
-              ],
-              [
-                1672,
-                1989
-              ],
-              [
-                1674,
-                1987
-              ],
-              [
-                1678,
-                1987
-              ],
-              [
-                1680,
-                1986
-              ],
-              [
-                1683,
-                1986
-              ],
-              [
-                1685,
-                1984
-              ],
-              [
-                1686,
-                1984
-              ],
-              [
-                1688,
-                1982
-              ],
-              [
-                1690,
-                1982
-              ],
-              [
-                1691,
-                1981
-              ],
-              [
-                1693,
-                1981
-              ],
-              [
-                1698,
-                1976
-              ],
-              [
-                1699,
-                1976
-              ],
-              [
-                1712,
-                1963
-              ],
-              [
-                1712,
-                1962
-              ],
-              [
-                1715,
-                1958
-              ],
-              [
-                1715,
-                1957
-              ],
-              [
-                1717,
-                1955
-              ],
-              [
-                1717,
-                1954
-              ],
-              [
-                1718,
-                1952
-              ],
-              [
-                1718,
-                1949
-              ],
-              [
-                1720,
-                1947
-              ],
-              [
-                1720,
-                1942
-              ],
-              [
-                1722,
-                1941
-              ],
-              [
-                1722,
-                1930
-              ],
-              [
-                1723,
-                1928
-              ],
-              [
-                1723,
-                1669
-              ],
-              [
-                1722,
-                1667
-              ],
-              [
-                1722,
-                1406
-              ],
-              [
-                1720,
-                1405
-              ],
-              [
-                1720,
-                1230
-              ],
-              [
-                1718,
-                1229
-              ],
-              [
-                1718,
-                1090
-              ],
-              [
-                1717,
-                1088
-              ],
-              [
-                1717,
-                931
-              ],
-              [
-                1715,
-                930
-              ],
-              [
-                1715,
-                819
-              ],
-              [
-                1714,
-                818
-              ],
-              [
-                1714,
-                690
-              ],
-              [
-                1712,
-                688
-              ],
-              [
-                1712,
-                542
-              ],
-              [
-                1710,
-                541
-              ],
-              [
-                1710,
-                408
-              ],
-              [
-                1709,
-                406
-              ],
-              [
-                1709,
-                318
-              ],
-              [
-                1707,
-                317
-              ],
-              [
-                1707,
-                213
-              ],
-              [
-                1706,
-                211
-              ],
-              [
-                1706,
-                184
-              ],
-              [
-                1704,
-                182
-              ],
-              [
-                1704,
-                179
-              ],
-              [
-                1702,
-                178
-              ],
-              [
-                1702,
-                174
-              ],
-              [
-                1701,
-                173
-              ],
-              [
-                1701,
-                171
-              ],
-              [
-                1699,
-                170
-              ],
-              [
-                1699,
-                168
-              ],
-              [
-                1698,
-                166
-              ],
-              [
-                1698,
-                165
-              ],
-              [
-                1696,
-                163
-              ],
-              [
-                1696,
-                162
-              ],
-              [
-                1680,
-                146
-              ],
-              [
-                1678,
-                146
-              ],
-              [
-                1677,
-                144
-              ],
-              [
-                1675,
-                144
-              ],
-              [
-                1672,
-                141
-              ],
-              [
-                1670,
-                141
-              ],
-              [
-                1669,
-                139
-              ],
-              [
-                1666,
-                139
-              ],
-              [
-                1664,
-                138
-              ],
-              [
-                1661,
-                138
-              ],
-              [
-                1659,
-                136
-              ],
-              [
-                1651,
-                136
-              ],
-              [
-                1650,
-                134
-              ]
-            ]
-          }
-        ]
-      }
-    },
-    "defect_inference": {
-      "defect_count": 5,
-      "total_actual_area": 1.356,
-      "defects": [
-        {
-          "label": "wear",
-          "pixel_area": 127.5,
-          "actual_area": 0.07678197899999999,
-          "width": 0.76074,
-          "height": 0.17178,
-          "contour": [
-            [
-              275,
-              169
-            ],
-            [
-              277,
-              171
-            ],
-            [
-              282,
-              172
-            ],
-            [
-              279,
-              173
-            ],
-            [
-              280,
-              175
-            ],
-            [
-              288,
-              175
-            ],
-            [
-              295,
-              174
-            ],
-            [
-              295,
-              171
-            ],
-            [
-              299,
-              171
-            ],
-            [
-              303,
-              170
-            ],
-            [
-              306,
-              170
-            ],
-            [
-              305,
-              168
-            ],
-            [
-              298,
-              168
-            ],
-            [
-              288,
-              169
-            ],
-            [
-              281,
-              169
-            ],
-            [
-              277,
-              168
-            ]
-          ],
-          "min_rect": [
-            [
-              290.5,
-              171.5
-            ],
-            [
-              31.0,
-              7.0
-            ],
-            -0.0
-          ]
-        },
-        {
-          "label": "wear",
-          "pixel_area": 37.0,
-          "actual_area": 0.0222818292,
-          "width": 0.18624548626899717,
-          "height": 0.1552045777416229,
-          "contour": [
-            [
-              135,
-              210
-            ],
-            [
-              137,
-              213
-            ],
-            [
-              137,
-              216
-            ],
-            [
-              135,
-              218
-            ],
-            [
-              132,
-              218
-            ],
-            [
-              131,
-              215
-            ],
-            [
-              132,
-              211
-            ]
-          ],
-          "min_rect": [
-            [
-              134.09999084472656,
-              214.30001831054688
-            ],
-            [
-              7.589465618133545,
-              6.324554920196533
-            ],
-            71.56504821777344
-          ]
-        },
-        {
-          "label": "wear",
-          "pixel_area": 160.5,
-          "actual_area": 0.0966549618,
-          "width": 0.16266578845024107,
-          "height": 0.9137169589233398,
-          "contour": [
-            [
-              123,
-              227
-            ],
-            [
-              125,
-              232
-            ],
-            [
-              123,
-              235
-            ],
-            [
-              121,
-              235
-            ],
-            [
-              121,
-              239
-            ],
-            [
-              120,
-              241
-            ],
-            [
-              118,
-              244
-            ],
-            [
-              116,
-              247
-            ],
-            [
-              115,
-              247
-            ],
-            [
-              114,
-              251
-            ],
-            [
-              114,
-              256
-            ],
-            [
-              111,
-              258
-            ],
-            [
-              110,
-              262
-            ],
-            [
-              108,
-              260
-            ],
-            [
-              107,
-              257
-            ],
-            [
-              109,
-              251
-            ],
-            [
-              112,
-              245
-            ],
-            [
-              115,
-              240
-            ],
-            [
-              118,
-              234
-            ],
-            [
-              121,
-              229
-            ]
-          ],
-          "min_rect": [
-            [
-              115.77690124511719,
-              244.1685791015625
-            ],
-            [
-              6.628597736358643,
-              37.23377990722656
-            ],
-            24.623563766479492
-          ]
-        },
-        {
-          "label": "wear",
-          "pixel_area": 199.0,
-          "actual_area": 0.11984010839999999,
-          "width": 0.22834019067764283,
-          "height": 0.8093390180969238,
-          "contour": [
-            [
-              425,
-              167
-            ],
-            [
-              426,
-              169
-            ],
-            [
-              428,
-              169
-            ],
-            [
-              428,
-              173
-            ],
-            [
-              430,
-              175
-            ],
-            [
-              434,
-              176
-            ],
-            [
-              436,
-              173
-            ],
-            [
-              437,
-              171
-            ],
-            [
-              440,
-              172
-            ],
-            [
-              447,
-              172
-            ],
-            [
-              448,
-              174
-            ],
-            [
-              449,
-              175
-            ],
-            [
-              453,
-              174
-            ],
-            [
-              457,
-              172
-            ],
-            [
-              458,
-              169
-            ],
-            [
-              458,
-              167
-            ],
-            [
-              454,
-              166
-            ],
-            [
-              445,
-              167
-            ],
-            [
-              434,
-              167
-            ],
-            [
-              428,
-              167
-            ]
-          ],
-          "min_rect": [
-            [
-              441.6407165527344,
-              171.08135986328125
-            ],
-            [
-              9.304816246032715,
-              32.98040008544922
-            ],
-            88.02507019042969
-          ]
-        },
-        {
-          "label": "wear",
-          "pixel_area": 308.0,
-          "actual_area": 0.18548117279999998,
-          "width": 0.24939382078170777,
-          "height": 1.1079625957489014,
-          "contour": [
-            [
-              501,
-              173
-            ],
-            [
-              505,
-              171
-            ],
-            [
-              510,
-              169
-            ],
-            [
-              511,
-              167
-            ],
-            [
-              510,
-              166
-            ],
-            [
-              504,
-              165
-            ],
-            [
-              494,
-              166
-            ],
-            [
-              487,
-              166
-            ],
-            [
-              479,
-              166
-            ],
-            [
-              471,
-              166
-            ],
-            [
-              468,
-              166
-            ],
-            [
-              467,
-              168
-            ],
-            [
-              466,
-              170
-            ],
-            [
-              466,
-              173
-            ],
-            [
-              468,
-              173
-            ],
-            [
-              470,
-              173
-            ],
-            [
-              471,
-              174
-            ],
-            [
-              474,
-              176
-            ],
-            [
-              479,
-              175
-            ],
-            [
-              482,
-              174
-            ],
-            [
-              486,
-              173
-            ],
-            [
-              488,
-              173
-            ],
-            [
-              491,
-              172
-            ],
-            [
-              493,
-              171
-            ],
-            [
-              494,
-              170
-            ],
-            [
-              496,
-              171
-            ],
-            [
-              496,
-              173
-            ],
-            [
-              497,
-              173
-            ],
-            [
-              499,
-              173
-            ]
-          ],
-          "min_rect": [
-            [
-              488.51434326171875,
-              170.51348876953125
-            ],
-            [
-              10.162747383117676,
-              45.14925003051758
-            ],
-            88.40885925292969
-          ]
-        }
-      ]
-    }
-  }
-}