Recognizing handwritten digits and characters using deep learning — progressing from single digit classification all the way to full word recognition. This project builds and trains CNN and CRNN (Convolutional Recurrent Neural Network) models, covering three levels of complexity:
MNIST digits → EMNIST letters A–Z → Full word recognition via CRNN + CTC Loss
- ✅ CNN on MNIST — ~99% test accuracy on digits 0–9
- ✅ CNN on EMNIST — ~95% test accuracy on letters A–Z
- ✅ CRNN architecture — ready for full word/sentence recognition using CTC decoding
| Dataset | Samples | Classes | Description |
|---|---|---|---|
| MNIST | 70,000 | 10 | Handwritten digits 0–9 |
| EMNIST Letters | 145,600 | 26 | Handwritten letters A–Z |
| IAM / IIIT-5K | Variable | 80+ | Full word images (for CRNN) |
| Model | Dataset | Test Accuracy |
|---|---|---|
| CNN | MNIST Digits | ~99% |
| CNN | EMNIST Letters | ~95% |
| CRNN | Word images | CTC decoded |
Train accuracy reaches ~99.4% with validation closely tracking — no significant overfitting.
Letters are harder than digits — the model converges to ~95% accuracy after 10 epochs.
Input (28×28×1)
↓
Conv2D(32, 3×3) + ReLU
↓
MaxPooling(2×2)
↓
Conv2D(64, 3×3) + ReLU
↓
MaxPooling(2×2)
↓
Conv2D(64 / 128, 3×3) + ReLU
↓
Flatten
↓
Dense(128 / 256) + ReLU
↓
Dropout(0.5)
↓
Dense(10 / 27) + Softmax
Input (32×128×1)
↓
4× Conv2D Blocks (32 → 64 → 128 → 256) + MaxPooling
↓
Reshape → (time_steps, features)
↓
Dense(256) + ReLU
↓
Bidirectional LSTM(128) × 2
↓
Dense(num_classes + 1) + Softmax ← +1 for CTC blank token
↓
CTC Loss Decoding → predicted text
Why CRNN for words?
- CNN extracts local visual features from the image
- BiLSTM captures sequential character dependencies left-to-right and right-to-left
- CTC Loss handles variable-length output without needing exact character position alignment
Raw Image → Normalize (÷255) → Reshape → Model → Softmax / CTC Decode → Prediction
| Step | MNIST | EMNIST | CRNN |
|---|---|---|---|
| Normalization | ÷ 255 | ÷ 255 | ÷ 255 |
| Reshape | (28,28,1) | (28,28,1) | (32,128,1) |
| Transpose fix | ✗ | ✓ (TFDS rotation) | — |
| Label encoding | 0–9 (int) | 1–26 (int) | char → index |
CodeAlpha-Handwritten-Character-Recognition/
│
├── train.py # Train CNN on MNIST digits
├── predict.py # Run prediction on a single image
├── emnist_train.py # Train CNN on EMNIST letters (A–Z)
├── crnn_model.py # CRNN architecture with CTC loss
├── requirements.txt # Python dependencies
├── README.md # Project documentation
│
├── saved_model/
│ ├── mnist_cnn_model.h5 # Saved MNIST model
│ └── emnist_letters_model.h5 # Saved EMNIST model
│
├── training_history.png # MNIST accuracy/loss curves
├── emnist_training_history.png # EMNIST accuracy/loss curves
├── sample_predictions.png # First 10 MNIST predictions
└── single_prediction.png # Single image prediction chart
# 1. Clone the repository
git clone https://github.com/ronakrajput8882/CodeAlpha-Handwritten-Character-Recognition.git
cd CodeAlpha-Handwritten-Character-Recognition
# 2. Install dependencies
pip install -r requirements.txt
# 3. Train on MNIST digits (downloads dataset automatically)
python train.py
# 4. Run a prediction on a random test image
python predict.py
# 5. Train on EMNIST letters A–Z
python emnist_train.py
# 6. Explore the CRNN architecture for word recognition
python crnn_model.pytensorflow>=2.10.0
numpy>=1.21.0
matplotlib>=3.5.0
tensorflow-datasets
Install all at once:
pip install -r requirements.txt
⚠️ Note: Theemnistpip package has a broken download URL. This project usestensorflow-datasetsinstead, which downloads EMNIST reliably from Google's servers.
- 🔢 MNIST is near-solved — simple 3-block CNN reaches 99%+ with dropout regularization
- 🔤 EMNIST letters are harder — 26 classes with more visual ambiguity (e.g., I vs l, O vs 0)
- 🔄 Transpose matters — TFDS stores EMNIST images rotated 90°; skipping the fix silently trains on sideways letters
- 📝 CTC Loss is key for words — it sums over all valid character-to-timestep alignments, so you don't need to label exact positions
- 🧠 BiLSTM beats LSTM — reading left-to-right and right-to-left captures context from both directions, critical for ambiguous strokes
| Tool | Use |
|---|---|
| Python 3.10+ | Core language |
| TensorFlow / Keras | Model building & training |
| TensorFlow Datasets | Reliable EMNIST data loading |
| NumPy | Array operations & preprocessing |
| Matplotlib | Training plots & prediction visualization |



