{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":39272,"databundleVersionId":4629629,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":11730750,"sourceType":"datasetVersion","datasetId":7363888},{"sourceId":11847257,"sourceType":"datasetVersion","datasetId":7443877}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"! pip install -qU \"python-gdcm\" pydicom pylibjpeg \"opencv-python-headless\" \"scikit-image\" \"ipywidgets\" \"dicomsdl\"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 1. Uninstall the old, incompatible torch\n!pip uninstall -y torch torchvision torchaudio","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 1. Clone YOLOv5\n!git clone https://github.com/ultralytics/yolov5.git /kaggle/working/yolov5\n\n# 2. Install its Python requirements\n!pip install -r /kaggle/working/yolov5/requirements.txt","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T05:24:27.533511Z","iopub.execute_input":"2025-05-19T05:24:27.533841Z","iopub.status.idle":"2025-05-19T05:25:42.04618Z","shell.execute_reply.started":"2025-05-19T05:24:27.533817Z","shell.execute_reply":"2025-05-19T05:25:42.045137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 1. Handle datasets\nimport io\nimport os\nimport cv2\nimport random\nimport torch\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom glob import glob\nfrom pathlib import Path\nfrom tqdm.auto import tqdm\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nfrom skimage.transform import resize\nfrom PIL import Image, ImageDraw\nfrom pathlib import Path\nfrom collections import Counter\nfrom joblib import Parallel, delayed\nfrom tqdm import tqdm\nimport imageio\nimport gc","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-19T05:26:03.445779Z","iopub.execute_input":"2025-05-19T05:26:03.446315Z","iopub.status.idle":"2025-05-19T05:26:05.630072Z","shell.execute_reply.started":"2025-05-19T05:26:03.446291Z","shell.execute_reply":"2025-05-19T05:26:05.629508Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"parent_dir = \"/kaggle/input/jp2000\"\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nmodel = torch.hub.load(\n    './yolov5', \n    'custom', \n    path=\"/kaggle/input/roi-rsna/rsna-roi-003.pt\", \n    source='local'\n)\nmodel.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T05:26:09.15423Z","iopub.execute_input":"2025-05-19T05:26:09.155002Z","iopub.status.idle":"2025-05-19T05:26:11.98892Z","shell.execute_reply.started":"2025-05-19T05:26:09.154979Z","shell.execute_reply":"2025-05-19T05:26:11.988159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.children()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T04:51:24.723054Z","iopub.execute_input":"2025-05-19T04:51:24.723822Z","iopub.status.idle":"2025-05-19T04:51:24.728139Z","shell.execute_reply.started":"2025-05-19T04:51:24.723778Z","shell.execute_reply":"2025-05-19T04:51:24.727564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.cuda.empty_cache()\nfile_list = glob(\n    os.path.join(parent_dir, \"train_image_processed_jp2000_512\", \"*\", \"*.jp2\")\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T05:24:02.384882Z","iopub.execute_input":"2025-05-19T05:24:02.385168Z","iopub.status.idle":"2025-05-19T05:24:02.454629Z","shell.execute_reply.started":"2025-05-19T05:24:02.385146Z","shell.execute_reply":"2025-05-19T05:24:02.45372Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%matplotlib inline\n\nimages = []\n\nfor path in random.sample(file_list, 25):\n    frame = plt.imread(path)\n    \n    # Convert to PIL Image\n    img_pil = Image.fromarray(frame)\n    draw = ImageDraw.Draw(img_pil)\n\n    detections = model(frame)\n    results = detections.pandas().xyxy[0].to_dict(orient=\"records\")\n    \n    for result in results:\n        xmin, ymin = int(result['xmin']), int(result['ymin'])\n        xmax, ymax = int(result['xmax']), int(result['ymax'])\n        draw.rectangle([(xmin, ymin), (xmax, ymax)], outline='red', width=4)\n    \n    images.append(np.array(img_pil))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T04:53:01.986654Z","iopub.execute_input":"2025-05-19T04:53:01.986972Z","iopub.status.idle":"2025-05-19T04:53:03.427467Z","shell.execute_reply.started":"2025-05-19T04:53:01.986948Z","shell.execute_reply":"2025-05-19T04:53:03.426851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig, axes = plt.subplots(5, 5, figsize=(20,20))\n    \nfor idx, image in enumerate(images):\n    i = idx % 5 \n    j = idx // 5 \n    axes[i, j].imshow(image, cmap=\"bone\")\n    axes[i, j].axis('off')\n\nplt.subplots_adjust(wspace=0, hspace=.2)\nplt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T04:53:11.726004Z","iopub.execute_input":"2025-05-19T04:53:11.726502Z","iopub.status.idle":"2025-05-19T04:53:12.925861Z","shell.execute_reply.started":"2025-05-19T04:53:11.726479Z","shell.execute_reply":"2025-05-19T04:53:12.924142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 4, figsize=(20, 5))\naxes = axes.flatten()\n\nfor ax, img in zip(axes, images[:4]):\n    ax.imshow(img)\n    ax.axis('off')\n\nplt.subplots_adjust(wspace=0, hspace=0.2)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T04:56:32.458739Z","iopub.execute_input":"2025-05-19T04:56:32.459083Z","iopub.status.idle":"2025-05-19T04:56:32.73946Z","shell.execute_reply.started":"2025-05-19T04:56:32.459061Z","shell.execute_reply":"2025-05-19T04:56:32.738789Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# === CONFIG ===\nRESIZE_TO = 512\nSAVE_DIR = f\"/kaggle/working/train_image_ROI_processed_jp2000_{RESIZE_TO}\"\nparent_dir = \"/kaggle/input/jp2000\"\n\n# Gather all .jp2 paths\nall_jp2_files = list(\n    Path(os.path.join(parent_dir, \"train_image_processed_jp2000_512\")).rglob(\"*.jp2\")\n)\nfail_counter = Counter()\nmodel.eval()\n\n# === CLEANING ===\ndef cleanup():\n    gc.collect()\n    torch.cuda.empty_cache()\n\n# === RESIZE ===\ndef image_resize(image, width=None, height=None):\n    (h, w) = image.shape[:2]\n\n    if width is None and height is None:\n        return image\n\n    if width is None:\n        r = height / float(h)\n        dim = (int(w * r), height)\n    else:\n        r = width / float(w)\n        dim = (width, int(h * r))\n\n    resized = resize(image, (dim[1], dim[0]), preserve_range=True, anti_aliasing=True)\n    return resized.astype(np.uint8)\n\n# === MAIN PROCESSING FUNCTION ===\ndef extract_and_roi(path):\n    try:\n        if not path.exists() or not path.is_file():\n            fail_counter[\"invalid_path\"] += 1\n            print(f\"[ERROR] Invalid path: {path}\")\n            return\n        \n        parent_folder = path.parent.name\n        save_subdir = os.path.join(parent_dir, SAVE_DIR, parent_folder)\n        os.makedirs(save_subdir, exist_ok=True)\n\n        image = plt.imread(str(path))\n        if image.dtype != np.uint8:\n            image = (image * 255).astype(np.uint8)\n        \n        # Ensure image loaded correctly\n        if image is None:\n            raise ValueError(\"Could not load image\")\n        \n        # Check if the image is valid\n        if image.shape[0] == 0 or image.shape[1] == 0:\n            fail_counter[\"invalid_image\"] += 1\n            print(f\"[ERROR] Image is empty: {path}\")\n            return\n        \n        results = model(image)\n        detections = results.pandas().xyxy[0]\n        \n        if len(detections) == 0:\n            fail_counter[\"no_roi\"] += 1\n            return\n\n        for i, det in detections.iterrows():\n            x1, y1, x2, y2 = map(int, [det[\"xmin\"], det[\"ymin\"], det[\"xmax\"], det[\"ymax\"]])\n            \n            # Check for valid ROI dimensions\n            if x1 < 0 or y1 < 0 or x2 > image.shape[1] or y2 > image.shape[0]:\n                fail_counter[\"invalid_roi\"] += 1\n                print(f\"[ERROR] Invalid ROI for {path}: {x1}, {y1}, {x2}, {y2}\")\n                continue\n            \n            roi = image[y1:y2, x1:x2]\n            roi_resized = image_resize(roi, width=RESIZE_TO)\n            \n            save_path = os.path.join(save_subdir, f\"{path.stem}.jp2\")\n            try:\n                imageio.imwrite(save_path, roi_resized, format='JP2')\n            except Exception as e:\n                print(f\"[ERROR] Failed to save ROI for {path}: {e}\")\n                fail_counter[\"save_error\"] += 1\n\n            # === For sanity Check === \n            # return save_path\n        \n            # Clean up memory\n            cleanup()\n\n    except Exception as e:\n        print(f\"[ERROR] Failed processing {path} — {e}\")\n        fail_counter[\"fail\"] += 1\n\n# === Sanity Check ===\n# for path in tqdm(all_jp2_files[:1], desc=\"Sanity Check\"):\n#     save_path = extract_and_roi(path)\n#     img = plt.imread(save_path)\n#     plt.imshow(img, cmap=\"turbo\")\n#     print(\"✅ Sanity check complete.\")\n#     print(f\"image size = {img.shape}\")\n    \n#     plt.axis('off')\n#     plt.show()\n#     break\n\n# === RUN ===\nParallel(n_jobs=16, backend=\"loky\", prefer=\"threads\")(\n    delayed(extract_and_roi)(path) for path in tqdm(all_jp2_files)\n)\n\nprint(f\"✅ Done! Processed {len(all_jp2_files)} images.\")\nprint(f\"❌ Failed: {fail_counter['fail']}, \",\n      f\"No ROI: {fail_counter['no_roi']}, \",\n      f\"Invalid Path: {fail_counter['invalid_path']}, \",\n      f\"Invalid Image: {fail_counter['invalid_image']},\" \n      f\"Save Errors: {fail_counter['save_error']}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}