{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.13"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":24800,"databundleVersionId":1831594,"sourceType":"competition"},{"sourceId":1801996,"sourceType":"datasetVersion","datasetId":1069999}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nfrom typing import Callable, Any\nimport multiprocessing\nimport math\n\nimport torch\nfrom torch import nn, optim\nfrom torchvision import transforms, utils\nfrom torch.utils.data import DataLoader, Dataset\ntqdm.pandas()\n\nimport cv2\nimport shutil\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport pydicom\nimport yaml\nimport glob\n\nfrom PIL import Image \n# from ultralytics import YOLO\n\nfrom sklearn.preprocessing import MultiLabelBinarizer \nfrom sklearn.model_selection import train_test_split\nfrom skmultilearn.model_selection import iterative_train_test_split\nfrom skimage import exposure\n\nfrom joblib import Parallel, delayed\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport random","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\ndevice","metadata":{"execution":{"iopub.status.busy":"2026-02-07T11:01:41.868792Z","iopub.execute_input":"2026-02-07T11:01:41.869177Z","iopub.status.idle":"2026-02-07T11:01:41.877077Z","shell.execute_reply.started":"2026-02-07T11:01:41.869145Z","shell.execute_reply":"2026-02-07T11:01:41.876106Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Relevant terms\n\n- DICOM: The image is originally in .dicom format, storing not only the image data but high-bit depth information (up to 16-bit) and metadata (patient info, settings,..)\n\n- VOI LUT (Volume of Interest Look-Up Table): is a mathematical transformation used in medical imaging to make the relevant parts of 16-bit DICOM image visible to human eye (or ML model)","metadata":{}},{"cell_type":"code","source":"# Each dicom file is a container with pixel data, patient info and extraction metadata\nsample_path = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/000434271f63a053c4128a0ba6352c7f.dicom'\n\ndicom = pydicom.dcmread(sample_path)\nprint(dicom)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:01:43.747242Z","iopub.execute_input":"2026-02-07T11:01:43.74785Z","iopub.status.idle":"2026-02-07T11:01:43.926819Z","shell.execute_reply.started":"2026-02-07T11:01:43.747822Z","shell.execute_reply":"2026-02-07T11:01:43.925791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(dicom.pixel_array.shape) #(2 dim for original resolution)\n\ndicom.pixel_array","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:01:44.698691Z","iopub.execute_input":"2026-02-07T11:01:44.699062Z","iopub.status.idle":"2026-02-07T11:01:44.722411Z","shell.execute_reply.started":"2026-02-07T11:01:44.699034Z","shell.execute_reply":"2026-02-07T11:01:44.721492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"### apply_voi_lut applies a transformation (windowing) to focus on a specific shade of gray that matters for anatomical details\n# -> intensify better gray areas\n\napply_voi_lut(dicom.pixel_array, dicom)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:01:46.9591Z","iopub.execute_input":"2026-02-07T11:01:46.959446Z","iopub.status.idle":"2026-02-07T11:01:47.113606Z","shell.execute_reply.started":"2026-02-07T11:01:46.959422Z","shell.execute_reply":"2026-02-07T11:01:47.112541Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---------------------------------------------------------------------------------------------------------------------","metadata":{}},{"cell_type":"markdown","source":"### Proceess img","metadata":{}},{"cell_type":"code","source":"def dicom2img(path, voi_lut=True, fix_monochrome=True):\n    # Read the file\n    dicom = pydicom.dcmread(path)\n\n    # VOI LUT\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array.astype(np.float32)\n\n    # pixel inversion black <-> white \n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\": #monochrome1 0-white, 1-black, need to invert\n        data = np.max(data) - data\n\n    # normalize to 0-1\n    data = data - np.min(data)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n\n    # Scale to 0–255 and change type to Unasigned 8-bit Int\n    data = (data * 255).astype(np.uint8)\n\n    return data","metadata":{"execution":{"iopub.status.busy":"2026-02-07T11:02:05.406277Z","iopub.execute_input":"2026-02-07T11:02:05.406932Z","iopub.status.idle":"2026-02-07T11:02:05.414625Z","shell.execute_reply.started":"2026-02-07T11:02:05.406884Z","shell.execute_reply":"2026-02-07T11:02:05.413691Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def hist_equalize(input_img):\n    equalize_img = exposure.equalize_hist(input_img)\n    equalize_img = (equalize_img * 255).astype(np.uint8)\n    return equalize_img\n\ndef clahe_equalize(input_img, clip_limit=3.0, tile_grid_size=(8, 8)):\n    \"\"\"\n    Apply CLAHE (Contrast Limited Adaptive Histogram Equalization)\n    \n    input_img: 2D grayscale image (uint8, 0–255)\n    \"\"\"\n    clahe = cv2.createCLAHE(\n        clipLimit=clip_limit,\n        tileGridSize=tile_grid_size\n    )\n    equalized_img = clahe.apply(input_img)\n    return equalized_img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:05.558215Z","iopub.execute_input":"2026-02-07T11:02:05.558543Z","iopub.status.idle":"2026-02-07T11:02:05.564333Z","shell.execute_reply.started":"2026-02-07T11:02:05.558518Z","shell.execute_reply":"2026-02-07T11:02:05.563285Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def batch_processing_img(dicom_path, target_size):\n    '''\n    dicom_path: original .dicom path\n    target_size: output size of the image (1024x1024 or 512x512)\n\n    Return:\n        clahe: CLAHE processed\n        equa: Histogram equalized\n    '''\n    img_array = dicom2img(dicom_path)\n    resize_img = cv2.resize(img_array, (target_size, target_size))\n\n    clahe = clahe_equalize(resize_img)\n    equa = hist_equalize(resize_img)\n    \n    return clahe, equa","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:04:49.056759Z","iopub.execute_input":"2026-02-07T11:04:49.057058Z","iopub.status.idle":"2026-02-07T11:04:49.062744Z","shell.execute_reply.started":"2026-02-07T11:04:49.057036Z","shell.execute_reply":"2026-02-07T11:04:49.061584Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_one_image(train_img, train = True):\n    full_path = os.path.join(train_dir, train_img)\n    img_id = os.path.splitext(train_img)[0]\n\n    if train == True:\n        save_name = os.path.join(output_dir, 'train', f\"{img_id}.png\")\n    else:\n        save_name = os.path.join(output_dir, 'test', f\"{img_id}.png\")\n\n    clahe, equa = batch_processing_img(full_path, size)\n    cv2.imwrite(save_name, clahe)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:07.544647Z","iopub.execute_input":"2026-02-07T11:02:07.54495Z","iopub.status.idle":"2026-02-07T11:02:07.550592Z","shell.execute_reply.started":"2026-02-07T11:02:07.544927Z","shell.execute_reply":"2026-02-07T11:02:07.549375Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"size = 1024\n\ntrain_dir = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train'\n# test_dir = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/test'\n\noutput_dir = \"/kaggle/working/processed_image\"\nos.makedirs(output_dir, exist_ok=True)\nos.makedirs(os.path.join(output_dir, 'train'), exist_ok=True)\n\ntrain_path = os.listdir(train_dir)\n# test_path = os.listdir(test_dir)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:07.706939Z","iopub.execute_input":"2026-02-07T11:02:07.70726Z","iopub.status.idle":"2026-02-07T11:02:07.71841Z","shell.execute_reply.started":"2026-02-07T11:02:07.707225Z","shell.execute_reply":"2026-02-07T11:02:07.717524Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Save img\n\nParallel(n_jobs=-1)(\n    delayed(process_one_image)(img, train = True)\n    for img in tqdm(train_path, desc=\"Processing train images\")\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:04:52.041089Z","iopub.execute_input":"2026-02-07T11:04:52.041439Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Process bbox","metadata":{}},{"cell_type":"code","source":"def resize_boxes(row, size):\n    \"\"\"\n    Resize bounding boxes to a fixed square image size\n    \"\"\"\n\n    # For no-finding rows\n    if pd.isna(row['x_min']):\n        return row['x_min'], row['y_min'], row['x_max'], row['y_max']\n\n    w_scale = size / row['width']\n    h_scale = size / row['height']\n\n    x_min_new = round(row['x_min'] * w_scale, 1)\n    x_max_new = round(row['x_max'] * w_scale, 1)\n    y_min_new = round(row['y_min'] * h_scale, 1)\n    y_max_new = round(row['y_max'] * h_scale, 1)\n\n    return x_min_new, y_min_new, x_max_new, y_max_new","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:14.993039Z","iopub.execute_input":"2026-02-07T11:02:14.993364Z","iopub.status.idle":"2026-02-07T11:02:15.00014Z","shell.execute_reply.started":"2026-02-07T11:02:14.99334Z","shell.execute_reply":"2026-02-07T11:02:14.998881Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def normalize_bbox(df):\n\n    # Box Center\n    df['x_center'] = (df['x_min'] + df['x_max'])/2\n    df['y_center'] = (df['y_min'] + df['y_max'])/2\n    df['bbox_width'] = df['x_max'] - df['x_min']\n    df['bbox_height'] = df['y_max'] - df['y_min']\n\n    # Box Center Normalized\n    df['x_center_norm'] = df['x_center'] / df['width']\n    df['y_center_norm'] = df['y_center'] / df['height']\n    df['bbox_height_norm'] = df['bbox_height'] / df['height']\n    df['bbox_width_norm'] = df['bbox_width'] / df['width']\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:15.149039Z","iopub.execute_input":"2026-02-07T11:02:15.149948Z","iopub.status.idle":"2026-02-07T11:02:15.155268Z","shell.execute_reply.started":"2026-02-07T11:02:15.149909Z","shell.execute_reply":"2026-02-07T11:02:15.154175Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def calculate_iou(box1, box2):\n\n    x1_min, y1_min = box1['x_min_new'], box1['y_min_new']\n    x1_max, y1_max = box1['x_max_new'], box1['y_max_new']\n    \n    x2_min, y2_min = box2['x_min_new'], box2['y_min_new']\n    x2_max, y2_max = box2['x_max_new'], box2['y_max_new']\n    \n    # Intersection\n    inter_x_min = max(x1_min, x2_min)\n    inter_y_min = max(y1_min, y2_min)\n    inter_x_max = min(x1_max, x2_max)\n    inter_y_max = min(y1_max, y2_max)\n    \n    if inter_x_min >= inter_x_max or inter_y_min >= inter_y_max:\n        return 0.0\n    \n    inter_area = (inter_x_max - inter_x_min) * (inter_y_max - inter_y_min)\n    \n    # Union\n    box1_area = (x1_max - x1_min) * (y1_max - y1_min)\n    box2_area = (x2_max - x2_min) * (y2_max - y2_min)\n    union_area = box1_area + box2_area - inter_area\n    \n    if union_area == 0:\n        return 0.0\n    \n    iou = inter_area / union_area\n    return iou","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:15.283978Z","iopub.execute_input":"2026-02-07T11:02:15.284266Z","iopub.status.idle":"2026-02-07T11:02:15.291855Z","shell.execute_reply.started":"2026-02-07T11:02:15.284245Z","shell.execute_reply":"2026-02-07T11:02:15.290767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def merge_boxes(box1, box2):\n    merged = box1.copy()\n    merged['x_min_new'] = min(box1['x_min_new'], box2['x_min_new'])\n    merged['y_min_new'] = min(box1['y_min_new'], box2['y_min_new'])\n    merged['x_max_new'] = max(box1['x_max_new'], box2['x_max_new'])\n    merged['y_max_new'] = max(box1['y_max_new'], box2['y_max_new'])\n    return merged","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:15.40502Z","iopub.execute_input":"2026-02-07T11:02:15.40534Z","iopub.status.idle":"2026-02-07T11:02:15.411411Z","shell.execute_reply.started":"2026-02-07T11:02:15.405297Z","shell.execute_reply":"2026-02-07T11:02:15.410397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def merge_overlapping_boxes(df, iou_threshold=0.3):\n\n    if df.empty:\n        return df\n    \n    required_cols = df.columns\n\n    keep_cols = [col for col in required_cols if col in df.columns]\n    \n    merged_records = []\n    processed_indices = set()\n\n    for (img_id, class_name), group in tqdm(df.groupby(['image_id', 'class_name']), \n                                             desc=\"Merging overlapping boxes\"):\n        group_indices = group.index.tolist()\n\n        if len(group_indices) == 1:\n            merged_records.append(group.iloc[0].to_dict())\n            processed_indices.update(group_indices)\n            continue\n        \n        # Convert to list of dicts \n        boxes = group.to_dict('records')\n        box_indices = group_indices.copy()\n        merged_flags = [False] * len(boxes)\n        \n        # Merge boxes with IoU > threshold\n        for i in range(len(boxes)):\n            if merged_flags[i]:\n                continue\n            \n            current_box = boxes[i]\n            boxes_to_merge = [i]\n\n            for j in range(i + 1, len(boxes)):\n                if merged_flags[j]:\n                    continue\n                \n                iou = calculate_iou(current_box, boxes[j])\n                \n                if iou > iou_threshold:\n                    boxes_to_merge.append(j)\n                    merged_flags[j] = True\n\n            if len(boxes_to_merge) > 1:\n                # Merge iteratively\n                merged_box = boxes[boxes_to_merge[0]]\n                for idx in boxes_to_merge[1:]:\n                    merged_box = merge_boxes(merged_box, boxes[idx])\n                merged_records.append(merged_box)\n                processed_indices.update([box_indices[idx] for idx in boxes_to_merge])\n            else:\n                merged_records.append(current_box)\n                processed_indices.add(box_indices[i])\n\n    merged_df = pd.DataFrame(merged_records)\n\n    final_cols = [col for col in keep_cols if col in merged_df.columns]\n    merged_df = merged_df[final_cols]\n\n    return merged_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:19.187421Z","iopub.execute_input":"2026-02-07T11:02:19.187725Z","iopub.status.idle":"2026-02-07T11:02:19.197706Z","shell.execute_reply.started":"2026-02-07T11:02:19.187702Z","shell.execute_reply":"2026-02-07T11:02:19.196459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df = pd.read_csv('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv')\nbbox_df = bbox_df.drop('rad_id', axis = 1)\n\nsize_df = pd.read_csv('/kaggle/input/d/xhlulu/vinbigdata/train_meta.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:19.482133Z","iopub.execute_input":"2026-02-07T11:02:19.48246Z","iopub.status.idle":"2026-02-07T11:02:19.593429Z","shell.execute_reply.started":"2026-02-07T11:02:19.482433Z","shell.execute_reply":"2026-02-07T11:02:19.592593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df = bbox_df.merge(size_df, how = 'left', on = 'image_id')\n\nbbox_df = bbox_df.rename(columns = {'dim0': 'height', 'dim1': 'width'})\n\nbbox_df[['x_min_new', 'y_min_new', 'x_max_new', 'y_max_new']] = bbox_df.progress_apply(resize_boxes, axis=1, result_type='expand', args=(512,))\n\nbbox_df = normalize_bbox(bbox_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:20.565937Z","iopub.execute_input":"2026-02-07T11:02:20.566236Z","iopub.status.idle":"2026-02-07T11:02:22.946853Z","shell.execute_reply.started":"2026-02-07T11:02:20.566214Z","shell.execute_reply":"2026-02-07T11:02:22.945902Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df_no = bbox_df[bbox_df['class_id'] == 14]\nbbox_df_yes = bbox_df[bbox_df['class_id'] != 14]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:22.973699Z","iopub.execute_input":"2026-02-07T11:02:22.974635Z","iopub.status.idle":"2026-02-07T11:02:22.990027Z","shell.execute_reply.started":"2026-02-07T11:02:22.974601Z","shell.execute_reply":"2026-02-07T11:02:22.989039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df_yes = merge_overlapping_boxes(bbox_df_yes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:24.568795Z","iopub.execute_input":"2026-02-07T11:02:24.569085Z","iopub.status.idle":"2026-02-07T11:02:38.475403Z","shell.execute_reply.started":"2026-02-07T11:02:24.569061Z","shell.execute_reply":"2026-02-07T11:02:38.474471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df = pd.concat([bbox_df_yes, bbox_df_no], axis = 0).sort_values('image_id').reset_index(drop = True)\n\nbbox_df = bbox_df.drop_duplicates()\n\nbbox_df = bbox_df.fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:02:39.848912Z","iopub.execute_input":"2026-02-07T11:02:39.849177Z","iopub.status.idle":"2026-02-07T11:02:39.964841Z","shell.execute_reply.started":"2026-02-07T11:02:39.849158Z","shell.execute_reply":"2026-02-07T11:02:39.964074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bbox_df.to_csv(os.path.join(output_dir, 'bbox.csv'), index=False, encoding='utf-8-sig')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:03:41.638996Z","iopub.execute_input":"2026-02-07T11:03:41.639346Z","iopub.status.idle":"2026-02-07T11:03:42.262768Z","shell.execute_reply.started":"2026-02-07T11:03:41.639285Z","shell.execute_reply":"2026-02-07T11:03:42.261696Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"-------------------------------------------------------------------------------------------------------------","metadata":{}},{"cell_type":"code","source":"class_label = bbox_df[['class_name', 'class_id']].drop_duplicates().reset_index(drop=True)\nclass_label.sort_values(by='class_id')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:03:56.065077Z","iopub.execute_input":"2026-02-07T11:03:56.065414Z","iopub.status.idle":"2026-02-07T11:03:56.081231Z","shell.execute_reply.started":"2026-02-07T11:03:56.065389Z","shell.execute_reply":"2026-02-07T11:03:56.080441Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def write_yolo_labels(df: pd.DataFrame, label_dir: str):\n\n    os.makedirs(label_dir, exist_ok=True)\n\n    df = df.copy()\n\n    df['image_id'] = df['image_id'].astype(str)\n    \n    for image_id, group in tqdm(df.groupby('image_id'), desc='Writing YOLO labels'):\n        lines: list[str] = []\n        for _, row in group.iterrows():\n            # Assuming normalized columns exist\n            if pd.isna(row['x_center_norm']): continue\n            \n            lines.append(\n                f\"{int(row['class_id'])} {row['x_center_norm']:.6f} {row['y_center_norm']:.6f} {row['bbox_width_norm']:.6f} {row['bbox_height_norm']:.6f}\"\n            )\n\n        label_path = os.path.join(label_dir, f\"{image_id}.txt\")\n        with open(label_path, 'w', encoding='utf-8') as f:\n            f.write('\\n'.join(lines))","metadata":{"execution":{"iopub.status.busy":"2026-02-07T11:04:08.989364Z","iopub.execute_input":"2026-02-07T11:04:08.990258Z","iopub.status.idle":"2026-02-07T11:04:08.996862Z","shell.execute_reply.started":"2026-02-07T11:04:08.990226Z","shell.execute_reply":"2026-02-07T11:04:08.995582Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_dir = os.path.join(output_dir, 'labels')\n\n# Generate labels\nprint(f\"Generating YOLO labels in {label_dir}...\")\nwrite_yolo_labels(bbox_df, label_dir)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T11:04:09.588074Z","iopub.execute_input":"2026-02-07T11:04:09.5884Z","iopub.status.idle":"2026-02-07T11:04:15.794896Z","shell.execute_reply.started":"2026-02-07T11:04:09.588375Z","shell.execute_reply":"2026-02-07T11:04:15.793642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"list_label = glob.glob(label_dir + \"/*\")\n\nfor i in range(1):\n    with open(list_label[i]) as f:\n        file = f.read()\n        print(file)\n\n## Each line contains the Class-x_center-y_center-height-width of the bbox","metadata":{"execution":{"iopub.status.busy":"2026-02-07T11:04:16.879173Z","iopub.execute_input":"2026-02-07T11:04:16.879537Z","iopub.status.idle":"2026-02-07T11:04:16.916141Z","shell.execute_reply.started":"2026-02-07T11:04:16.879503Z","shell.execute_reply":"2026-02-07T11:04:16.915144Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import shutil\n# import os\n\n# folder_to_zip = \"/kaggle/working/clahe_images\"\n# zip_path = \"/kaggle/working/clahe_images.zip\"\n\n# # Remove old zip if exists\n# if os.path.exists(zip_path):\n#     os.remove(zip_path)\n\n# # Create zip\n# shutil.make_archive(\n#     base_name=zip_path.replace(\".zip\", \"\"),\n#     format=\"zip\",\n#     root_dir=folder_to_zip\n# )\n\n# print(\"Zip created at:\", zip_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-26T13:15:12.737157Z","iopub.execute_input":"2026-01-26T13:15:12.73753Z","iopub.status.idle":"2026-01-26T13:15:41.323126Z","shell.execute_reply.started":"2026-01-26T13:15:12.737504Z","shell.execute_reply":"2026-01-26T13:15:41.321847Z"}},"outputs":[],"execution_count":null}]}