Diabetic Retinopathy Screening & Patient Management Platform
Copyright (c) 2024 Gaurav Singh Thakur, Niharika Raghunandan — All Rights Reserved. See LICENSE for usage restrictions.
I built RetinaGuard as a two-sided clinical web platform for automated diabetic retinopathy (DR) severity screening, longitudinal patient monitoring, and doctor–patient management. Patients upload retinal fundus images and track their eye health history; clinicians get a complete dashboard with high-risk alerts, severity trends across visits, and inline annotation tools. The five-level DR grading follows the International Clinical Diabetic Retinopathy Severity Scale.
The screening engine is an EfficientNet-B4 with Grad-CAM diagnostic focus mapping — when real weights are loaded it produces a colour overlay that highlights which retinal regions drove each severity grade, which I designed for clinical explainability rather than pure accuracy.
| Feature | Description |
|---|---|
| 5-Level DR Grading | Classifies retinal images as No DR / Mild / Moderate / Severe / Proliferative |
| Diagnostic Focus Map | Grad-CAM heatmap overlay identifying which retinal regions drive each severity grade |
| Patient Portal | Secure login, profile, scan upload, full history, clinical advice per result |
| Doctor Portal | Patient list, high-risk alerts, severity trend charts, inline notes per scan |
| Longitudinal Tracking | Severity trend charts across all visits for every patient |
| Doctor–Patient Assignment | Doctors are linked to specific patients; admins see all |
| Screening Confidence | Confidence percentage and per-grade probability distribution for each result |
| Role-Based Access | Three roles: patient, doctor, admin with separate views and permissions |
| Simulation Mode | Full app runs without trained weights — placeholder results for demonstration |
| Public Landing Page | Marketing-grade front page with feature overview and grading reference |
I used EfficientNet-B4 as the backbone, pretrained on ImageNet and fine-tuned end-to-end for five-class DR grading.
| Component | Detail |
|---|---|
| Backbone | EfficientNet-B4 (transfer learning) |
| Input resolution | 512 × 512 px |
| Preprocessing | CLAHE contrast enhancement + augmentation pipeline |
| Explainability | Gradient-weighted Class Activation Mapping (Grad-CAM) |
| Optimiser | AdamW |
| Scheduler | CosineAnnealingLR |
| Stopping | Early stopping (patience 12) — best checkpoint by validation QWK |
| Training stopped at | Epoch 39 |
| Dataset | APTOS 2019 (Kaggle Blindness Detection) |
All hyperparameters live in ml/config.py. The full training script is
ml/train.py and the Colab/Kaggle notebooks are in notebooks/.
Trained weights are distributed via the
Releases page rather than committed to git (to keep the repo
lightweight). Download retinoguard_best.pth and place it at
backend/weights/retinoguard_best.pth — the app switches from Simulation Mode
to real inference automatically on next restart.
If no checkpoint is present, the app runs in Simulation Mode (deterministic placeholder results) so the full UI is still usable. Simulated output carries no diagnostic validity.
I trained on APTOS 2019 and evaluated on a stratified held-out test set of 367 fundus images the model never saw during training.
| Metric | Value |
|---|---|
| Accuracy | 0.8174 |
| Quadratic Weighted Kappa | 0.8866 |
| Macro AUC (one-vs-rest) | 0.9389 |
| Weighted F1 | 0.8128 |
I picked the best checkpoint by validation QWK — the metric the DR-grading community actually uses. My validation and test QWK land almost on top of each other (0.8832 vs 0.8866), which tells me the model is genuinely learning the disease rather than memorizing the training set. Training early-stopped at epoch 39.
| Grade | Precision | Recall | F1 | AUC | Support |
|---|---|---|---|---|---|
| No DR | 0.962 | 0.983 | 0.973 | 0.998 | 181 |
| Mild DR | 0.645 | 0.540 | 0.588 | 0.934 | 37 |
| Moderate DR | 0.741 | 0.800 | 0.769 | 0.940 | 100 |
| Severe DR | 0.389 | 0.368 | 0.378 | 0.896 | 19 |
| Proliferative DR | 0.600 | 0.500 | 0.545 | 0.927 | 30 |
The model is strongest on No DR and Moderate DR. Severe DR is the weakest class, but it only has 19 test samples — I'm leaving the number visible rather than hiding it. The honest story is more useful than a cherry-picked one.
The full write-up — methodology, exact train/val/test split, and how to reproduce everything — is in docs/RESULTS.md.
| Component | Technology |
|---|---|
| Web framework | Flask 3.0 |
| Database ORM | Flask-SQLAlchemy + SQLite |
| Authentication | Flask-Login + Werkzeug password hashing |
| Image serving | Flask static/upload routes |
| Component | Technology |
|---|---|
| UI framework | Bootstrap 5.3 |
| Icons | Bootstrap Icons 1.11 |
| Charts | Chart.js 4.4 |
| Fonts | Inter (Google Fonts) |
RetinaGuard/
│
├── ml/ # Screening engine
│ ├── config.py # All hyperparameters and class definitions
│ ├── model.py # EfficientNet-B4 architecture & loader
│ ├── preprocessing.py # CLAHE + train/val transform pipelines
│ ├── predict.py # Inference engine + Grad-CAM overlay
│ ├── train.py # Full training script with early stopping
│ └── evaluate.py # Held-out evaluation & metrics export
│
├── backend/ # Flask application
│ ├── app.py # Application factory (blueprint registration)
│ ├── config.py # Flask config classes (dev / prod)
│ ├── database.py # SQLAlchemy + LoginManager instances
│ ├── models/
│ │ ├── user.py # Patient/Doctor/Admin user model
│ │ └── scan.py # Scan result & report model
│ └── routes/
│ ├── auth.py # Login, register, logout, landing page
│ ├── patients.py # Patient profile view & edit
│ ├── scans.py # Upload, inference, history, delete
│ ├── dashboard.py # Patient dashboard stats & trend API
│ └── doctor.py # Doctor portal — patient list, detail, notes
│
├── frontend/
│ ├── templates/ # Jinja2 HTML templates
│ └── static/
│ ├── css/style.css
│ └── js/
│ ├── main.js
│ ├── scan.js
│ └── charts.js
│
├── notebooks/ # Training notebooks (Colab & Kaggle)
│
├── docs/
│ ├── RESULTS.md # Full evaluation write-up
│ └── results/ # Confusion matrices, ROC curves, metrics JSON
│
├── tests/ # Pytest suite
│ ├── conftest.py
│ ├── test_auth.py
│ ├── test_scans.py
│ └── test_predict.py
│
├── uploads/ # Runtime image store — gitignored
├── backend/weights/ # Model checkpoint — gitignored
│ └── retinoguard_best.pth # Download from Releases and place here
│
├── .env.example # Environment variable template
├── run.py # Application entry point
├── setup_db.py # Database initialisation & demo seed
├── requirements.txt # Web app dependencies
├── requirements-ml.txt # ML training dependencies
└── LICENSE
- Python 3.10 or higher
- pip
- (Optional) CUDA-compatible GPU for faster inference
git clone https://github.com/Gaurav-0704/RetinaGuard.git
cd RetinaGuardpip install -r requirements.txtPyTorch note: installation varies by platform and CUDA version. Visit pytorch.org for the right command.
cp .env.example .envAt minimum, set a SECRET_KEY before running in any shared environment:
python -c "import secrets; print(secrets.token_hex(32))"Add the output to your .env file. If SECRET_KEY is not set, the app
generates an ephemeral key and logs a warning — sessions won't survive
restarts, which is fine for local dev but not for deployment.
# Create tables only
python setup_db.py
# Create tables + demo accounts (recommended for first run)
python setup_db.py --demoDemo accounts:
| Role | Password | |
|---|---|---|
| Patient | demo@retinoguard.com | demo1234 |
| Doctor | admin@retinoguard.com | admin1234 |
The database (retinoguard.db) is created automatically in the project root.
run.py also calls db.create_all() on startup, so the app is safe to launch
without running setup_db.py first — you just won't have demo data.
Download retinoguard_best.pth from the
Releases page and place it at:
backend/weights/retinoguard_best.pth
The app detects the file at startup and switches to live inference automatically.
python run.pyOpen http://127.0.0.1:5000 in your browser.
pip install pytest
pytest tests/ -vThe test suite runs against an in-memory SQLite database with mocked inference — no GPU, no trained weights, no uploaded images needed.
pip install -r requirements-ml.txt
python -m ml.train \
--images_dir path/to/images \
--csv_path path/to/labels.csvCSV format:
id_code,diagnosis
abc123,0
def456,2
diagnosis is an integer 0–4 (DR severity grade). The best checkpoint saves
automatically to backend/weights/retinoguard_best.pth.
| Grade | Name | Clinical Description |
|---|---|---|
| 0 | No DR | No visible signs. Annual screening recommended. |
| 1 | Mild DR | Microaneurysms only. Revisit in 9–12 months. |
| 2 | Moderate DR | More than microaneurysms but less than Severe. Ophthalmologist referral; revisit in 6 months. |
| 3 | Severe DR | Extensive haemorrhages, venous beading. Urgent specialist referral. |
| 4 | Proliferative DR | Neovascularisation present. Immediate ophthalmic intervention needed. |
| Variable | Default | Description |
|---|---|---|
SECRET_KEY |
ephemeral (warns at startup) | Flask session secret — set this before deploying |
DATABASE_URL |
sqlite:///retinoguard.db |
SQLAlchemy connection string |
RetinaGuard is a screening aid developed for educational and portfolio purposes. It is not a certified medical device and must not be used as a substitute for professional ophthalmic examination and diagnosis. All results must be reviewed and confirmed by a qualified healthcare professional. The authors accept no liability for clinical decisions based on this software.
This software is proprietary. Viewing is permitted; copying, distribution, modification, and commercial use are strictly prohibited without explicit written permission from both authors. See LICENSE for the full terms.
I built RetinaGuard as an extension of a diabetic retinopathy detection system Niharika and I developed together during our undergraduate research. This platform takes that shared academic foundation and extends it into a full-stack clinical screening application.
| Name | Role | |
|---|---|---|
| 🔬 | Gaurav Singh Thakur | Co-author · Full-stack development, screening engine, platform architecture |
| 🔬 | Niharika Raghunandan | Co-author · Original DR research, academic foundation, clinical knowledge |
GitHub: github.com/Gaurav-0704
Copyright (c) 2024 Gaurav Singh Thakur, Niharika Raghunandan. All Rights Reserved.


