ChestSense / README.md
NoumanUsman's picture
Upload folder using huggingface_hub
52e8264 verified
|
Raw
History Blame Contribute Delete
10.3 kB
# Lung Cancer Classification API with Grad-CAM
A production-ready Flask REST API for classifying lung cancer types using DenseNet121 with Grad-CAM visualization. Validates medical images, provides explainable AI predictions, and returns base64-encoded visualizations.
## Features
- βœ… **DenseNet121 Classification**: 4-class lung cancer type prediction (Adenocarcinoma, Small Cell, Large Cell, Squamous Cell)
- βœ… **Grad-CAM Visualization**: Visual explanation of model predictions via heatmap overlays
- βœ… **CT Scan Validation**: Automatic rejection of non-medical (color) images
- βœ… **Dual Preprocessing**: Attempts both normalized and non-normalized preprocessing for robust predictions
- βœ… **REST API**: Flask with Swagger UI documentation
- βœ… **CORS Support**: Mobile and cross-origin requests enabled
- βœ… **Production Ready**: Gunicorn WSGI server, environment variables, Docker-compatible
- βœ… **JSON Responses**: Base64-encoded images for mobile integration
## Installation
### Local Development
```bash
# Clone the repository
git clone <repo-url>
cd Grad-Cam-Backend
# Create virtual environment
python3.11 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
```
### Docker (Optional)
```bash
docker build -t lung-cancer-api .
docker run -p 5001:5001 lung-cancer-api
```
## Usage
### Running Locally
```bash
# Development (debug mode enabled)
DEBUG=true python app.py
# Production (debug mode disabled)
python app.py
# Or use Gunicorn
gunicorn app:app --bind 0.0.0.0:5001
```
### Running Tests
Classify a single image using the command-line tool:
```bash
source .venv/bin/activate
python test.py /path/to/ct_scan.jpg
```
Example output:
```
============================================================
🩺 LUNG CANCER CLASSIFICATION - DenseNet121
============================================================
πŸ“„ Image: ct_scan.jpg
πŸ“ Size: (512, 512, 3)
πŸ” Running classification...
============================================================
πŸ“Š CLASSIFICATION RESULTS
============================================================
Adenocarcinoma (Class A) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 45.23%
Small Cell (Class B) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘ 72.15%
Large Cell (Class E) β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 12.50%
Squamous Cell (Class G) β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 8.12%
============================================================
πŸ₯ FINAL DIAGNOSIS
============================================================
Classification: Small Cell (Class B)
Confidence: 72.15%
============================================================
βœ… Result saved to 'classification_result.png'
```
### REST API
**Base URL**: `http://localhost:5001`
#### 1. Health Check
```bash
GET /health
```
Response: `{"status": "healthy", "model_loaded": true}`
#### 2. CT Scan Validation (No Classification)
```bash
POST /validate-ct
Content-Type: multipart/form-data
file: <image_file>
```
Response:
```json
{
"is_ct_scan": true,
"color_score": 4.5,
"message": "Valid CT scan - grayscale image detected"
}
```
#### 3. Full Analysis with Grad-CAM
```bash
POST /analyze
Content-Type: multipart/form-data
file: <image_file>
```
Response (on success):
```json
{
"success": true,
"prediction": "Small Cell (Class B)",
"confidence": 72.15,
"all_confidences": {
"Adenocarcinoma (Class A)": 45.23,
"Small Cell (Class B)": 72.15,
"Large Cell (Class E)": 12.50,
"Squamous Cell (Class G)": 8.12
},
"original_image": "base64_encoded_jpeg_string",
"heatmap_image": "base64_encoded_gradcam_heatmap"
}
```
### Swagger UI
Interactive API documentation available at: **http://localhost:5001/docs**
## Deployment
### Railway.app Deployment
1. **Create a Railway account** at https://railway.app
2. **Connect your GitHub repository**
- Go to Railway dashboard
- Click "New Project" β†’ "Deploy from GitHub repo"
- Select this repository
3. **Configure environment variables** in Railway dashboard:
```
DEBUG=False
PORT=5001
```
4. **Deploy**
- Railway automatically detects `Procfile` and deploys the app
- Your API will be available at `https://<your-project>.up.railway.app`
### Heroku Deployment (Legacy)
```bash
heroku create <app-name>
heroku config:set DEBUG=False
git push heroku main
```
## API Validation
### CT Scan Validation Threshold
- **Valid CT scans**: Color score < 6.0 (grayscale images)
- **Rejected**: Color score β‰₯ 6.0 (color photos, non-medical images)
Color score measures RGB channel variance:
- Pure grayscale: 0-2
- Real CT scans: 2-6
- Color photos: 7-100
### Confidence Threshold
- **Accepted**: Confidence β‰₯ 50%
- **Rejected**: Confidence < 50% (uncertain predictions)
## Configuration
### Environment Variables
Create a `.env` file (or set via environment):
```bash
# Flask settings
DEBUG=False # Set to True for development
PORT=5001 # Server port (defaults to 5001)
# Optional overrides
# MODEL_PATH=models/densenet_final_classification.pth
```
## Model Architecture
```
DenseNet121 (Feature Extractor)
↓
[2176 channels]
↓
Classifier:
- ReLU Activation
- Linear(2176 β†’ 4) [outputs class logits]
↓
Softmax Probabilities
↓
4-Class Output:
[Adenocarcinoma, Small Cell, Large Cell, Squamous Cell]
```
## Preprocessing Pipeline
The API uses **dual preprocessing** for robustness:
1. **Normalized**: ImageNet normalization (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
2. **Non-normalized**: Raw tensor scaling
Algorithm selects whichever produces higher max confidence, adapting to different training conditions.
## Grad-CAM Explanation
Grad-CAM (Gradient-weighted Class Activation Mapping) highlights regions the model focuses on:
- **Red/Hot regions**: Model focuses heavily (high confidence)
- **Blue/Cool regions**: Model has low attention (less relevant)
- **Alpha blending**: 0.4 transparency for visualization
Extracted from: `model.features.norm5` (last fully-connected layer before classifier)
## Error Handling
| Status | Error | Solution |
|--------|-------|----------|
| 400 | "No file uploaded" | Ensure multipart/form-data with 'file' field |
| 400 | "Invalid input: image does not appear to be a CT scan" | Use actual CT scan (grayscale medical image) |
| 400 | "Confidence too low" | Model uncertain; try another image |
| 500 | "Error processing image" | Check server logs; verify model file exists |
## File Structure
```
Grad-Cam-Backend/
β”œβ”€β”€ app.py # Main Flask application
β”œβ”€β”€ test.py # Command-line classification tool
β”œβ”€β”€ models/
β”‚ └── densenet_final_classification.pth # DenseNet weights
β”œβ”€β”€ requirements.txt # Python dependencies
β”œβ”€β”€ Procfile # Railway deployment config
β”œβ”€β”€ runtime.txt # Python version (3.11.14)
β”œβ”€β”€ .env.example # Example environment variables
β”œβ”€β”€ .gitignore # Git ignore patterns
└── README.md # This file
```
## Class Labels
| Index | Class | Description |
|-------|-------|-------------|
| 0 | Adenocarcinoma (Class A) | Most common; develops in glandular cells |
| 1 | Small Cell (Class B) | Aggressive; fast-growing variant |
| 2 | Large Cell (Class E) | Rare; large undifferentiated cells |
| 3 | Squamous Cell (Class G) | Develops in flat cells lining airways |
## Performance Tuning
### Increase Sensitivity
```python
CONFIDENCE_THRESHOLD = 0.3 # Lower from 0.5 to accept more predictions
# In app.py line ~180
```
### Adjust CT Validation
```python
is_valid = color_score < 8.0 # Raise from 6.0 if rejecting true CTs with color compression
# In app.py line ~157
```
## Troubleshooting
### Model fails to load
```
RuntimeError: Error(s) in loading state_dict for DenseNet:
Missing key(s) in state_dict: ...
```
**Solution**: Ensure `models/densenet_final_classification.pth` exists and matches architecture in `load_model()`.
### Port already in use
```bash
# Find process using port 5001
lsof -i :5001
# Kill the process
kill -9 <PID>
# Or use different port
PORT=5002 python app.py
```
### Module import errors
```bash
# Ensure all dependencies installed
pip install -r requirements.txt
# Verify virtual environment active
source .venv/bin/activate
```
## API Examples
### Python Client
```python
import requests
import base64
from PIL import Image
from io import BytesIO
API_URL = "http://localhost:5001"
# Upload and classify CT scan
with open("ct_scan.jpg", "rb") as f:
files = {"file": f}
response = requests.post(f"{API_URL}/analyze", files=files)
result = response.json()
print(f"Diagnosis: {result['prediction']}")
print(f"Confidence: {result['confidence']}%")
# Decode and view heatmap
heatmap_data = base64.b64decode(result['heatmap_image'])
heatmap_img = Image.open(BytesIO(heatmap_data))
heatmap_img.show()
```
### JavaScript/Flutter Client
```javascript
const formData = new FormData();
formData.append('file', imageFile);
const response = await fetch('http://localhost:5001/analyze', {
method: 'POST',
body: formData
});
const result = await response.json();
console.log(`Diagnosis: ${result.prediction}`);
console.log(`Confidence: ${result.confidence}%`);
// Display heatmap from base64
const img = new Image();
img.src = `data:image/jpeg;base64,${result.heatmap_image}`;
```
## Dependencies
- **Flask 3.0.0**: REST framework
- **Gunicorn 21.2.0**: WSGI server
- **PyTorch 2.1.0**: Deep learning
- **TorchVision 0.16.0**: Computer vision
- **OpenCV 4.8.1.78**: Image processing
- **Pillow 10.1.0**: Image I/O
- **NumPy 1.24.3**: Array operations
- **Flask-CORS 4.0.0**: Cross-origin support
- **Flasgger 0.9.7.1**: Swagger API docs
## License
Proprietary - Medical Research Use Only
## Support
For issues, email: support@lungcancerapi.com
---
**Last Updated**: March 8, 2026
**Version**: 1.0.0
**Status**: Production Ready βœ