{"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":198046308,"sourceType":"kernelVersion"},{"sourceId":198066213,"sourceType":"kernelVersion"}],"dockerImageVersionId":30762,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q ultralytics\n!pip install -q albumentations  # Thêm thư viện augment dữ liệu","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-10-14T16:06:36.848063Z","iopub.execute_input":"2024-10-14T16:06:36.848548Z","iopub.status.idle":"2024-10-14T16:07:05.649347Z","shell.execute_reply.started":"2024-10-14T16:06:36.848507Z","shell.execute_reply":"2024-10-14T16:07:05.648173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom pathlib import Path\nfrom sklearn.utils import resample\nfrom sklearn.model_selection import train_test_split\nimport os\nfrom shutil import copyfile\nimport yaml\nfrom albumentations import Compose, RandomRotate90, Flip, Transpose, ShiftScaleRotate, RandomBrightnessContrast\nfrom ultralytics import YOLO","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:05.651278Z","iopub.execute_input":"2024-10-14T16:07:05.651615Z","iopub.status.idle":"2024-10-14T16:07:12.372010Z","shell.execute_reply.started":"2024-10-14T16:07:05.651579Z","shell.execute_reply":"2024-10-14T16:07:12.371011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Load trained model\n# model = YOLO('/kaggle/input/vincxr-yolov8m/runs/detect/Yolov8m(640, 100, 32)/weights/best.pt')\n\n# # Perform prediction on test images folder with a specified batch size\n# results = model.predict(\n#     source='/kaggle/input/amia-public-challenge-2024/test/test',\n#     conf=0.2,\n#     iou=0.2,\n#     imgsz=640,\n# #     device='0',  # Use only one GPU (change to '0,1' if you increase batch size)\n#     batch=16,  # Keep batch size at 16 for single GPU\n# #     visualize=True,\n# #     augment=True,  # TTA\n#     save_txt=True,\n#     save_conf=True,\n#     show_labels=True,\n#     show_conf=True,\n#     show_boxes=True\n# )","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:12.373252Z","iopub.execute_input":"2024-10-14T16:07:12.373706Z","iopub.status.idle":"2024-10-14T16:07:12.378203Z","shell.execute_reply.started":"2024-10-14T16:07:12.373672Z","shell.execute_reply":"2024-10-14T16:07:12.377330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Xử lý cho 16 class\n#https://etrain.xyz/posts/vinbigdata-chest-x-ray-abnormalities-detection\n# https://www.kaggle.com/code/duythanhng/vinbigdata-yolov5-16-class\n# https://www.kaggle.com/datasets/awsaf49/vinbigdata-1024-image-dataset","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:12.380177Z","iopub.execute_input":"2024-10-14T16:07:12.380501Z","iopub.status.idle":"2024-10-14T16:07:12.389162Z","shell.execute_reply.started":"2024-10-14T16:07:12.380468Z","shell.execute_reply":"2024-10-14T16:07:12.388308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Đọc file kích thước ảnh từ img_size.csv\nimg_size_file = '/kaggle/input/amia-public-challenge-2024/img_size.csv'\nimg_size_df = pd.read_csv(img_size_file)\n\n# Chuyển đổi dữ liệu thành dạng dictionary để tra cứu nhanh\nimg_size_dict = {row['image_id']: (row['dim0'], row['dim1']) for _, row in img_size_df.iterrows()}\n\n# Đường dẫn tới thư mục ảnh test\ntest_images_folder = '/kaggle/input/amia-public-challenge-2024/test/test'\n\n# Lấy danh sách file test (tên ảnh) trong thư mục test\ntest_image_filenames = [f for f in os.listdir(test_images_folder) if f.endswith('.png')]","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:12.390323Z","iopub.execute_input":"2024-10-14T16:07:12.390958Z","iopub.status.idle":"2024-10-14T16:07:13.541517Z","shell.execute_reply.started":"2024-10-14T16:07:12.390926Z","shell.execute_reply":"2024-10-14T16:07:13.540693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # for VinBigData 1024 Image Dataset\n\n# # Đường dẫn tới thư mục ảnh test\n# test_images_folder = '/kaggle/input/vinbigdata-1024-image-dataset/vinbigdata/test'\n\n# # Lấy danh sách file test (tên ảnh) trong thư mục test\n# test_image_filenames = [f for f in os.listdir(test_images_folder) if f.endswith('.png')]\n\n# dim = '1024' #1024, 512, 256, 'original'\n# test_df = pd.read_csv(f'/kaggle/input/vinbigdata-{dim}-image-dataset/vinbigdata/test.csv')\n# test_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:13.542696Z","iopub.execute_input":"2024-10-14T16:07:13.543050Z","iopub.status.idle":"2024-10-14T16:07:13.547289Z","shell.execute_reply.started":"2024-10-14T16:07:13.543016Z","shell.execute_reply":"2024-10-14T16:07:13.546485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport csv\nimport pandas as pd\nimport numpy as np\n\n# Load trained model\nmodel = YOLO('/kaggle/input/vincxr-yolov8x-balancemax-hpyolov8-chestxray2/vincxr_yolov8x_balanceMax_HPYOLOv8_ChestXray/time11hour2/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-balancemax-mambayolov8/vincxr_yolov8x_balanceMax_MambaYOLOv8/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-640px-16class-lstm/vincxr_yolov8x_640px_16class_lstm/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-attentioncbam-time11/runs/detect/Yolov8m(640, 100, 32)/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-lstm/runs/detect/Yolov8m(640, 100, 32)/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-640px-16class-gru/vincxr_yolov8x_640px_16class_gru/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-gru/vincxr_yolov8m_640px_16class_gru/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8/other/default/1/best_vincxr-yolov8m-640px-16class-SODYOLOv8.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-modyolov8/vincxr_yolov8m_640px_16class_ModYOLOv8/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-balancemax-hpyolov8/vincxr_yolov8m_balanceMax_HPYOLOv8/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-hpyolov8/vincxr_yolov8m_640px_16class_HPYOLOv8/time11hour_new/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-640px-16class-hpyolov8_ntgiang2304/other/default/1/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8m-balancemax-msyolov8/vincxr_yolov8m_balanceMax_MSYOLOv8/time8hour_resume/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-balancemax-hpyolov8/vincxr_yolov8x_balanceMax_HPYOLOv8/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-balancemax-hpyolov8-chestxray/vincxr_yolov8x_balanceMax_HPYOLOv8_ChestXray/time11hour/weights/best.pt')\n# model = YOLO('/kaggle/input/vincxr-yolov8x-balancemax-msyolov8/vincxr_yolov8x_balanceMax_MSYOLOv8/time11hour/weights/best.pt')","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:13.548590Z","iopub.execute_input":"2024-10-14T16:07:13.548896Z","iopub.status.idle":"2024-10-14T16:07:15.956859Z","shell.execute_reply.started":"2024-10-14T16:07:13.548865Z","shell.execute_reply":"2024-10-14T16:07:15.955825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Thực hiện dự đoán\nresults = model.predict(\n    source=test_images_folder,\n    conf=0.01,\n    iou=0.45,\n    imgsz=640,\n    batch=64,\n    device='0',  # Use only one GPU (change to '0,1' if you increase batch size)\n    save_txt=True,\n    save_conf=True,\n    show_labels=True,\n    show_conf=True,\n    show_boxes=True\n)","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:07:15.958548Z","iopub.execute_input":"2024-10-14T16:07:15.958966Z","iopub.status.idle":"2024-10-14T16:17:00.205721Z","shell.execute_reply.started":"2024-10-14T16:07:15.958923Z","shell.execute_reply":"2024-10-14T16:17:00.204916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Áp Dụng Quy Tắc Xử Lý:\n\n# Nếu có \"No finding\" (no_finding):\n# Có cả \"finding\" (finding):\n# So sánh xác suất cao nhất của \"No finding\" và \"finding\".\n# Nếu \"No finding\" có xác suất cao hơn, chọn chỉ \"No finding\".\n# Nếu không, không thêm gì vào final_detections (loại bỏ \"finding\").\n# Chỉ có \"No finding\" kèm các lớp khác (other_classes):\n# Nếu xác suất của \"No finding\" > 80%, chọn chỉ \"No finding\".\n# Ngược lại, chọn các lớp khác (loại bỏ \"No finding\").\n# Chỉ có \"No finding\": Chọn \"No finding\".\n# Nếu không có \"No finding\":\n# Không thêm \"finding\" vào final_detections.\n# Chỉ chọn các lớp khác (other_classes).\n\n\n\nimport csv\nfrom glob import glob\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport os\nimport logging\n\n# Cấu hình logging\nlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n\ndef yolo2voc(h, w, data):\n    x_center, y_center, width, height = data[:, 0], data[:, 1], data[:, 2], data[:, 3]\n    xmin = (x_center - width / 2) * w\n    xmax = (x_center + width / 2) * w\n    ymin = (y_center - height / 2) * h\n    ymax = (y_center + height / 2) * h\n    return np.column_stack((xmin, ymin, xmax, ymax))\n\ndef process_detections(file_path, img_size_dict, confidence_threshold=0.8):\n    image_id, _ = os.path.splitext(os.path.basename(file_path))\n    h, w = img_size_dict.get(image_id, (1, 1))  # Mặc định (1,1) để tránh chia cho 0\n    \n    with open(file_path, 'r') as f:\n        content = f.read().strip()\n        if not content:\n            # Nếu không có phát hiện, mặc định là \"No finding\"\n            logging.info(f\"{image_id}: Không có phát hiện. Mặc định 'No finding'.\")\n            return \"14 1 0 0 1 1\"\n        \n        # Chia nội dung thành các phát hiện\n        try:\n            data = np.array(content.replace('\\n', ' ').split()).astype(np.float32).reshape(-1, 6)\n        except ValueError:\n            # Nếu dữ liệu không đúng định dạng, mặc định là \"No finding\"\n            logging.warning(f\"{image_id}: Dữ liệu phát hiện không đúng định dạng. Mặc định 'No finding'.\")\n            return \"14 1 0 0 1 1\"\n        \n        # Sắp xếp lại cột: [class_id, confidence, x_center, y_center, width, height]\n        data = data[:, [0, 5, 1, 2, 3, 4]]\n        \n        # Chuyển đổi hộp giới hạn\n        bboxes = np.round(np.concatenate((data[:, :2], yolo2voc(h, w, data[:, 2:])), axis=1), 3)\n        \n        # Phân loại các phát hiện theo class_id\n        no_finding = bboxes[bboxes[:, 0] == 14]\n        finding = bboxes[bboxes[:, 0] == 15]\n        other_classes = bboxes[(bboxes[:, 0] != 14) & (bboxes[:, 0] != 15)]\n        \n        # Khởi tạo danh sách để lưu các phát hiện cuối cùng\n        final_detections = []\n        \n        # Xử lý \"No finding\"\n        if no_finding.size > 0:\n            max_no_finding_conf = np.max(no_finding[:, 1])\n            \n            # Xử lý khi có cả \"finding\"\n            if finding.size > 0:\n                max_finding_conf = np.max(finding[:, 1])\n                if max_no_finding_conf > max_finding_conf:\n                    # Chọn \"No finding\"\n                    final_detections = [f\"14 {max_no_finding_conf:.3f} 0 0 1 1\"]\n                else:\n                    # Không chọn \"finding\" do yêu cầu loại bỏ class 15\n                    # Do đó, không thêm gì vào final_detections ở đây\n                    pass\n            else:\n                # Nếu có kèm các lớp khác\n                if other_classes.size > 0:\n                    if max_no_finding_conf > confidence_threshold:\n                        # Chọn chỉ \"No finding\"\n                        final_detections = [f\"14 {max_no_finding_conf:.3f} 0 0 1 1\"]\n                    else:\n                        # Bao gồm các lớp khác (loại trừ \"No finding\")\n                        final_detections = [\n                            f\"{int(cls)} {conf:.3f} {int(xmin)} {int(ymin)} {int(xmax)} {int(ymax)}\"\n                            for cls, conf, xmin, ymin, xmax, ymax in other_classes\n                        ]\n                else:\n                    # Chỉ có \"No finding\"\n                    final_detections = [f\"14 {max_no_finding_conf:.3f} 0 0 1 1\"]\n        else:\n            # Nếu không có \"No finding\"\n            if finding.size > 0:\n                # Không thêm \"finding\" vào final_detections theo yêu cầu\n                pass\n            if other_classes.size > 0:\n                # Bao gồm các lớp khác\n                final_detections += [\n                    f\"{int(cls)} {conf:.3f} {int(xmin)} {int(ymin)} {int(xmax)} {int(ymax)}\"\n                    for cls, conf, xmin, ymin, xmax, ymax in other_classes\n                ]\n        \n        # Xác định chuỗi dự đoán cuối cùng\n        if final_detections:\n            return ' '.join(final_detections)\n        else:\n            # Mặc định là \"No finding\" nếu không có phát hiện nào\n            return \"14 1.0 0 0 1 1\"\n\n\ndef create_submission_csv(label_dir, img_size_dict, output_csv='submission_new.csv', confidence_threshold=0.8):\n    # Lấy danh sách tất cả các tệp label\n    label_files = glob(os.path.join(label_dir, '*.txt'))\n    \n    # Khởi tạo danh sách để lưu kết quả\n    submission_data = []\n    \n    # Duyệt qua từng tệp label và xử lý\n    for file_path in tqdm(label_files, desc=\"Đang xử lý các tệp label\"):\n        image_id, _ = os.path.splitext(os.path.basename(file_path))\n        prediction_string = process_detections(file_path, img_size_dict, confidence_threshold)\n        submission_data.append({'image_id': image_id, 'PredictionString': prediction_string})\n    \n    # Chuyển đổi thành DataFrame và ghi vào CSV\n    submission_df = pd.DataFrame(submission_data)\n    submission_df.to_csv(output_csv, index=False)\n    \n    print(f\"File {output_csv} đã được tạo thành công.\")\n\n    \n# Định nghĩa đường dẫn tới thư mục chứa các tệp label\nlabel_directory = 'runs/detect/predict/labels'\n\n# Gọi hàm để tạo file submission\ncreate_submission_csv(label_directory, img_size_dict, output_csv='submission_new.csv', confidence_threshold=0.8)","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:17:00.207050Z","iopub.execute_input":"2024-10-14T16:17:00.207490Z","iopub.status.idle":"2024-10-14T16:17:01.455415Z","shell.execute_reply.started":"2024-10-14T16:17:00.207456Z","shell.execute_reply":"2024-10-14T16:17:01.454519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Code tối ưu chạy ok\n\n# import csv\n# from glob import glob\n# import numpy as np\n# from tqdm import tqdm\n# import os\n\n# # Hàm chuyển đổi từ định dạng YOLO sang VOC\n# def yolo2voc(h, w, data):\n#     x_center, y_center, width, height = data[:, 0], data[:, 1], data[:, 2], data[:, 3]\n#     xmin = (x_center - width / 2) * w\n#     xmax = (x_center + width / 2) * w\n#     ymin = (y_center - height / 2) * h\n#     ymax = (y_center + height / 2) * h\n#     return np.column_stack((xmin, ymin, xmax, ymax))\n\n# # Mở file submission để ghi\n# with open('submission_new.csv', mode='w', newline='') as submission_file:\n#     writer = csv.writer(submission_file)\n    \n#     # Ghi tiêu đề\n#     writer.writerow(['image_id', 'PredictionString'])\n    \n#     # Duyệt qua từng file kết quả phát hiện\n#     for file_path in tqdm(glob('runs/detect/predict/labels/*txt')):\n#         image_id, _ = os.path.splitext(os.path.basename(file_path))\n#         h, w = img_size_dict[image_id]\n        \n#         with open(file_path, 'r') as f:\n#             data = np.array(f.read().replace('\\n', ' ').strip().split(' ')).astype(np.float32).reshape(-1, 6)\n#             data = data[:, [0, 5, 1, 2, 3, 4]]\n#             bboxes = np.round(np.concatenate((data[:, :2], np.round(yolo2voc(h, w, data[:, 2:]))), axis=1), 1)\n            \n#             prediction_strings = [\n#                 f\"{int(class_id)} {confidence:.3f} {xmin:.0f} {ymin:.0f} {xmax:.0f} {ymax:.0f}\"\n#                 for class_id, confidence, xmin, ymin, xmax, ymax in bboxes\n#                 if int(class_id) != 15\n#             ]\n            \n#             if int(bboxes[0][0]) == 14:\n#                 final_prediction_string = \"14 1.0 0 0 1 1\"\n#             elif len(prediction_strings) > 0:\n#                 final_prediction_string = ' '.join(prediction_strings)\n#             else:\n#                 final_prediction_string = \"14 1 0 0 1 1\"\n            \n#             # Ghi thông tin dự đoán cho từng ảnh vào file submission\n#             writer.writerow([image_id, final_prediction_string])\n\n# print(\"File submission_new.csv đã được tạo thành công.\")","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:17:01.458073Z","iopub.execute_input":"2024-10-14T16:17:01.458389Z","iopub.status.idle":"2024-10-14T16:17:01.464018Z","shell.execute_reply.started":"2024-10-14T16:17:01.458354Z","shell.execute_reply":"2024-10-14T16:17:01.463122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #test submit ok '/kaggle/input/amia-public-challenge-2024/test/test'\n\n# import csv\n# from glob import glob\n# import numpy as np\n# from tqdm import tqdm\n\n# # Hàm chuyển đổi từ định dạng YOLO sang VOC\n# def yolo2voc(h, w, data):\n#     x_center, y_center, width, height = data[:, 0], data[:, 1], data[:, 2], data[:, 3]\n#     xmin = (x_center - width / 2) * w\n#     xmax = (x_center + width / 2) * w\n#     ymin = (y_center - height / 2) * h\n#     ymax = (y_center + height / 2) * h\n#     return np.column_stack((xmin, ymin, xmax, ymax))\n\n# # Mở file submission để ghi\n# with open('submission.csv', mode='w', newline='') as submission_file:\n#     writer = csv.writer(submission_file)\n    \n#     # Ghi tiêu đề\n#     writer.writerow(['image_id', 'PredictionString'])\n    \n#     # Duyệt qua từng file kết quả phát hiện\n#     for file_path in tqdm(glob('/kaggle/working/runs/detect/predict/labels/*txt')):\n#         image_id = file_path.split('/')[-1].split('.')[0]\n#         h, w = img_size_dict[image_id]\n        \n#         with open(file_path, 'r') as f:\n#             data = np.array(f.read().replace('\\n', ' ').strip().split(' ')).astype(np.float32).reshape(-1, 6)\n#             data = data[:, [0, 5, 1, 2, 3, 4]]\n#             bboxes = np.round(np.concatenate((data[:, :2], np.round(yolo2voc(h, w, data[:, 2:]))), axis=1), 1)\n            \n#             prediction_strings = []\n#             for bbox in bboxes:\n#                 class_id, confidence, xmin, ymin, xmax, ymax = bbox\n                \n#                 # Kiểm tra nếu class ID là 14 (\"No finding\"), chuẩn hóa kết quả\n#                 if int(class_id) == 14:\n#                     prediction_string = \"14 1.0 0 0 1 1\"\n#                     break  # Không cần xử lý thêm các box khác nếu đã là lớp 14\n\n#                 if int(class_id) != 15:\n#                     prediction_string = f\"{int(class_id)} {confidence:.3f} {xmin:.0f} {ymin:.0f} {xmax:.0f} {ymax:.0f}\"\n#                     prediction_strings.append(prediction_string)\n            \n#             if len(prediction_strings) > 0:\n#                 final_prediction_string = ' '.join(prediction_strings)\n#             else:\n#                 final_prediction_string = \"14 1 0 0 1 1\"\n            \n#             # Ghi thông tin dự đoán cho từng ảnh vào file submission\n#             writer.writerow([image_id, final_prediction_string])\n\n# print(\"File submission.csv đã được tạo thành công.\")","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:17:01.465494Z","iopub.execute_input":"2024-10-14T16:17:01.465877Z","iopub.status.idle":"2024-10-14T16:17:01.479395Z","shell.execute_reply.started":"2024-10-14T16:17:01.465835Z","shell.execute_reply":"2024-10-14T16:17:01.478531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# #For for VinBigData 1024 Image Dataset\n# # Submit for VinBigData Chest X-ray Abnormalities Detection\n\n# import csv\n# from glob import glob\n# import numpy as np\n# from tqdm import tqdm\n\n# # Hàm chuyển đổi từ định dạng YOLO sang VOC\n# def yolo2voc(h, w, data):\n#     x_center, y_center, width, height = data[:, 0], data[:, 1], data[:, 2], data[:, 3]\n#     xmin = (x_center - width / 2) * w\n#     xmax = (x_center + width / 2) * w\n#     ymin = (y_center - height / 2) * h\n#     ymax = (y_center + height / 2) * h\n#     return np.column_stack((xmin, ymin, xmax, ymax))\n\n# # Mở file submission để ghi\n# with open('submission.csv', mode='w', newline='') as submission_file:\n#     writer = csv.writer(submission_file)\n    \n#     # Ghi tiêu đề\n#     writer.writerow(['image_id', 'PredictionString'])\n    \n#     # Duyệt qua từng file kết quả phát hiện\n#     for file_path in tqdm(glob('/kaggle/working/runs/detect/predict/labels/*txt')):\n#         image_id = file_path.split('/')[-1].split('.')[0]\n#         w, h = test_df.loc[test_df.image_id==image_id,['width', 'height']].values[0]\n        \n#         with open(file_path, 'r') as f:\n#             data = np.array(f.read().replace('\\n', ' ').strip().split(' ')).astype(np.float32).reshape(-1, 6)\n#             data = data[:, [0, 5, 1, 2, 3, 4]]\n#             bboxes = np.round(np.concatenate((data[:, :2], np.round(yolo2voc(h, w, data[:, 2:]))), axis=1), 1)\n            \n#             prediction_strings = []\n#             for bbox in bboxes:\n#                 class_id, confidence, xmin, ymin, xmax, ymax = bbox\n                \n#                 # Kiểm tra nếu class ID là 14 (\"No finding\"), chuẩn hóa kết quả\n#                 if int(class_id) == 14:\n#                     prediction_string = \"14 1.0 0 0 1 1\"\n#                     break  # Không cần xử lý thêm các box khác nếu đã là lớp 14\n\n#                 if int(class_id) != 15:\n#                     prediction_string = f\"{int(class_id)} {confidence:.3f} {xmin:.0f} {ymin:.0f} {xmax:.0f} {ymax:.0f}\"\n#                     prediction_strings.append(prediction_string)\n            \n#             if len(prediction_strings) > 0:\n#                 final_prediction_string = ' '.join(prediction_strings)\n#             else:\n#                 final_prediction_string = \"14 1 0 0 1 1\"\n            \n#             # Ghi thông tin dự đoán cho từng ảnh vào file submission\n#             writer.writerow([image_id, final_prediction_string])\n\n# print(\"File submission.csv đã được tạo thành công.\")","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:17:01.480413Z","iopub.execute_input":"2024-10-14T16:17:01.480715Z","iopub.status.idle":"2024-10-14T16:17:01.495067Z","shell.execute_reply.started":"2024-10-14T16:17:01.480668Z","shell.execute_reply":"2024-10-14T16:17:01.494145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Đánh giá mô hình trên tập validation\n# val_results = model.val(\n#     data ='/kaggle/input/vinbigdata-yolo-dataset-with-wbf-640px-16class/vinbigdata-yolo-dataset-with-wbf-640px-16class/data.yaml',\n#     split = 'val',\n#     device='0,1',\n#     iou=0.5)\n# print(val_results.box.map)  # mAP@0.5\n\n# import numpy as np\n\n# # Đưa ra ngưỡng riêng cho từng lớp\n# class_thresholds = [0.5] * len(val_results.box.ap50)  # Khởi tạo ngưỡng mặc định cho tất cả các lớp\n\n# for class_id in range(len(val_results.box.ap50)):\n#     if class_id < len(val_results.box.p):  # Kiểm tra xem class_id có hợp lệ không\n#         precision = val_results.box.p[class_id]\n#         recall = val_results.box.r[class_id]\n#         f1 = val_results.box.f1[class_id]\n        \n#         #  Sử dụng F1 score làm ngưỡng cho mỗi lớp thay vì trung bình của precision và recall. F1 score là một thước đo cân bằng giữa precision và recall.\n#         #  Đặt ngưỡng tối thiểu là 0.1 để tránh ngưỡng quá thấp có thể dẫn đến quá nhiều dự đoán sai.\n        \n#         # Tính ngưỡng tối ưu dựa trên F1 score\n#         threshold = f1  # Sử dụng F1 score làm ngưỡng\n        \n#         class_thresholds[class_id] = max(threshold, 0.01)  # Đặt ngưỡng tối thiểu là 0.1\n\n# print(\"Ngưỡng của từng lớp:\", class_thresholds)\n\n# # Hàm dự đoán với ngưỡng riêng cho từng lớp\n# def predict_with_thresholds(img_path):\n#     results = model.predict(img_path, conf=0.01, iou=0.45, agnostic_nms=True, max_det=300)\n    \n#     boxes = []\n#     scores = []\n#     class_ids = []\n    \n#     for result in results:\n#         for box, score, class_id in zip(result.boxes.xyxy, result.boxes.conf, result.boxes.cls):\n#             class_id = int(class_id)\n#             if class_id < len(class_thresholds) and score >= class_thresholds[class_id]:\n#                 boxes.append(box.tolist())\n#                 scores.append(float(score))\n#                 class_ids.append(class_id)\n    \n#     return boxes, scores, class_ids\n\n# # Danh sách tên lớp\n# class_names = ['Aortic_enlargement', 'Atelectasis', 'Calcification', 'Cardiomegaly', 'Consolidation', 'ILD', 'Infiltration', 'Lung_Opacity', 'Nodule/Mass', 'Other_lesion', 'Pleural_effusion', 'Pleural_thickening', 'Pneumothorax', 'Pulmonary_fibrosis', 'No finding', 'Finding']\n\n# # Dự đoán trên ảnh mới\n# img_path = '/kaggle/input/vinbigdata-yolo-dataset-with-wbf-640px-16class/vinbigdata-yolo-dataset-with-wbf-640px-16class/test/images/0005e8e3701dfb1dd93d53e2ff537b6e.jpg'\n# boxes, scores, class_ids = predict_with_thresholds(img_path)\n\n# print(\"Số lượng dự đoán:\", len(boxes))\n# print(\"\\nThông tin chi tiết các hộp dự đoán:\")\n# for i, (box, score, class_id) in enumerate(zip(boxes, scores, class_ids)):\n#     print(f\"Dự đoán {i+1}:\")\n#     print(f\"  Hộp giới hạn: {box}\")\n#     print(f\"  Độ tự tin: {score:.4f}\")\n#     print(f\"  Lớp ID: {class_id}\")\n#     print(f\"  Tên lớp: {class_names[class_id]}\")\n#     print()","metadata":{"execution":{"iopub.status.busy":"2024-10-14T16:17:01.496312Z","iopub.execute_input":"2024-10-14T16:17:01.496585Z","iopub.status.idle":"2024-10-14T16:17:01.510645Z","shell.execute_reply.started":"2024-10-14T16:17:01.496555Z","shell.execute_reply":"2024-10-14T16:17:01.509811Z"},"trusted":true},"execution_count":null,"outputs":[]}]}