{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":75176,"databundleVersionId":8252256,"sourceType":"competition"},{"sourceId":9407465,"sourceType":"datasetVersion","datasetId":5647407,"isSourceIdPinned":false}],"dockerImageVersionId":30762,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Cài đặt các thư viện cần thiết\n!pip install -q ultralytics\n!pip install -q ensemble-boxes","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-09-16T03:26:18.454703Z","iopub.execute_input":"2024-09-16T03:26:18.455024Z","iopub.status.idle":"2024-09-16T03:26:47.634824Z","shell.execute_reply.started":"2024-09-16T03:26:18.454983Z","shell.execute_reply":"2024-09-16T03:26:47.633606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #gỡ bỏ không sử dụng wandb để tránh lỗi\n# !pip uninstall wandb -y","metadata":{"execution":{"iopub.status.busy":"2024-09-16T03:26:47.637067Z","iopub.execute_input":"2024-09-16T03:26:47.637396Z","iopub.status.idle":"2024-09-16T03:26:47.641710Z","shell.execute_reply.started":"2024-09-16T03:26:47.637358Z","shell.execute_reply":"2024-09-16T03:26:47.640797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -U albumentations ipywidgets","metadata":{"execution":{"iopub.status.busy":"2024-09-16T03:26:47.642889Z","iopub.execute_input":"2024-09-16T03:26:47.643221Z","iopub.status.idle":"2024-09-16T03:27:02.934894Z","shell.execute_reply.started":"2024-09-16T03:26:47.643188Z","shell.execute_reply":"2024-09-16T03:27:02.934016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -q wandb","metadata":{"execution":{"iopub.status.busy":"2024-09-16T03:27:02.936882Z","iopub.execute_input":"2024-09-16T03:27:02.937299Z","iopub.status.idle":"2024-09-16T03:27:15.634310Z","shell.execute_reply.started":"2024-09-16T03:27:02.937253Z","shell.execute_reply":"2024-09-16T03:27:15.633004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\nfrom pathlib import Path\n\n# Thiết lập API key cho wandb\nwandb.login(key='4f88ff0bbc6e3485258bca7079d7da4c47798ccd')\n\n# # Khởi tạo một run mới với tên dự án và tên lượt chạy cụ thể\n# # wandb.init(project='vincxr_yolov8s-3labels', name='n14th9')\n\n# Paths to data directories\nROOT = Path(\"/kaggle/input/vinbigdata-yolo-dataset-with-wbf-3labels/vinbigdata-yolo-dataset-with-wbf-3labels\")","metadata":{"execution":{"iopub.status.busy":"2024-09-16T03:27:15.637676Z","iopub.execute_input":"2024-09-16T03:27:15.638063Z","iopub.status.idle":"2024-09-16T03:27:18.617522Z","shell.execute_reply.started":"2024-09-16T03:27:15.638024Z","shell.execute_reply":"2024-09-16T03:27:18.616754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import các thư viện\nimport os\nimport cv2\nimport numpy as np\nfrom ultralytics import YOLO\nimport torch\nfrom ensemble_boxes import weighted_boxes_fusion\nfrom pathlib import Path\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\n\n# Đường dẫn tới thư mục chứa dữ liệu\nbase_dir = Path('/kaggle/input/vinbigdata-yolo-dataset-with-wbf-3labels/vinbigdata-yolo-dataset-with-wbf-3labels')\n\n# Định nghĩa hàm để huấn luyện mô hình\ndef train_model(model_name, data_yaml, epochs=50, imgsz=640, mixup=0.5, batch_size=32, device='0,1'):\n    \"\"\"\n    Huấn luyện mô hình YOLOv8 với các tham số cho trước.\n    \"\"\"\n    # Chọn trọng số mô hình phù hợp (yolov8m.pt hoặc yolov8x.pt)\n    model_weights = 'yolov8m.pt'  # Thay đổi nếu cần thiết\n    \n    # Khởi tạo mô hình YOLOv8\n    model = YOLO(model_weights)  # Khởi tạo mô hình YOLOv8m\n    \n    # Huấn luyện mô hình\n    model.train(\n        data=str(data_yaml),\n        epochs=epochs,\n        batch=batch_size,\n        imgsz=imgsz,\n        mixup=mixup,  # Thay đổi mixup từ 0 thành 0.5\n        project='vinbigdata_yolov8_models',\n        name=model_name,\n        augment=True,  # Bật data augmentation để tăng tính đa dạng của dữ liệu\n        iou=0.5,\n        device=device,  # Sử dụng cả 2 GPU\n        exist_ok=True,\n        verbose=True   # Log đầu ra\n    )\n    return model\n\n# Huấn luyện các mô hình\n\n# Mô hình 1: trained labels-1 on all images\nmodel1 = train_model(\n    model_name='model1_labels_1_all_images',\n    data_yaml=base_dir / 'labels_1' / 'data.yaml'\n)\n\n# Mô hình 2: trained labels-2 on all images\nmodel2 = train_model(\n    model_name='model2_labels_2_all_images',\n    data_yaml=base_dir / 'labels_2' / 'data.yaml'\n)\n\n# # Mô hình 3: trained labels-3 on all images\n# model3 = train_model(\n#     model_name='model3_labels_3_all_images',\n#     data_yaml=base_dir / 'labels_3' / 'data.yaml'\n# )\n\n# Mô hình 4: trained labels-1 only on images with disease\nmodel4 = train_model(\n    model_name='model4_labels_1_disease_only',\n    data_yaml=base_dir / 'labels_1_disease_only' / 'data.yaml'\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-16T03:27:18.618555Z","iopub.execute_input":"2024-09-16T03:27:18.618941Z","iopub.status.idle":"2024-09-16T03:47:40.832043Z","shell.execute_reply.started":"2024-09-16T03:27:18.618909Z","shell.execute_reply":"2024-09-16T03:47:40.831173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Chạy được nhưng không có check device trước\n\n# import numpy as np\n# import cv2\n# from tqdm import tqdm\n# from ensemble_boxes import weighted_boxes_fusion\n\n# def normalize_boxes(boxes, img_width, img_height):\n#     \"\"\"\n#     Chuẩn hóa các bounding box về khoảng [0, 1].\n#     \"\"\"\n#     boxes[:, 0] = np.clip(boxes[:, 0] / img_width, 0, 1)  # x_min\n#     boxes[:, 1] = np.clip(boxes[:, 1] / img_height, 0, 1)  # y_min\n#     boxes[:, 2] = np.clip(boxes[:, 2] / img_width, 0, 1)  # x_max\n#     boxes[:, 3] = np.clip(boxes[:, 3] / img_height, 0, 1)  # y_max\n#     return boxes\n\n# def filter_zero_area_boxes(boxes, scores, labels):\n#     \"\"\"\n#     Loại bỏ các hộp có diện tích bằng 0 và lọc đồng thời scores và labels.\n#     \"\"\"\n#     widths = boxes[:, 2] - boxes[:, 0]\n#     heights = boxes[:, 3] - boxes[:, 1]\n#     non_zero_area_mask = (widths > 0) & (heights > 0)\n#     boxes = boxes[non_zero_area_mask]\n#     scores = scores[non_zero_area_mask]\n#     labels = labels[non_zero_area_mask]\n#     return boxes, scores, labels\n\n# def tta_inference(model, image_paths, img_size=640, batch_size=16):\n#     \"\"\"\n#     Thực hiện suy luận với TTA trên danh sách hình ảnh.\n#     \"\"\"\n#     results = []\n#     scales = [1.0, 0.83, 0.67]\n#     flips = [False, True]  # Không lật và lật ngang\n\n#     for img_path in tqdm(image_paths, desc=\"Performing TTA Inference\"):\n#         img = cv2.imread(str(img_path))\n#         if img is None:\n#             print(f\"Warning: Unable to read image {img_path}. Skipping.\")\n#             continue\n#         img_original = img.copy()\n#         img_height, img_width = img.shape[:2]\n#         boxes_list = []\n#         scores_list = []\n#         labels_list = []\n\n#         tta_images = []\n#         tta_transforms = []\n\n#         for scale in scales:\n#             for flip in flips:\n#                 img_resized = cv2.resize(img, None, fx=scale, fy=scale)\n#                 if flip:\n#                     img_resized = cv2.flip(img_resized, 1)  # Lật ngang\n#                 tta_images.append(img_resized)\n#                 tta_transforms.append((scale, flip))\n\n#         # Suy luận với batch_size trên tất cả các TTA images\n#         preds_list = model.predict(\n#             tta_images,\n#             imgsz=img_size,\n#             batch=batch_size,\n#             verbose=False,\n#             device='cuda:0'  # Chỉ sử dụng GPU số 0\n#         )\n\n#         for preds, (scale, flip) in zip(preds_list, tta_transforms):\n#             boxes = preds.boxes.xyxy.cpu().numpy()\n#             scores = preds.boxes.conf.cpu().numpy()\n#             labels = preds.boxes.cls.cpu().numpy()\n\n#             if boxes.size == 0:\n#                 # Không có dự đoán nào, bỏ qua\n#                 continue\n\n#             # Chuẩn hóa tọa độ hộp về khoảng [0, 1]\n#             boxes = normalize_boxes(boxes, img_width, img_height)\n\n#             if flip:\n#                 boxes[:, [0, 2]] = 1 - boxes[:, [2, 0]]  # Điều chỉnh khi lật ngang\n#                 # Đảm bảo tọa độ hộp sau khi lật vẫn nằm trong phạm vi [0, 1]\n#                 boxes = np.clip(boxes, 0, 1)\n\n#             # Loại bỏ hộp có diện tích bằng 0 và lọc đồng thời scores và labels\n#             boxes, scores, labels = filter_zero_area_boxes(boxes, scores, labels)\n\n#             # Kiểm tra nếu sau khi lọc không còn hộp nào\n#             if boxes.size == 0:\n#                 continue\n\n#             boxes_list.append(boxes)\n#             scores_list.append(scores)\n#             labels_list.append(labels)\n\n#         # Kiểm tra nếu không có hộp nào để hợp nhất\n#         if len(boxes_list) == 0:\n#             # Bạn có thể quyết định cách xử lý trường hợp này\n#             # Ví dụ: bỏ qua hình ảnh này hoặc thêm kết quả trống\n#             results.append({\n#                 'image_id': img_path.stem,\n#                 'boxes': np.array([]),\n#                 'scores': np.array([]),\n#                 'labels': np.array([])\n#             })\n#             continue\n\n#         # Hợp nhất kết quả với WBF\n#         boxes_fused, scores_fused, labels_fused = weighted_boxes_fusion(\n#             boxes_list, scores_list, labels_list, weights=None, iou_thr=0.5, skip_box_thr=0.001\n#         )\n        \n#         # Sau khi hợp nhất WBF, đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n#         boxes_fused = np.clip(boxes_fused, 0, 1)\n\n#         # Lưu kết quả\n#         results.append({\n#             'image_id': img_path.stem,\n#             'boxes': boxes_fused,\n#             'scores': scores_fused,\n#             'labels': labels_fused\n#         })\n\n#     return results\n\n# # Danh sách đường dẫn hình ảnh cần suy luận\n# # test_image_dir = base_dir / 'labels_1' / 'test' / 'images'  # Sử dụng labels_1 làm tham chiếu\n# test_image_dir = Path('/kaggle/input/amia-public-challenge-2024/test/test')\n# test_image_paths = list(test_image_dir.glob('*.png'))\n\n# # Thực hiện suy luận với TTA cho từng mô hình\n# results_model1 = tta_inference(model1, test_image_paths)\n# results_model2 = tta_inference(model2, test_image_paths)\n# # results_model3 = tta_inference(model3, test_image_paths)\n# results_model4 = tta_inference(model4, test_image_paths)\n\n# # Hợp nhất kết quả từ các mô hình với WBF\n# def ensemble_predictions(results_list):\n#     \"\"\"\n#     Hợp nhất kết quả từ danh sách các kết quả suy luận của các mô hình.\n#     \"\"\"\n#     ensemble_results = []\n#     for idx in range(len(test_image_paths)):\n#         image_id = results_list[0][idx]['image_id']\n#         boxes_list = []\n#         scores_list = []\n#         labels_list = []\n\n#         for results in results_list:\n#             boxes = results[idx]['boxes']\n#             scores = results[idx]['scores']\n#             labels = results[idx]['labels']\n#             if boxes.size == 0:\n#                 continue\n#             boxes_list.append(boxes)\n#             scores_list.append(scores)\n#             labels_list.append(labels)\n\n#         # Hợp nhất kết quả với WBF\n#         if len(boxes_list) == 0:\n#             # Không có hộp nào từ bất kỳ mô hình nào\n#             ensemble_results.append({\n#                 'image_id': image_id,\n#                 'boxes': np.array([]),\n#                 'scores': np.array([]),\n#                 'labels': np.array([])\n#             })\n#             continue\n\n#         boxes_ens, scores_ens, labels_ens = weighted_boxes_fusion(\n#             boxes_list, scores_list, labels_list, weights=None, iou_thr=0.5, skip_box_thr=0.001\n#         )\n\n#         # Sau khi hợp nhất WBF, đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n#         boxes_ens = np.clip(boxes_ens, 0, 1)\n\n#         ensemble_results.append({\n#             'image_id': image_id,\n#             'boxes': boxes_ens,\n#             'scores': scores_ens,\n#             'labels': labels_ens\n#         })\n\n#     return ensemble_results\n\n# # Lựa chọn các mô hình để ensemble\n# # Ví dụ: model-1 + model-2 + model-4\n# ensemble_results = ensemble_predictions([results_model1, results_model2, results_model4])\n\n# # Xử lý lớp 14 (\"No findings\")\n# def handle_no_findings(ensemble_results, results_model1, results_model2):\n#     \"\"\"\n#     Thêm lớp 14 (\"No findings\") vào kết quả suy luận.\n#     \"\"\"\n#     final_results = []\n#     for idx, result in enumerate(ensemble_results):\n#         image_id = result['image_id']\n#         boxes = result['boxes']\n#         scores = result['scores']\n#         labels = result['labels']\n\n#         # Lấy điểm tin cậy cao nhất từ model1 và model2\n#         scores_model1 = results_model1[idx]['scores']\n#         scores_model2 = results_model2[idx]['scores']\n#         max_score_model1 = np.max(scores_model1) if len(scores_model1) > 0 else 0\n#         max_score_model2 = np.max(scores_model2) if len(scores_model2) > 0 else 0\n#         finding_score = max(max_score_model1, max_score_model2)\n\n#         # Tính điểm tin cậy cho lớp 14\n#         no_finding_score = 1 - finding_score\n\n#         # Thêm hộp dự đoán cho lớp 14 nếu không có bất kỳ đối tượng nào được phát hiện\n#         if finding_score < 0.5:  # Ngưỡng tin cậy có thể điều chỉnh\n#             boxes = np.vstack([boxes, [0, 0, 1, 1]])  # Hộp bao phủ toàn bộ hình ảnh\n#             scores = np.hstack([scores, no_finding_score])\n#             labels = np.hstack([labels, 14])  # Giả sử lớp 14 là \"No findings\"\n\n#         final_results.append({\n#             'image_id': image_id,\n#             'boxes': boxes,\n#             'scores': scores,\n#             'labels': labels\n#         })\n\n#     return final_results\n\n# # Thêm lớp 14 vào kết quả\n# final_results = handle_no_findings(ensemble_results, results_model1, results_model2)\n\n# # Lưu kết quả cuối cùng vào tệp submission.csv hoặc định dạng phù hợp\n# def save_results_to_csv(final_results, output_file='submission.csv'):\n#     \"\"\"\n#     Lưu kết quả cuối cùng vào tệp CSV.\n#     \"\"\"\n#     with open(output_file, 'w') as f:\n#         f.write('image_id,PredictionString\\n')\n#         for result in final_results:\n#             image_id = result['image_id']\n#             prediction_strings = []\n#             for box, score, label in zip(result['boxes'], result['scores'], result['labels']):\n#                 x_min, y_min, x_max, y_max = box\n#                 prediction_strings.append(f\"{int(label)} {score:.4f} {x_min:.4f} {y_min:.4f} {x_max:.4f} {y_max:.4f}\")\n#             prediction_str = ' '.join(prediction_strings)\n#             f.write(f\"{image_id},{prediction_str}\\n\")\n\n# # Lưu kết quả\n# save_results_to_csv(final_results)\n\n# print(\"Inference and ensemble complete. Results saved to submission.csv.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport cv2\nfrom tqdm import tqdm\nfrom ensemble_boxes import weighted_boxes_fusion\nimport torch\nfrom pathlib import Path\n\n# Hàm kiểm tra thiết bị: Sử dụng GPU nếu có, nếu không sẽ sử dụng CPU\ndef get_device():\n    return 'cuda:0' if torch.cuda.is_available() else 'cpu'\n\n# Hàm chuẩn hóa bounding box\ndef normalize_boxes(boxes, img_width, img_height):\n    boxes[:, 0] = np.clip(boxes[:, 0] / img_width, 0, 1)  # x_min\n    boxes[:, 1] = np.clip(boxes[:, 1] / img_height, 0, 1)  # y_min\n    boxes[:, 2] = np.clip(boxes[:, 2] / img_width, 0, 1)  # x_max\n    boxes[:, 3] = np.clip(boxes[:, 3] / img_height, 0, 1)  # y_max\n    return boxes\n\n# Hàm lọc các hộp có diện tích bằng 0\ndef filter_zero_area_boxes(boxes, scores, labels):\n    widths = boxes[:, 2] - boxes[:, 0]\n    heights = boxes[:, 3] - boxes[:, 1]\n    non_zero_area_mask = (widths > 0) & (heights > 0)\n    boxes = boxes[non_zero_area_mask]\n    scores = scores[non_zero_area_mask]\n    labels = labels[non_zero_area_mask]\n    return boxes, scores, labels\n\n# Hàm inference với TTA (không chia batch, thực hiện từng ảnh một)\ndef tta_inference(model, image_paths, img_size=640, device='cpu'):\n    results = []\n    scales = [1.0, 0.83, 0.67]\n    flips = [False, True]  # Không lật và lật ngang\n\n    for img_path in tqdm(image_paths, desc=\"Performing TTA Inference\"):\n        img = cv2.imread(str(img_path))\n        if img is None:\n            print(f\"Warning: Unable to read image {img_path}. Skipping.\")\n            continue\n        img_height, img_width = img.shape[:2]\n        boxes_list = []\n        scores_list = []\n        labels_list = []\n\n        tta_images = []\n        tta_transforms = []\n\n        # Tạo các phiên bản TTA cho mỗi ảnh\n        for scale in scales:\n            for flip in flips:\n                img_resized = cv2.resize(img, None, fx=scale, fy=scale)\n                if flip:\n                    img_resized = cv2.flip(img_resized, 1)  # Lật ngang\n                tta_images.append(img_resized)\n                tta_transforms.append((scale, flip))\n\n        # Suy luận với từng ảnh một\n        preds_list = model.predict(\n            tta_images,\n            imgsz=img_size,\n            batch=1,  # Không sử dụng batch inference\n            verbose=False,\n            device=device\n        )\n\n        for preds, (scale, flip) in zip(preds_list, tta_transforms):\n            boxes = preds.boxes.xyxy.cpu().numpy()\n            scores = preds.boxes.conf.cpu().numpy()\n            labels = preds.boxes.cls.cpu().numpy()\n\n            if boxes.size == 0:\n                continue\n\n            # Chuẩn hóa hộp giới hạn\n            boxes = normalize_boxes(boxes, img_width, img_height)\n\n            if flip:\n                boxes[:, [0, 2]] = 1 - boxes[:, [2, 0]]  # Điều chỉnh khi lật ngang\n                boxes = np.clip(boxes, 0, 1)\n\n            boxes, scores, labels = filter_zero_area_boxes(boxes, scores, labels)\n\n            if boxes.size == 0:\n                continue\n\n            boxes_list.append(boxes)\n            scores_list.append(scores)\n            labels_list.append(labels)\n\n        if len(boxes_list) == 0:\n            results.append({\n                'image_id': img_path.stem,  # Thêm 'image_id' tại đây\n                'boxes': np.array([]),\n                'scores': np.array([]),\n                'labels': np.array([])\n            })\n            continue\n\n        # Hợp nhất kết quả với WBF\n        boxes_fused, scores_fused, labels_fused = weighted_boxes_fusion(\n            boxes_list, scores_list, labels_list, weights=None, iou_thr=0.5, skip_box_thr=0.001\n        )\n\n        # Sau khi hợp nhất WBF, đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n        boxes_fused = np.clip(boxes_fused, 0, 1)\n\n        results.append({\n            'image_id': img_path.stem,  # Thêm 'image_id' tại đây\n            'boxes': boxes_fused,\n            'scores': scores_fused,\n            'labels': labels_fused\n        })\n\n        # Giải phóng bộ nhớ GPU sau mỗi ảnh\n        torch.cuda.empty_cache()\n\n    return results\n\n# Hợp nhất kết quả từ nhiều mô hình\ndef ensemble_predictions(results_list):\n    ensemble_results = []\n    for idx in range(len(results_list[0])):\n        boxes_list = []\n        scores_list = []\n        labels_list = []\n\n        for results in results_list:\n            boxes = results[idx]['boxes']\n            scores = results[idx]['scores']\n            labels = results[idx]['labels']\n            if boxes.size == 0:\n                continue\n            boxes_list.append(boxes)\n            scores_list.append(scores)\n            labels_list.append(labels)\n\n        if len(boxes_list) == 0:\n            ensemble_results.append({\n                'boxes': np.array([]),\n                'scores': np.array([]),\n                'labels': np.array([])\n            })\n            continue\n\n        # Hợp nhất kết quả với WBF\n        boxes_ens, scores_ens, labels_ens = weighted_boxes_fusion(\n            boxes_list, scores_list, labels_list, weights=None, iou_thr=0.5, skip_box_thr=0.001\n        )\n\n        # Đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n        boxes_ens = np.clip(boxes_ens, 0, 1)\n\n        ensemble_results.append({\n            'boxes': boxes_ens,\n            'scores': scores_ens,\n            'labels': labels_ens\n        })\n\n    return ensemble_results\n\n# Hàm thêm lớp 14 \"No findings\"\ndef handle_no_findings(ensemble_results, results_model1, results_model2):\n    final_results = []\n    for idx, result in enumerate(ensemble_results):\n        boxes = result['boxes']\n        scores = result['scores']\n        labels = result['labels']\n\n        # Lấy điểm tin cậy cao nhất từ model1 và model2\n        scores_model1 = results_model1[idx]['scores']\n        scores_model2 = results_model2[idx]['scores']\n        max_score_model1 = np.max(scores_model1) if len(scores_model1) > 0 else 0\n        max_score_model2 = np.max(scores_model2) if len(scores_model2) > 0 else 0\n        finding_score = max(max_score_model1, max_score_model2)\n\n        # Tính điểm tin cậy cho lớp 14\n        no_finding_score = 1 - finding_score\n\n        # Thêm hộp dự đoán cho lớp 14 nếu không có bất kỳ đối tượng nào được phát hiện\n        if finding_score < 0.5:  # Ngưỡng tin cậy có thể điều chỉnh\n            boxes = np.vstack([boxes, [0, 0, 1, 1]])  # Hộp bao phủ toàn bộ hình ảnh\n            scores = np.hstack([scores, no_finding_score])\n            labels = np.hstack([labels, 14])  # Giả sử lớp 14 là \"No findings\"\n\n        final_results.append({\n            'image_id': results_model1[idx]['image_id'],  # Thêm 'image_id' tại đây\n            'boxes': boxes,\n            'scores': scores,\n            'labels': labels\n        })\n\n    return final_results\n\n# Lưu kết quả cuối cùng vào tệp submission.csv hoặc định dạng phù hợp\ndef save_results_to_csv(final_results, output_file='submission.csv'):\n    \"\"\"\n    Lưu kết quả cuối cùng vào tệp CSV.\n    \"\"\"\n    with open(output_file, 'w') as f:\n        f.write('image_id,PredictionString\\n')\n        for result in final_results:\n            image_id = result['image_id']  # Đảm bảo 'image_id' có mặt trong từng result\n            prediction_strings = []\n            for box, score, label in zip(result['boxes'], result['scores'], result['labels']):\n                x_min, y_min, x_max, y_max = box\n                prediction_strings.append(f\"{int(label)} {score:.4f} {x_min:.4f} {y_min:.4f} {x_max:.4f} {y_max:.4f}\")\n            prediction_str = ' '.join(prediction_strings)\n            f.write(f\"{image_id},{prediction_str}\\n\")\n\n# Sử dụng thiết bị dựa trên GPU hoặc CPU\ndevice = get_device()\n\n# Danh sách đường dẫn hình ảnh cần suy luận\ntest_image_dir = Path('/kaggle/input/amia-public-challenge-2024/test/test')\n# test_image_dir = base_dir / 'labels_1_disease_only' / 'test' / 'images'  # Sử dụng labels_1 làm tham chiếu\n# test_image_paths = list(test_image_dir.glob('*.png'))\nallowed_extensions = {'.jpg', '.png'}  # Tập hợp các phần mở rộng được phép\ntest_image_paths = [p for p in test_image_dir.glob('*') if p.suffix.lower() in allowed_extensions]\n\n# Thực hiện suy luận với TTA cho từng mô hình\nresults_model1 = tta_inference(model1, test_image_paths, device=device)\nresults_model2 = tta_inference(model2, test_image_paths, device=device)\nresults_model4 = tta_inference(model4, test_image_paths, device=device)\n\n# Hợp nhất kết quả từ nhiều mô hình\nensemble_results = ensemble_predictions([results_model1, results_model2, results_model4])\n\n# Xử lý lớp 14 \"No findings\"\nfinal_results = handle_no_findings(ensemble_results, results_model1, results_model2)\n\n# Lưu kết quả\nsave_results_to_csv(final_results)\n\nprint(\"Inference and ensemble complete. Results saved to submission.csv.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #Chạy nhiều batch nhưng đang lỗi xử lý không hết ảnh\n# import numpy as np\n# import cv2\n# from tqdm import tqdm\n# from ensemble_boxes import weighted_boxes_fusion\n# import torch\n# from pathlib import Path\n\n# # Hàm kiểm tra thiết bị: Sử dụng GPU nếu có, nếu không sẽ sử dụng CPU\n# def get_device():\n#     return 'cuda:0' if torch.cuda.is_available() else 'cpu'\n\n# # Hàm chuẩn hóa bounding box\n# def normalize_boxes(boxes, img_width, img_height):\n#     boxes[:, 0] = np.clip(boxes[:, 0] / img_width, 0, 1)  # x_min\n#     boxes[:, 1] = np.clip(boxes[:, 1] / img_height, 0, 1)  # y_min\n#     boxes[:, 2] = np.clip(boxes[:, 2] / img_width, 0, 1)  # x_max\n#     boxes[:, 3] = np.clip(boxes[:, 3] / img_height, 0, 1)  # y_max\n#     return boxes\n\n# # Hàm lọc các hộp có diện tích bằng 0\n# def filter_zero_area_boxes(boxes, scores, labels):\n#     widths = boxes[:, 2] - boxes[:, 0]\n#     heights = boxes[:, 3] - boxes[:, 1]\n#     non_zero_area_mask = (widths > 0) & (heights > 0)\n#     boxes = boxes[non_zero_area_mask]\n#     scores = scores[non_zero_area_mask]\n#     labels = labels[non_zero_area_mask]\n#     return boxes, scores, labels\n\n# # Hàm inference với TTA và batch inference\n# def tta_inference(model, image_paths, img_size=640, batch_size=16, device='cpu'):\n#     results = []\n#     scales = [1.0, 0.83, 0.67]\n#     flips = [False, True]  # Không lật và lật ngang\n\n#     skipped_images = []  # Thêm biến để lưu các ảnh bị bỏ qua\n\n#     for batch_start in tqdm(range(0, len(image_paths), batch_size), desc=\"Performing TTA Inference\"):\n#         batch_paths = image_paths[batch_start:batch_start + batch_size]\n#         batch_images = []\n#         batch_transforms = []\n        \n#         for img_path in batch_paths:\n#             img = cv2.imread(str(img_path))\n#             if img is None:\n#                 print(f\"Warning: Unable to read image {img_path}. Skipping.\")\n#                 skipped_images.append(img_path)  # Ghi lại tên ảnh bị bỏ qua\n#                 continue\n\n#             img_height, img_width = img.shape[:2]\n\n#             # Tạo các phiên bản TTA cho mỗi ảnh\n#             tta_images = []\n#             tta_transforms = []\n#             for scale in scales:\n#                 for flip in flips:\n#                     img_resized = cv2.resize(img, None, fx=scale, fy=scale)\n#                     if flip:\n#                         img_resized = cv2.flip(img_resized, 1)  # Lật ngang\n#                     tta_images.append(img_resized)\n#                     tta_transforms.append((img_width, img_height, scale, flip))\n\n#             batch_images.extend(tta_images)\n#             batch_transforms.extend(tta_transforms)\n\n#         if not batch_images:\n#             continue\n\n#         # Chuyển đổi hình ảnh sang batch để suy luận\n#         preds_list = model.predict(\n#             batch_images,\n#             imgsz=img_size,\n#             batch=batch_size,\n#             verbose=False,\n#             device=device\n#         )\n\n#         # Xử lý kết quả từ mô hình\n#         for preds, (img_width, img_height, scale, flip), img_path in zip(preds_list, batch_transforms, batch_paths):\n#             boxes = preds.boxes.xyxy.cpu().numpy()\n#             scores = preds.boxes.conf.cpu().numpy()\n#             labels = preds.boxes.cls.cpu().numpy()\n\n#             if boxes.size == 0:\n#                 continue\n\n#             boxes = normalize_boxes(boxes, img_width, img_height)\n\n#             if flip:\n#                 boxes[:, [0, 2]] = 1 - boxes[:, [2, 0]]  # Điều chỉnh khi lật ngang\n#                 boxes = np.clip(boxes, 0, 1)\n\n#             boxes, scores, labels = filter_zero_area_boxes(boxes, scores, labels)\n\n#             if boxes.size == 0:\n#                 continue\n\n#             results.append({\n#                 'image_id': img_path.stem,  # Save image ID as the filename\n#                 'boxes': boxes,\n#                 'scores': scores,\n#                 'labels': labels\n#             })\n\n#         # Giải phóng bộ nhớ GPU\n#         torch.cuda.empty_cache()\n\n#     # Kiểm tra xem có bao nhiêu ảnh đã bị bỏ qua\n#     if skipped_images:\n#         print(f\"Skipped {len(skipped_images)} images due to read errors:\")\n#         for img in skipped_images:\n#             print(f\"  {img}\")\n\n#     # Đếm số lượng ảnh đã thực sự xử lý\n#     processed_images_count = len(results) // (len(scales) * len(flips))  # Đếm số lượng ảnh đã xử lý\n#     print(f\"Number of images actually processed: {processed_images_count}\")\n    \n#     return results\n\n# # Hợp nhất kết quả từ nhiều mô hình với kiểm tra độ dài\n# def ensemble_predictions(results_list):\n#     ensemble_results = []\n#     num_images = min([len(results) for results in results_list])  # Lấy số lượng ảnh nhỏ nhất\n#     print(f\"Number of images processed: {num_images}\")\n\n#     for idx in range(num_images):\n#         boxes_list = []\n#         scores_list = []\n#         labels_list = []\n#         image_id = results_list[0][idx]['image_id']  # Lấy image_id từ kết quả của mô hình đầu tiên\n\n#         for results in results_list:\n#             if idx < len(results):\n#                 boxes = results[idx]['boxes']\n#                 scores = results[idx]['scores']\n#                 labels = results[idx]['labels']\n#                 if boxes.size == 0:\n#                     continue\n#                 boxes_list.append(boxes)\n#                 scores_list.append(scores)\n#                 labels_list.append(labels)\n\n#         if len(boxes_list) == 0:\n#             ensemble_results.append({\n#                 'image_id': image_id,\n#                 'boxes': np.array([]),\n#                 'scores': np.array([]),\n#                 'labels': np.array([])\n#             })\n#             continue\n\n#         # Hợp nhất kết quả với WBF (tăng ngưỡng IoU để giảm số hộp chồng lặp)\n#         boxes_ens, scores_ens, labels_ens = weighted_boxes_fusion(\n#             boxes_list, scores_list, labels_list, weights=None, iou_thr=0.5, skip_box_thr=0.01\n#         )\n\n#         # Đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n#         boxes_ens = np.clip(boxes_ens, 0, 1)\n\n#         ensemble_results.append({\n#             'image_id': image_id,\n#             'boxes': boxes_ens,\n#             'scores': scores_ens,\n#             'labels': labels_ens\n#         })\n\n#     return ensemble_results\n\n# # Hàm thêm lớp 14 \"No findings\"\n# def handle_no_findings(ensemble_results, results_model1, results_model2):\n#     final_results = []\n#     for idx, result in enumerate(ensemble_results):\n#         boxes = result['boxes']\n#         scores = result['scores']\n#         labels = result['labels']\n#         image_id = result['image_id']  # Lấy image_id từ ensemble_results\n\n#         # Lấy điểm tin cậy cao nhất từ model1 và model2\n#         scores_model1 = results_model1[idx]['scores']\n#         scores_model2 = results_model2[idx]['scores']\n#         max_score_model1 = np.max(scores_model1) if len(scores_model1) > 0 else 0\n#         max_score_model2 = np.max(scores_model2) if len(scores_model2) > 0 else 0\n#         finding_score = max(max_score_model1, max_score_model2)\n\n#         # Điều chỉnh logic: Chỉ thêm lớp 14 nếu không có lớp nào khác có score > ngưỡng nhất định và không có hộp nào\n#         threshold = 0.5\n#         if finding_score < threshold and len(boxes) == 0:\n#             no_finding_score = 1 - finding_score\n#             boxes = np.vstack([boxes, [0, 0, 1, 1]])  # Hộp bao phủ toàn bộ hình ảnh\n#             scores = np.hstack([scores, no_finding_score])\n#             labels = np.hstack([labels, 14])  # Giả sử lớp 14 là \"No findings\"\n\n#         final_results.append({\n#             'image_id': image_id,\n#             'boxes': boxes,\n#             'scores': scores,\n#             'labels': labels\n#         })\n\n#     return final_results\n\n# # Lưu kết quả cuối cùng vào tệp submission.csv hoặc định dạng phù hợp\n# def save_results_to_csv(final_results, output_file='submission.csv'):\n#     \"\"\"\n#     Lưu kết quả cuối cùng vào tệp CSV.\n#     \"\"\"\n#     with open(output_file, 'w') as f:\n#         f.write('image_id,PredictionString\\n')\n#         for result in final_results:\n#             image_id = result['image_id']\n#             prediction_strings = []\n#             for box, score, label in zip(result['boxes'], result['scores'], result['labels']):\n#                 x_min, y_min, x_max, y_max = box\n#                 prediction_strings.append(f\"{int(label)} {score:.4f} {x_min:.4f} {y_min:.4f} {x_max:.4f} {y_max:.4f}\")\n#             prediction_str = ' '.join(prediction_strings)\n#             f.write(f\"{image_id},{prediction_str}\\n\")\n\n# # Sử dụng thiết bị dựa trên GPU hoặc CPU\n# device = get_device()\n\n# # Kiểm tra số lượng ảnh trong thư mục\n# print(f\"Total images found in directory: {len(test_image_paths)}\")\n\n# # Danh sách đường dẫn hình ảnh cần suy luận\n# # test_image_dir = Path('/kaggle/input/amia-public-challenge-2024/test/test')\n# test_image_dir = base_dir / 'labels_1_disease_only' / 'test' / 'images'  # Sử dụng labels_1 làm tham chiếu\n# allowed_extensions = {'.jpg', '.png'}  # Tập hợp các phần mở rộng được phép\n# test_image_paths = [p for p in test_image_dir.glob('*') if p.suffix.lower() in allowed_extensions]\n\n# # Thực hiện suy luận với TTA cho từng mô hình\n# results_model1 = tta_inference(model1, test_image_paths, device=device)\n# results_model2 = tta_inference(model2, test_image_paths, device=device)\n# results_model4 = tta_inference(model4, test_image_paths, device=device)\n\n# # Hợp nhất kết quả từ nhiều mô hình\n# ensemble_results = ensemble_predictions([results_model1, results_model2, results_model4])\n\n# # Xử lý lớp 14 \"No findings\"\n# final_results = handle_no_findings(ensemble_results, results_model1, results_model2)\n\n# # Lưu kết quả\n# save_results_to_csv(final_results)\n\n# print(\"Inference and ensemble complete. Results saved to submission.csv.\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport numpy as np\nfrom ultralytics import YOLO\nfrom ensemble_boxes import weighted_boxes_fusion\nimport matplotlib.pyplot as plt\nfrom pathlib import Path\n\n# Đường dẫn tới các mô hình đã huấn luyện\nmodel1_path = 'vinbigdata_yolov8_models/model1_labels_1_all_images/weights/best.pt'\nmodel2_path = 'vinbigdata_yolov8_models/model2_labels_2_all_images/weights/best.pt'\nmodel4_path = 'vinbigdata_yolov8_models/model4_labels_1_disease_only/weights/best.pt'\n\n# Tải các mô hình\nmodel1 = YOLO(model1_path)\nmodel2 = YOLO(model2_path)\nmodel4 = YOLO(model4_path)\n\n# Danh sách các mô hình\nmodels = [model1, model2, model4]\n\n# Định nghĩa tên các lớp và màu sắc cho trực quan hóa\nviz_labels = {\n    0: \"Aortic_enlargement\",\n    1: \"Atelectasis\",\n    2: \"Calcification\",\n    3: \"Cardiomegaly\",\n    4: \"Consolidation\",\n    5: \"ILD\",\n    6: \"Infiltration\",\n    7: \"Lung_Opacity\",\n    8: \"Nodule/Mass\",\n    9: \"Other_lesion\",\n    10: \"Pleural_effusion\",\n    11: \"Pleural_thickening\",\n    12: \"Pneumothorax\",\n    13: \"Pulmonary_fibrosis\",\n    14: \"No findings\"\n}\n\nlabel2color = {\n    0: (255, 0, 0),        # Red\n    1: (0, 255, 0),        # Green\n    2: (0, 0, 255),        # Blue\n    3: (255, 255, 0),      # Cyan\n    4: (255, 0, 255),      # Magenta\n    5: (0, 255, 255),      # Yellow\n    6: (128, 0, 0),        # Maroon\n    7: (0, 128, 0),        # Dark Green\n    8: (0, 0, 128),        # Navy\n    9: (128, 128, 0),      # Olive\n    10: (128, 0, 128),     # Purple\n    11: (0, 128, 128),     # Teal\n    12: (128, 128, 128),   # Gray\n    13: (0, 0, 0),         # Black\n    14: (255, 255, 255)    # White for \"No findings\"\n}\n\n# Hàm loại bỏ hộp có diện tích bằng 0\ndef filter_zero_area_boxes(boxes, scores, labels):\n    areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])\n    mask = areas > 0\n    return boxes[mask], scores[mask], labels[mask]\n\n# Hàm thực hiện TTA suy luận trên một hình ảnh\ndef tta_inference_single_image(models, image_path, img_size=640):\n    img = cv2.imread(str(image_path))\n    if img is None:\n        print(f\"Warning: Unable to read image {image_path}. Skipping.\")\n        return None\n    img_height, img_width = img.shape[:2]\n    boxes_list_all_models = []\n    scores_list_all_models = []\n    labels_list_all_models = []\n\n    scales = [1.0, 0.83, 0.67]\n    flips = [False, True]  # Không lật và lật ngang\n\n    for model in models:\n        boxes_list = []\n        scores_list = []\n        labels_list = []\n\n        for scale in scales:\n            for flip in flips:\n                # Chuẩn bị hình ảnh\n                img_resized = cv2.resize(img, None, fx=scale, fy=scale)\n                if flip:\n                    img_resized = cv2.flip(img_resized, 1)  # Lật ngang\n\n                # Suy luận\n                preds = model.predict(img_resized, imgsz=img_size, verbose=False)[0]\n                boxes = preds.boxes.xyxy.cpu().numpy()\n                scores = preds.boxes.conf.cpu().numpy()\n                labels = preds.boxes.cls.cpu().numpy()\n\n                # Chuyển đổi tọa độ hộp về kích thước ban đầu\n                scale_factor = [img_width / img_resized.shape[1], img_height / img_resized.shape[0]] * 2\n                boxes = boxes * scale_factor\n\n                if flip:\n                    boxes[:, [0, 2]] = img_width - boxes[:, [2, 0]]  # Điều chỉnh khi lật ngang\n\n                # Chuẩn hóa tọa độ hộp về [0, 1]\n                boxes[:, [0, 2]] /= img_width\n                boxes[:, [1, 3]] /= img_height\n\n                # Loại bỏ hộp có diện tích bằng 0 và lọc đồng thời scores và labels\n                boxes, scores, labels = filter_zero_area_boxes(boxes, scores, labels)\n\n                # Kiểm tra nếu sau khi lọc không còn hộp nào\n                if boxes.size == 0:\n                    continue\n\n                boxes_list.append(boxes)\n                scores_list.append(scores)\n                labels_list.append(labels)\n\n        # Kiểm tra nếu không có hộp nào từ bất kỳ mô hình nào\n        if len(boxes_list) == 0:\n            # Bạn có thể quyết định cách xử lý trường hợp này\n            boxes_list_all_models.append(np.array([]))\n            scores_list_all_models.append(np.array([]))\n            labels_list_all_models.append(np.array([]))\n            continue\n\n        boxes_list_all_models.append(np.vstack(boxes_list))\n        scores_list_all_models.append(np.hstack(scores_list))\n        labels_list_all_models.append(np.hstack(labels_list))\n\n    # Hợp nhất kết quả với WBF\n    boxes_fused, scores_fused, labels_fused = weighted_boxes_fusion(\n        boxes_list_all_models, scores_list_all_models, labels_list_all_models, weights=None, iou_thr=0.5, skip_box_thr=0.001\n    )\n\n    # Sau khi hợp nhất WBF, đảm bảo các giá trị tọa độ vẫn nằm trong phạm vi [0, 1]\n    boxes_fused = np.clip(boxes_fused, 0, 1)\n\n    # Chuyển đổi tọa độ hộp về dạng [xmin, ymin, xmax, ymax] theo kích thước gốc\n    boxes_fused[:, [0, 2]] *= img_width\n    boxes_fused[:, [1, 3]] *= img_height\n\n    result = {\n        'image_id': Path(image_path).stem,\n        'boxes': boxes_fused,\n        'scores': scores_fused,\n        'labels': labels_fused\n    }\n\n    return result\n\ndef handle_no_findings_single_image(result, models_results_model1_model2, img_width, img_height):\n    \"\"\"\n    Thêm lớp 14 (\"No findings\") vào kết quả suy luận của một hình ảnh.\n    \"\"\"\n    if result is None:\n        return None\n\n    image_id = result['image_id']\n    boxes = result['boxes']\n    scores = result['scores']\n    labels = result['labels']\n\n    # Lấy điểm tin cậy cao nhất từ model1 và model2\n    scores_model1 = models_results_model1_model2[0]['scores']\n    scores_model2 = models_results_model1_model2[1]['scores']\n    max_score_model1 = np.max(scores_model1) if len(scores_model1) > 0 else 0\n    max_score_model2 = np.max(scores_model2) if len(scores_model2) > 0 else 0\n    finding_score = max(max_score_model1, max_score_model2)\n\n    # Tính điểm tin cậy cho lớp 14\n    no_finding_score = 1 - finding_score\n\n    # Thêm hộp dự đoán cho lớp 14 nếu không có bất kỳ đối tượng nào được phát hiện\n    if finding_score < 0.5:  # Ngưỡng tin cậy có thể điều chỉnh\n        boxes = np.vstack([boxes, [0, 0, img_width, img_height]])  # Hộp bao phủ toàn bộ hình ảnh\n        scores = np.hstack([scores, no_finding_score])\n        labels = np.hstack([labels, 14])  # Giả sử lớp 14 là \"No findings\"\n\n    result_final = {\n        'image_id': image_id,\n        'boxes': boxes,\n        'scores': scores,\n        'labels': labels\n    }\n\n    return result_final\n\n# Hiển thị kết quả trên hình ảnh\ndef display_result_on_image(image_path, result, viz_labels, label2color):\n    \"\"\"\n    Hiển thị kết quả suy luận trên hình ảnh.\n    \"\"\"\n    img = cv2.imread(str(image_path))\n    img_height, img_width = img.shape[:2]\n    \n    for box, score, label in zip(result['boxes'], result['scores'], result['labels']):\n        if label == 14:  # Skip \"No findings\"\n            continue\n        \n        # Ensure boxes are within image boundaries\n        x_min, y_min, x_max, y_max = map(int, box)\n        x_min = max(0, x_min)\n        y_min = max(0, y_min)\n        x_max = min(img_width, x_max)\n        y_max = min(img_height, y_max)\n        \n        # Get color for this label\n        color = label2color.get(int(label), (0, 255, 0))  # Default to green if label not in dict\n        \n        # Draw bounding box\n        cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color, 2)\n        \n        # Get the class name\n        class_name = viz_labels.get(int(label), 'Unknown')\n        \n        # Put label text\n        cv2.putText(img, f\"{class_name}: {score:.2f}\", (x_min, y_min - 10),\n                    cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)\n\n    # Hiển thị hình ảnh\n    plt.figure(figsize=(12, 8))\n    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n    plt.axis('off')\n    plt.show()\n\n# Đường dẫn tới hình ảnh mới\nnew_image_path = '/kaggle/input/vinbigdata-yolo-dataset-with-wbf-3labels/vinbigdata-yolo-dataset-with-wbf-3labels/labels_1_disease_only/test/images/071ff9c782ead87dfa9b1c025c25e769.jpg'  # Thay thế bằng đường dẫn thực tế\n\n# Thực hiện suy luận trên hình ảnh mới\nresult = tta_inference_single_image(models, new_image_path)\n\n# Lấy kích thước ảnh\nimg = cv2.imread(new_image_path)\nif img is not None:\n    img_height, img_width = img.shape[:2]\nelse:\n    print(f\"Warning: Unable to read image {new_image_path}.\")\n    img_height, img_width = 0, 0\n\n# Thực hiện suy luận riêng lẻ với model1 và model2 để tính finding_score\nresult_model1 = tta_inference_single_image([model1], new_image_path)\nresult_model2 = tta_inference_single_image([model2], new_image_path)\n\n# Xử lý lớp 14 (\"No findings\")\nresult_final = handle_no_findings_single_image(result, [result_model1, result_model2], img_width, img_height)\n\n# Hiển thị kết quả\ndisplay_result_on_image(new_image_path, result_final, viz_labels, label2color)","metadata":{"execution":{"iopub.status.busy":"2024-09-16T05:57:09.165863Z","iopub.execute_input":"2024-09-16T05:57:09.166361Z","iopub.status.idle":"2024-09-16T05:57:12.234538Z","shell.execute_reply.started":"2024-09-16T05:57:09.166311Z","shell.execute_reply":"2024-09-16T05:57:12.233546Z"},"trusted":true},"execution_count":null,"outputs":[]}]}