CoolFace
Apppublic

SDLC-Corp/Medical-Imaging-Brain-tumor-analysis

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes
App README

<div align="center">

🧠 Brain Tumor Detection β€” SDLC Corp

![PyTorch](https://pytorch.org/) ![ONNX](https://onnxruntime.ai/docs/tutorials/web/) ![Gradio](https://gradio.app/) ![HF Spaces-yellow?style=for-the-badge)](https://huggingface.co/spaces) ![License](#-credits--licenses)

An SDLC Corp deep-learning web app that classifies brain MRI scans into four categories (glioma Β· meningioma Β· no-tumor Β· pituitary). Two models run entirely in the browser via ONNX Runtime Web β€” a ViT for the prediction (~97% on a held-out test set) and a ResNet50 for grad-free explainability β€” deployable as a free Hugging Face Static Space.

</div>


⚠️ Medical Disclaimer

This tool is for educational and research purposes only. It is not a substitute for professional medical diagnosis. Always consult a qualified radiologist or medical professional for clinical decisions.

πŸ“Œ Table of Contents


πŸ”¬ About the Project

Brain tumors are among the most critical conditions in medicine β€” accurate classification helps guide treatment decisions. This SDLC Corp project packages a fine-tuned ResNet50 MRI classifier into a modern, privacy-preserving web app that runs the model entirely in the user's browser (no server, no upload) and layers on real explainability and reliability tooling.

What this project covers:

  • β€”Exporting a PyTorch ResNet50 to ONNX (fp16) for in-browser inference via ONNX Runtime Web
  • β€”Class Activation Mapping β€” instant, grad-free, per-class explainability heatmaps
  • β€”Test-time augmentation, predictive-entropy uncertainty, and embedding-based out-of-distribution detection
  • β€”Content-based retrieval of the most similar reference scans
  • β€”One-command deployment to a free Hugging Face Static Space

βš™οΈ How It Works

User selects an MRI Scan (.jpg / .png)   ← stays in the browser
              β”‚
              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό                             β–Ό                                β”‚
   ViT preprocessing                ResNet preprocessing                     β”‚
   (resize 224, norm [-1,1])        (resize 256 β†’ crop 224 β†’ ImageNet)       β”‚
              β–Ό                             β–Ό                                β”‚
   ViT-base/16 (ONNX fp16)          ResNet50 (ONNX fp16, 2 outputs)          β”‚
   β†’ logits β†’ softmax               β†’ logits + last-conv feature maps        β”‚
              β”‚                             β”‚                                β”‚
              β–Ό                             β–Ό                                β–Ό
   Prediction + confidence     Grad-free Class Activation Map     GAP embedding β†’
   bars + uncertainty          (per-class, instant)               OOD + retrieval
              β”‚
              β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Glioma  β”‚ Meningioma β”‚ No-tumor β”‚ Pituitary  β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ§ͺ Advanced ML features (all in-browser)

Beyond a single forward pass, the app runs a small suite of real inference-time ML techniques β€” entirely client-side, with negligible extra download:

FeatureWhat it doesHow
Class Activation MappingInstant, per-class "where did the model look" heatmapGrad-free CAM: the ONNX model emits a 2nd output (last-conv feature maps); CAM_c = Ξ£_k W[c,k]Β·A_k with the classifier weights (cam_weights.json)
Test-Time AugmentationMore robust prediction by self-ensemblingAverages softmax over the original + horizontal + vertical flips; reports cross-view agreement
Uncertainty quantificationA certainty meter + low-confidence flagNormalized predictive entropy of the class distribution (+ TTA view agreement)
Out-of-distribution detectionWarns when the input isn't a brain MRICompares the image's 2048-d feature embedding to the reference MRIs; flags when max cosine similarity < a calibrated threshold (advanced.json)
Similar-scan retrievalShows the nearest reference scans (content-based image retrieval)Pools conv features to a 2048-d embedding; cosine-kNN against precomputed gallery embeddings (reference.json)
Why OOD matters here: softmax is overconfident on garbage β€” feed the app pure noise and it will predict a tumor class at ~100% "confidence". The embedding-based OOD check catches exactly this case and warns the user, which softmax confidence alone never would.

These assets are produced by compute_stats.py (run after export_onnx.py).


πŸ“Š Classes & data

The classifier predicts four categories of T1-weighted brain MRI:

ClassDescription
πŸ”΄ GliomaArises from glial cells; most common & often the most aggressive
🟑 MeningiomaGrows on the membranes around the brain; often benign
🟒 No tumorNo tumor signature detected
🟠 PituitaryForms on the pituitary gland at the base of the brain; usually benign

The underlying model weights were fine-tuned on a public Brain Tumor MRI image-classification dataset (the four-class glioma / meningioma / no-tumor / pituitary set). See Credits & Licenses for provenance.

⚠️ SDLC Corp has not independently re-benchmarked these third-party weights; accuracy on new data is not claimed here (see Model Performance).

πŸ—οΈ Model Architecture

The app runs two complementary models in the browser, each doing what it's best at:

                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  MRI ─┬─ resize 224 ────►  ViT-base/16   (higher accuracy)         β”‚
       β”‚  norm [-1,1]     β”‚  β†’ prediction Β· confidence Β· uncertaintyβ”‚  ← displayed
       β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       └─ resize 256 ─────►  ResNet50  (GAP β†’ Linear head)           β”‚
          crop 224        β”‚  β†’ CAM heatmap (grad-free)               β”‚  ← explain
          ImageNet norm   β”‚  β†’ 2048-d embedding β†’ OOD + retrieval    β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
ModelSource (Hugging Face Hub)Role
ViT`amjadfqs/vit-base-patch16-224-in21k-finetuned-brain-tumor`Prediction (β‰ˆ97% held-out)
ResNet50`Alia-Mohammed/resnet-50-finetuned-brain-tumor`CAM heatmap + embeddings

The ResNet is kept specifically because its global-average-pool β†’ Linear head makes grad-free CAM possible (a ViT has no such head). Both are exported to ONNX float16 (export_onnx.py): ResNet 47 MB, ViT 172 MB β€” parity with their PyTorch sources ~1e-4 / 1e-6 (verify_pipeline.py). Each falls back to fp32 if a browser can't run fp16 in WASM.


πŸ“ˆ Model Performance

Measured with benchmark.py / benchmark_ensemble.py on a held-out test set of 1,311 labelled MRIs (the Kaggle "Brain Tumor MRI" Testing split; label order matches the models).

ModelAccuracyMacro-F1Glioma recall
ResNet5085.96%0.8490.713
ViT (deployed predictor)97.10%0.9700.963
ResNet+ViT average96.87%0.9670.950

The app therefore uses the ViT for prediction and the ResNet50 for the CAM heatmap + feature embeddings (OOD / retrieval).

ViT per-class F1 (deployed model): glioma 0.967, meningioma 0.948, notumor 0.985, pituitary 0.980 β€” and glioma recall 0.963 (vs the ResNet's 0.713). Run python benchmark_ensemble.py for the full breakdown.

Read this honestly:

  • β€”Averaging the two models is slightly worse than the ViT alone β€” the ResNet (86%) is too weak to help, so a naive ensemble drags the ViT down. The real win was switching the predictor to the ViT (+11 points; glioma recall 0.71 β†’ 0.96).
  • β€”This is in-distribution generalization; it assumes the checkpoints trained on the Training split and did not see this Testing split. If they overlapped, 97% is optimistic, and real-world accuracy on other scanners/institutions is lower.
  • β€”The deployed fp16 ONNX models match their PyTorch sources (parity ~1e-4 / 1e-6).
  • β€”Still not a medical device β€” even at 97% test accuracy, ~1 in 30 is wrong.

πŸ“ Project Structure

BRAIN TUMOR DETECTION [END 2 END]/
β”‚
β”‚  ── Static Space (deployed, in-browser) ──────────────────────────
β”œβ”€β”€ index.html                              # Space entry point (sdk: static)
β”œβ”€β”€ style.css                               # UI styles
β”œβ”€β”€ app.js                                  # onnxruntime-web inference + CAM + TTA + uncertainty + OOD + retrieval
β”œβ”€β”€ cam_weights.json                        # classifier weights for in-browser CAM (generated)
β”œβ”€β”€ reference.json                          # gallery feature embeddings for kNN retrieval (generated)
β”œβ”€β”€ advanced.json                           # OOD threshold + uncertainty config (generated)
β”œβ”€β”€ labels.json                             # labels + preprocessing config (generated)
β”œβ”€β”€ πŸ“‚ model/
β”‚   β”œβ”€β”€ vit.fp16.onnx                       # prediction model, ~172 MB  (git-lfs)
β”‚   β”œβ”€β”€ vit.onnx                            # fp32 fallback, ~343 MB     (git-lfs)
β”‚   β”œβ”€β”€ bt_resnet50.fp16.onnx               # CAM/embedding model, ~47 MB (git-lfs)
β”‚   └── bt_resnet50.onnx                    # fp32 fallback, ~94 MB      (git-lfs)
β”œβ”€β”€ πŸ“‚ examples/                            # example MRIs shown in the UI
β”‚
β”‚  ── Tooling & PyTorch reference ──────────────────────────────────
β”œβ”€β”€ export_onnx.py                          # PyTorch β†’ ONNX (fp32 + fp16) + labels.json + cam_weights.json
β”œβ”€β”€ compute_stats.py                        # gallery embeddings + OOD threshold (reference.json, advanced.json)
β”œβ”€β”€ benchmark.py                            # accuracy/F1/confusion matrix on a labelled held-out test set
β”œβ”€β”€ benchmark_ensemble.py                   # compares ResNet vs ViT vs ensemble on the test set
β”œβ”€β”€ verify_pipeline.py                      # checks browser preprocessing == PyTorch
β”œβ”€β”€ app_gradio.py                           # full Gradio app w/ real Grad-CAM (local)
β”œβ”€β”€ πŸ“‚ src/                                  # config Β· model Β· inference Β· gradcam
β”œβ”€β”€ πŸ“‚ Brain-Tumor-Test-Images/             # source images copied into examples/
β”‚
β”œβ”€β”€ requirements.txt                        # deps for the Gradio reference app
β”œβ”€β”€ requirements-export.txt                 # deps for export_onnx.py (one-time)
β”œβ”€β”€ .gitattributes                          # git-lfs rules for *.onnx
β”œβ”€β”€ .gitignore
└── README.md                               # you are here

πŸš€ Getting Started

1. Get the repository

bash
git clone <your-sdlc-corp-repo-url>
cd brain-tumor-detection

2. Set up environment

bash
python -m venv venv
source venv/bin/activate        # Linux / macOS
venv\Scripts\activate           # Windows

pip install -r requirements.txt

This project ships two front-ends that share the same model:

Front-endFileRuns whereDeploys to
Static web app (in-browser ONNX)index.html + app.jsThe visitor's browser (WebAssembly)Hugging Face _Static_ Space β€” free
Gradio app (reference / local)app_gradio.pyPython + PyTorch, with real Grad-CAMLocal, or a paid HF Gradio Space

Option A β€” Run the static web app locally

First export the model to ONNX (one-time; needs the export deps):

bash
pip install -r requirements-export.txt
python export_onnx.py          # downloads weights, writes model/*.onnx + labels.json + cam_weights.json
python compute_stats.py        # writes reference.json + advanced.json (embeddings + OOD threshold)

Then serve the folder as static files (any static server works):

bash
python -m http.server 8000
# open http://localhost:8000

Upload an MRI scan β†’ you get a prediction, per-class confidence bars, and an instant Class Activation Map (click any class to see where the model looks for it) β€” all computed in the browser in ~1 second.

Option B β€” Run the full Gradio app (real Grad-CAM)

bash
pip install -r requirements.txt
python app_gradio.py           # opens http://127.0.0.1:7860

Weights (bt_resnet50_model.pt) auto-download from Google Drive on first run. Override with the BT_MODEL_URL / BT_GDRIVE_ID environment variables.


☁️ Deploy to Hugging Face Spaces (free Static Space)

On the free plan, HF Spaces only offers Static Spaces (Gradio/Docker require PRO). This repo targets exactly that: the YAML block at the top of this README sets sdk: static, and the models run in the browser β€” no server needed.

This repo is already built and committed (git + LFS initialised, fp16 models tracked, main branch). To deploy, just create a Static Space and push:

bash
# 1. Create a new Space β†’ SDK: Static β†’ https://huggingface.co/new-space
# 2. Add it as a remote and push (LFS uploads the fp16 .onnx models):
git remote add space https://huggingface.co/spaces/<your-username>/<space-name>
git push space main

HF then serves index.html at the Space URL; the browser fetches the two fp16 ONNX models and runs inference locally. Because everything is static, the Space is free and always-on (no cold starts).

Sizes: the fp16 models (~172 MB ViT + ~47 MB ResNet β‰ˆ 220 MB) download to each visitor once, then are cached. The fp32 fallbacks are .gitignored to keep the repo lean; add them back (edit .gitignore) for older browsers that can't run fp16 in WASM.

Rebuilding the assets from scratch (optional)

The .onnx models and JSON assets are already committed. To regenerate them (e.g. after changing models):

bash
pip install -r requirements-export.txt
python export_onnx.py       # ViT + ResNet β†’ ONNX (fp16 + fp32) + labels.json + cam_weights.json
python compute_stats.py     # reference.json + advanced.json (embeddings + OOD threshold)
python benchmark.py         # (optional) accuracy on a held-out test set

πŸ–₯️ App Preview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  1 Β· Choose an MRI scan       β”‚  2 Β· Result                       β”‚
β”‚                               β”‚                                   β”‚
β”‚   [ Click to upload / drag ]  β”‚   🟑  Meningioma                  β”‚
β”‚                               β”‚   Confidence: 35.7%               β”‚
β”‚   Or try an example:          β”‚                                   β”‚
β”‚   [β–ͺ][β–ͺ][β–ͺ][β–ͺ][β–ͺ]             β”‚   Meningioma  β–“β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘  35.7%    β”‚
β”‚                               β”‚   Glioma      β–“β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘  25.7%    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚   No tumor    β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  22.1%    β”‚
β”‚   β”‚  Input  β”‚   CAM   β”‚       β”‚   Pituitary   β–“β–“β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  16.5%    β”‚
β”‚   β”‚  (MRI)  β”‚(heatmap)β”‚       β”‚   ↑ click a class to switch CAM    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚   [ Analyze ]   opacity β–“β–“β–“β–‘β–‘      β”‚
β”‚                               β”‚   ⚠️ Educational use only.        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       Everything runs in the browser β€” the image never leaves the device.

πŸ› οΈ Tech Stack

LayerTechnology
Deep LearningPyTorch Β· πŸ€— Transformers Β· Torchvision
ModelResNet50 (transfer learning, from HF Hub)
In-browser inferenceONNX Runtime Web (WASM) Β· fp16 ONNX
Static frontendHTML5 Β· CSS3 Β· vanilla JS Β· <canvas> preprocessing
ExplainabilityClass Activation Mapping (browser, grad-free) Β· Grad-CAM (Gradio app)
Advanced inferenceTest-time augmentation Β· entropy uncertainty Β· embedding OOD detection Β· kNN retrieval
Reference appGradio
DeploymentHugging Face Static Space (free)
Export toolingtorch.onnx Β· onnxconverter-common (fp16)

πŸ“œ Credits & Licenses

This application β€” the in-browser inference pipeline, Class Activation Mapping, test-time augmentation, uncertainty/OOD tooling, retrieval, UI, and export/verification scripts β€” is Β© 2026 SDLC Corp, released under the Apache License 2.0.

It builds on the following third-party components, used under their licenses (this section serves as the attribution NOTICE required by Apache-2.0 Β§4):

ComponentRoleLicense
`amjadfqs/vit-base-patch16-224-in21k-finetuned-brain-tumor`Prediction model weights (ViT)Apache-2.0
`Alia-Mohammed/resnet-50-finetuned-brain-tumor`Explainability model weights (ResNet50)Apache-2.0
`google/vit-base-patch16-224-in21k` Β· `microsoft/resnet-50`BackbonesApache-2.0
ONNX Runtime Web Β· PyTorch Β· πŸ€— Transformers Β· GradioTooling / runtimeApache-2.0 / BSD / MIT
The model weights are third-party pretrained artifacts used under the Apache-2.0 license; SDLC Corp does not claim to have trained them and has not independently validated them for clinical use.

Further reading:


<div align="center">

Β© 2026 SDLC Corp Β· For research &amp; educational use only β€” not a medical device.

</div>