{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":117682,"databundleVersionId":14443416,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":false,"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 PIL import Image, ImageSequence\nfrom pathlib import Path\nimport zipfile\nfrom io import BytesIO\nfrom tqdm import tqdm\nfrom skimage.filters import threshold_otsu\nfrom skimage.morphology import remove_small_objects\nfrom skimage.measure import label\n\nbase_dir = Path(\"/kaggle/input/vesuvius-challenge-surface-detection/\")\ntest_img_dir = base_dir / \"test_images\"\ntest_csv_path = base_dir / \"test.csv\"\nsubmission_zip_path = Path(\"/kaggle/working/submission.zip\")\n\ntry:\n    test_meta = pd.read_csv(test_csv_path)\n    print(f\" Found {len(test_meta)} test volumes in CSV.\")\nexcept FileNotFoundError:\n    print(f\" Error: Test CSV not found at {test_csv_path}\")\n\n\ndef load_volume(path: Path) -> np.ndarray:\n    \"\"\"\n    Load a multi-page TIFF into a 3D NumPy array: (slices, H, W)\n    \"\"\"\n    try:\n        with Image.open(path) as img:\n            frames = [np.array(frame) for frame in ImageSequence.Iterator(img)]\n        volume = np.stack(frames)\n        return volume\n    except Exception as e:\n        raise RuntimeError(f\"Error loading TIFF {path}: {e}\")\n\n\ndef smarter_predict(volume: np.ndarray) -> np.ndarray:\n    \"\"\"\n    A non-ML baseline using Otsu's threshold\n    followed by morphological cleanup.\n    \"\"\"\n    try:\n        thresh = threshold_otsu(volume)\n        mask = (volume > thresh)\n    except ValueError:\n\n        print(\"     Otsu thresholding failed, falling back to mean.\")\n        mean_val = volume.mean()\n        mask = (volume > mean_val)\n\n    labeled_mask = label(mask)\n    cleaned_mask = remove_small_objects(labeled_mask, min_size=5000)\n    \n    final_mask = (cleaned_mask > 0).astype(np.uint8)\n    \n    return final_mask\n\n\ndef save_volume_to_zip(volume: np.ndarray, zip_file, filename: str):\n    \"\"\"\n    Save 3D volume as a multi-page TIFF into an already-open ZIP.\n    \"\"\"\n    try:\n        slices = [Image.fromarray(v) for v in volume] # Already uint8\n        buffer = BytesIO()\n        slices[0].save(\n            buffer,\n            format=\"TIFF\",\n            save_all=True,\n            append_images=slices[1:]\n        )\n        zip_file.writestr(filename, buffer.getvalue())\n    except Exception as e:\n        raise RuntimeError(f\"Error saving {filename} to ZIP: {e}\")\n\n\nZIP_COMPRESSION = zipfile.ZIP_DEFLATED\nZIP_COMPRESS_LEVEL = 9\n\nprint(f\"\\n Starting processing... Writing to {submission_zip_path}\")\nprint(f\"   Compression: {ZIP_COMPRESSION}, Level: {ZIP_COMPRESS_LEVEL}\")\n\nwith zipfile.ZipFile(submission_zip_path, \"w\", \n                     compression=ZIP_COMPRESSION, \n                     compresslevel=ZIP_COMPRESS_LEVEL) as zf:\n    \n    for _, row in tqdm(test_meta.iterrows(), total=len(test_meta), desc=\"Processing volumes\"):\n        image_id = row[\"id\"]\n        filename = f\"{image_id}.tif\"\n        img_path = test_img_dir / filename\n\n        if not img_path.exists():\n            print(f\" File missing, skipping: {filename}\")\n            continue\n\n        try:\n            # 1. Load\n            volume = load_volume(img_path)\n            \n            if volume.ndim != 3:\n                print(f\" Invalid volume shape {volume.shape}, skipping {filename}\")\n                continue\n\n            # 2. Predict \n            mask = smarter_predict(volume)\n            \n            # 3. Save\n            save_volume_to_zip(mask, zf, filename) \n\n        except Exception as e:\n            print(f\" Error processing {filename}: {e}\")\n            continue\n\nprint(f\"\\n : {submission_zip_path}\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-15T05:24:16.882578Z","iopub.execute_input":"2025-11-15T05:24:16.882877Z","iopub.status.idle":"2025-11-15T05:24:37.414922Z","shell.execute_reply.started":"2025-11-15T05:24:16.882848Z","shell.execute_reply":"2025-11-15T05:24:37.413964Z"}},"outputs":[],"execution_count":null}]}