A full-stack deep learning web app that classifies handwritten digits in real time. Draw a digit or upload an image — CNN predicts it instantly with full confidence breakdown.
📸 Screenshots • ✨ Features • ⚙️ How It Works • 🧠 Model • 🚀 Getting Started • 📁 Structure • 🛠️ Tech Stack • 🔬 Training
| Feature | Description |
|---|---|
| ⚡ Real-time Inference | Predict digits in under 50ms |
| ✏️ Drawing Canvas | Freehand drawing with adjustable brush size |
| 📤 Image Upload | Supports PNG, JPG, BMP formats |
| 📊 Confidence Breakdown | Full per-class probability scores for digits 0–9 |
| 🎨 Beautiful 2-Page UI | Home landing page + Studio workspace |
| 🧠 Advanced CNN | 99.55% test accuracy on MNIST test set |
🖊️ Step 1 — Input
You either draw a digit on the freehand canvas or upload an image file (PNG, JPG, BMP). Both paths feed into the same preprocessing pipeline.
🔧 Step 2 — Preprocessing
Raw input is messy — different sizes, positions, stroke widths. The pipeline cleans it all:
# Operation Purpose 1️⃣ Grayscale conversion Strip color, keep structure 2️⃣ Otsu thresholding Clean binary black & white image 3️⃣ Bounding box crop Remove empty space around digit 4️⃣ Padding Center the digit with breathing room 5️⃣ Resize to 28 × 28 Match exact MNIST training format 6️⃣ Normalize 0–255 → 0.0–1.0 Scale pixels for the neural network
🧠 Step 3 — CNN Inference
The clean 28×28 image passes through the trained CNN — two convolutional blocks extract visual features, then dense layers classify the digit. The model outputs 10 probability scores, one per class.
📊 Step 4 — Results
The app displays the predicted digit, confidence percentage, and a full probability bar chart for all 10 digit classes — so you see exactly how certain the model is.
🖊️ Draw on canvas 📤 Upload an image
↘ ↙
🔧 Grayscale → Threshold → Crop → Pad → 28×28 → Normalize
↓
🧠 Conv Block 1 → Conv Block 2 → Dense(256) → Softmax(10)
↓
📊 Predicted Digit · Confidence % · Class Probabilities
💡 Why preprocessing matters — The CNN was trained on clean, centered 28×28 MNIST digits. A digit drawn in the corner or at the wrong scale would confuse the model. The pipeline bridges that gap between real-world input and training data format — which is the key to 99.55% real-world accuracy.
Input (28 × 28 × 1)
│
▼
┌─────────────────────────────────┐
│ Conv2D(32, 3×3) ReLU │
│ Conv2D(32, 3×3) ReLU │ ← detects edges & basic strokes
│ MaxPooling2D │
│ Dropout(0.25) │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ Conv2D(64, 3×3) ReLU │
│ Conv2D(64, 3×3) ReLU │ ← learns curves & digit shapes
│ MaxPooling2D │
│ Dropout(0.25) │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ Flatten │
│ Dense(256) ReLU │ ← combines all learned features
│ Dropout(0.5) │
│ Dense(10) Softmax │ ← final class probabilities
└─────────────────────────────────┘
│
▼
Prediction (0 – 9)
| Hyperparameter | Value |
|---|---|
| Optimizer | Adam (lr = 1e-3) |
| Loss | Sparse Categorical Crossentropy |
| Augmentation | Rotation ±10°, Zoom ±10%, Shifts ±10% |
| Batch Size | 128 |
| Callbacks | ReduceLROnPlateau + EarlyStopping |
| Test Accuracy | 99.55% ✅ |
git clone https://github.com/huda-usman/handwritten-digit-recognition.git
cd handwritten-digit-recognitionpip install -r requirements.txtstreamlit run app.py🌐 Open http://localhost:8501 in your browser.
✅ No training needed — the pre-trained model (
model/mnist_cnn_v2_model.keras) is included!
handwritten-digit-recognition/
│
├── 📄 app.py # Main Streamlit app (Home + Studio)
├── 📄 requirements.txt # Python dependencies
├── 📄 README.md # This file
│
├── 📂 model/
│ └── mnist_cnn_v2_model.keras # Pre-trained CNN model (5.1 MB)
│
├── 📂 notebooks/
│ └── train_on_colab.ipynb # Google Colab GPU training notebook
│
└── 📂 assets/
├── 📂 screenshots/
│ ├── HomePage.png
│ ├── Studio.png
│ ├── Canvas.png
│ ├── Canvas2.png
│ └── Canvas3.png
└── 📂 samples/
├── 0.jpeg 1.jpeg 2.jpeg
├── 3.jpeg 4.jpeg 5.jpeg
├── 6.jpeg 7.png 8.jpeg
└── 9.jpeg
| Layer | Technology | Purpose |
|---|---|---|
| 🎨 Frontend | Streamlit + Custom CSS | Web UI & routing |
| ✏️ Drawing | streamlit-drawable-canvas | Freehand digit input |
| 🧠 ML Framework | TensorFlow 2.x / Keras | Model training & inference |
| 🖼️ Image Processing | OpenCV + Pillow | Preprocessing pipeline |
| 📊 Dataset | MNIST | 70k handwritten digit samples |
| ☁️ Training | Google Colab (T4 GPU) | Free GPU training |
The model is already trained and included. To retrain from scratch:
☁️ Option A — Google Colab (Recommended · Free GPU)
- Open
notebooks/train_on_colab.ipynbin Google Colab - Select Runtime → Change runtime type → T4 GPU
- Run all cells — takes ~5 minutes
- Download
mnist_cnn_v2_model.kerasand replace inmodel/
💻 Option B — Local Machine
python -c "from app import *; get_model()"This project is open-source under the MIT License — feel free to use, modify, and share.




