{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":117682,"databundleVersionId":15062069,"isSourceIdPinned":false}],"dockerImageVersionId":31328,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 📜 Vesuvius Geometric Manifold Unroller\n\n## Classical Signal Reconstruction & Surface Detection","metadata":{}},{"cell_type":"markdown","source":"This notebook departs from standard black-box Deep Learning approaches, instead treating the Vesuvius scrolls as a 3D Geometric Manifold $\\mathcal{M}$. By utilizing the physical properties of X-ray attenuation and structural constraints, we isolate surface signals through rigorous classical signal processing.The Mathematical Framework1. Z-Axis Variance MaximizationTo identify the papyrus interface, we seek the slice $z^*$ with the maximum local variance, representing the highest structural complexity:$$z^* = \\arg\\max_{z} \\left( \\frac{1}{N} \\sum_{i=1}^{N} (I_{z,i} - \\mu_z)^2 \\right)$$2. Adaptive Signal CleaningWe decouple the papyrus signal from noise using a variance-weighted adaptive filter. Given a low-pass signal $L$, the cleaned intensity $C$ is defined by:$$C = L + (I - L) \\cdot \\frac{\\sigma^2}{\\sigma^2 + \\sigma_{noise}^2}$$3. Multi-Scale Vesselness (Frangi Filter)The surface is modeled as a 2D plate in 3D space. We use the Eigenvalues $(\\lambda_1, \\lambda_2)$ of the Hessian matrix $H$:$$H = \\begin{bmatrix} \\frac{\\partial^2 I}{\\partial x^2} & \\frac{\\partial^2 I}{\\partial x \\partial y} \\\\ \\frac{\\partial^2 I}{\\partial y \\partial x} & \\frac{\\partial^2 I}{\\partial y^2} \\end{bmatrix}$$The \"sheetness\" measure $S$ highlights continuous linear structures while suppressing random noise:$$S = \\exp\\left(-\\frac{R_\\beta^2}{2\\beta^2}\\right) \\left(1 - \\exp\\left(-\\frac{S^2}{2c^2}\\right)\\right)$$4. Edge-Preserving Bilateral RefinementWe apply a Bilateral filter to ensure the mask boundaries $\\partial\\Omega$ align with physical intensity gradients:$$I^{filtered}(x) = \\frac{1}{W_p} \\sum_{x_i \\in \\Omega} I(x_i) f_s(\\|x_i - x\\|) g_r(|I(x_i) - I(x)|)$$\n\n## Technical Roadmap\n| Phase | Method | Objective| \n|-------|--------|----------|\n| I. Identification | Variance Maxima | Find the \"Best Z\" layer containing the highest structural signal.\n|II. Cleaning | Local Std Deviation | Decouple the air-to-papyrus interface from background noise.\n| III. Detection | Frangi Filter | Highlight the continuous manifold structure (the sheet).| \n|IV. Post-Processing | Bilateral & Otsu | Refine boundaries and binarize the output for submission.","metadata":{}},{"cell_type":"code","source":"!pip install imagecodecs tiffile","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-27T09:29:39.023057Z","iopub.execute_input":"2026-03-27T09:29:39.023471Z","iopub.status.idle":"2026-03-27T09:29:43.051821Z","shell.execute_reply.started":"2026-03-27T09:29:39.023429Z","shell.execute_reply":"2026-03-27T09:29:43.050636Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport tifffile\nimport os\nimport pandas as pd\nimport gc\nimport cv2\nimport zipfile\nfrom tqdm.auto import tqdm\nfrom scipy.ndimage import gaussian_filter\nfrom skimage.filters import frangi\n\nTILE_SIZE = 224\n\ndef rle_encode(mask):\n    pixels = mask.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef refine_manifold_mask(img, sheet_map):\n    norm_sheet = cv2.normalize(sheet_map, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n    refined = cv2.bilateralFilter(norm_sheet, d=11, sigmaColor=75, sigmaSpace=75)\n    binary = cv2.adaptiveThreshold(refined, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \n                                   cv2.THRESH_BINARY, 11, 2)\n    kernel = np.ones((3,3), np.uint8)\n    healed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)\n    return (healed // 255).astype(np.uint8)\n\nclass VesuviusGeometricEngine:\n    def __init__(self, crop_size=1024):\n        self.crop_size = crop_size\n\n    def process_volume(self, path):\n        try:\n            with tifffile.TiffFile(path) as tif:\n                volume = tif.asarray()\n            \n            if volume.ndim == 3:\n                variances = [np.std(volume[z, ::10, ::10]) for z in range(volume.shape[0])]\n                best_z = np.argmax(variances)\n                raw_2d = volume[best_z].astype('float32')\n            else:\n                raw_2d = volume.astype('float32')\n            \n            del volume\n            gc.collect()\n\n            raw_2d /= (np.max(raw_2d) + 1e-6)\n            low_pass = gaussian_filter(raw_2d, sigma=1.5)\n            diff = raw_2d - low_pass\n            s_intensity = np.std(diff) * 0.5 + 1e-6\n            cleaned = low_pass + raw_2d * (diff**2 / (diff**2 + s_intensity**2))\n\n            sheet_map = frangi(cleaned, sigmas=[1.0, 1.5], black_ridges=False)\n            return refine_manifold_mask(cleaned, sheet_map)\n        except Exception:\n            return None\n\ndef run_submission():\n    TEST_DIR = \"/kaggle/input/competitions/vesuvius-challenge-surface-detection/test_images\"\n    if not os.path.exists(TEST_DIR):\n        pd.DataFrame({'id': [], 'target': []}).to_csv(\"submission.csv\", index=False)\n        return\n\n    test_files = sorted([f for f in os.listdir(TEST_DIR) if f.endswith('.tif')])\n    engine = VesuviusGeometricEngine()\n    results = []\n\n    for fname in tqdm(test_files):\n        path = os.path.join(TEST_DIR, fname)\n        mask = engine.process_volume(path)\n        \n        if mask is not None:\n            results.append({\n                'id': fname.replace(\".tif\", \"\"),\n                'target': rle_encode(mask)\n            })\n        else:\n            results.append({\n                'id': fname.replace(\".tif\", \"\"),\n                'target': \"\"\n            })\n        gc.collect()\n\n    df = pd.DataFrame(results)\n    df.to_csv(\"submission.csv\", index=False)\n    \n    with zipfile.ZipFile(\"submission.zip\", \"w\") as z:\n        z.write(\"submission.csv\")\n\nif __name__ == \"__main__\":\n    run_submission()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-27T09:29:43.054178Z","iopub.execute_input":"2026-03-27T09:29:43.054581Z","iopub.status.idle":"2026-03-27T09:29:43.810169Z","shell.execute_reply.started":"2026-03-27T09:29:43.054541Z","shell.execute_reply":"2026-03-27T09:29:43.809357Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"End of Code","metadata":{}}]}