| import os
|
| import tempfile
|
| import nibabel as nib
|
| import numpy as np
|
| import gdown
|
| import gradio as gr
|
| import torch
|
|
|
|
|
| from nnunetv2.inference.predict_from_raw_data import nnUNetPredictor
|
|
|
|
|
|
|
|
|
| MODEL_DIR = "models/nnUNet_trained"
|
| os.makedirs(MODEL_DIR, exist_ok=True)
|
|
|
| FOLDER_URL = "https://drive.google.com/drive/folders/163zOL8NmdYqhRCAGNOWG7Ak85_awF4Xv"
|
|
|
| if not os.path.exists(os.path.join(MODEL_DIR, "fold_0")):
|
| print("β¬ Downloading nnU-Net model from Google Drive ...")
|
| gdown.download_folder(FOLDER_URL, output=MODEL_DIR, quiet=False, use_cookies=False)
|
| print("β
Model downloaded.")
|
| else:
|
| print("β
Model already cached, skipping download.")
|
|
|
|
|
|
|
|
|
| print("π§ Initializing nnU-Net predictor ...")
|
| predictor = nnUNetPredictor(
|
| model_training_output_dir=MODEL_DIR,
|
| use_folds=[0, 1, 2, 3, 4],
|
| checkpoint_name="checkpoint_final.pth",
|
| device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| )
|
| predictor.initialize_from_trained_model_folder()
|
| print("β
Predictor ready.")
|
|
|
|
|
|
|
|
|
| def run_inference(nii_file):
|
|
|
| with tempfile.TemporaryDirectory() as tmpdir:
|
| input_path = os.path.join(tmpdir, "input.nii.gz")
|
| nii_file.save(input_path)
|
|
|
|
|
| output_dir = os.path.join(tmpdir, "output")
|
| os.makedirs(output_dir, exist_ok=True)
|
|
|
|
|
| predictor.predict_from_files(
|
| [input_path],
|
| output_dir=output_dir,
|
| save_probabilities=False
|
| )
|
|
|
|
|
| output_files = [f for f in os.listdir(output_dir) if f.endswith(".nii.gz")]
|
| if not output_files:
|
| raise RuntimeError("Prediction failed: No output NIfTI file found.")
|
|
|
| result_path = os.path.join(output_dir, output_files[0])
|
|
|
|
|
| img = nib.load(input_path).get_fdata()
|
| seg = nib.load(result_path).get_fdata()
|
|
|
|
|
| mid_slice = img.shape[2] // 2
|
| overlay = np.stack([
|
| img[:, :, mid_slice] / np.max(img),
|
| seg[:, :, mid_slice] / np.max(seg) if np.max(seg) > 0 else np.zeros_like(seg[:, :, mid_slice]),
|
| np.zeros_like(seg[:, :, mid_slice])
|
| ], axis=-1)
|
|
|
| return (overlay, result_path)
|
|
|
|
|
|
|
|
|
| title = "π§ Physics-Informed nnU-Net (Fisher PDE) for Glioblastoma MRI Segmentation"
|
| description = """
|
| Upload a **.nii** or **.nii.gz** MRI volume to run inference using the Physics-Informed nnU-Net model.
|
| The model integrates a Fisher diffusion-reaction equation for enhanced tumor boundary accuracy.
|
| """
|
|
|
| iface = gr.Interface(
|
| fn=run_inference,
|
| inputs=gr.File(label="Upload MRI NIfTI (.nii / .nii.gz)"),
|
| outputs=[
|
| gr.Image(label="Segmentation Overlay (mid-slice)"),
|
| gr.File(label="Download Full 3D Segmentation (.nii.gz)")
|
| ],
|
| title=title,
|
| description=description,
|
| allow_flagging="never"
|
| )
|
|
|
| if __name__ == "__main__":
|
| iface.launch()
|
|
|