_____ _ __ ______ _ __ _
/ ___/__________(_)___ / /_ / ____/___ ____ _____ (_) /_(_)___ ____
\__ \/ ___/ ___/ / __ \/ __/_____/ / / __ \/ __ `/ __ \/ / __/ / __ \/ __ \
___/ / /__/ / / / /_/ / /_/_____/ /___/ /_/ / /_/ / / / / / /_/ / /_/ / / / /
/____/\___/_/ /_/ .___/\__/ \____/\____/\__, /_/ /_/_/\__/_/\____/_/ /_/
/_/ /____/
Depression. Anxiety. Stress. โ three invisible forces that shape lives.
This project reads them from the strokes of a pen.
EmotionDetectionUsingHandwriting is a full machine learning pipeline that detects emotional states from online handwriting signals captured on digital tablets. Pen trajectory data โ coordinates, pressure, velocity, tilt โ gets rendered into grayscale images and fed into a CNN that classifies the writer's emotional state.
It uses the EMOTHAW dataset (129 subjects, 7 handwriting tasks each) and labels derived from the DASS-21 (Depression Anxiety Stress Scales) questionnaire.
.svc file โโโถ parse pen data โโโถ render trajectory โโโถ CNN โโโถ emotion
๐ Web Application:
https://script-cognition.streamlit.app/
โ ๏ธ Deployment Notice
This Streamlit demo is intended for interface visualization and workflow demonstration only.
Due to deployment constraints (model size and training requirements), the hosted version does not include fully trained models.For accurate predictions and complete functionality, please run the application locally after training the models as described below.
| Feature | Detail | |
|---|---|---|
| ๐ง | Dual CNN Architectures | EmotionCNN (2.7M params) ยท ResNet18 transfer learning (11.2M params) |
| ๐ฏ | Three Emotion Dimensions | Depression ยท Anxiety ยท Stress โ train each independently |
| ๐ | DASS-21 Labels | Binary (Low / High) or full 5-class severity |
| ๐ฌ | 29+ Handwriting Features | Velocity, pressure, curvature, stroke count, pen-lift frequency |
| ๐ | Streamlit Web App | Upload .svc files ยท switch emotions ยท live trajectory viz |
| ๐ฅ๏ธ | Powerful CLI | Train ยท predict ยท visualize ยท extract โ all from the terminal |
| โก | GPU Ready | CUDA support out of the box |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ EMOTHAW Dataset โ
โ โ
โ Subjects โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 129 โ
โ Tasks/user โโโโโโโโโโโโโโโโโโโโ 7 โ
โ Samples โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 900+ โ
โ HW Features โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 29+ โ
โ Emotions โโโโโโโโโโโโโโ 3 โ
โ โ
โ Format: .svc โ X, Y, timestamp, pressure, โ
โ pen status, azimuth, altitude โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Emotion targets (binary Low / High per DASS-21 thresholds):
- ๐ฃ Depression โ Normal โ Extremely Severe
- ๐ต Anxiety โ Normal โ Extremely Severe
- ๐ฉท Stress โ Normal โ Extremely Severe
EmotionDetectionUsingHandwriting/
โ
โโโ โ๏ธ config.py central configuration
โโโ ๐ main.py unified CLI entry point
โโโ ๐ app.py Streamlit web interface
โโโ ๐ run_app.py web app launcher helper
โโโ ๐ requirements.txt
โ
โโโ ๐ preprocessing/
โ โโโ svc_parser.py .svc โ NumPy arrays
โ
โโโ ๐ data/
โ โโโ label_loader.py DASS scores โ class labels
โ โโโ dataset.py PyTorch Dataset + DataLoader
โ
โโโ ๐ features/
โ โโโ image_generator.py trajectories โ images
โ โโโ signal_features.py 29+ handwriting features
โ
โโโ ๐ models/
โ โโโ cnn_model.py EmotionCNN + EmotionResNet
โ
โโโ ๐ training/
โ โโโ train_cnn.py training loop + early stopping
โ
โโโ ๐ evaluation/
โ โโโ evaluate.py metrics, confusion matrix, plots
โ
โโโ ๐ inference/
โ โโโ predict.py run inference on new samples
โ
โโโ ๐ utils/
โ โโโ visualization.py trajectory & dataset plots
โ
โโโ ๐ outputs/
โโโ models/ saved checkpoints (.pth)
โโโ plots/ generated figures
โโโ image_cache/ cached trajectory images
- Python 3.10+
- EMOTHAW dataset at
../archive/DataEmothaw/ - CUDA (optional, for GPU acceleration)
# Clone the repo
git clone https://github.com/kshitiz-arc/EmotionDetectionUsingHandwriting.git
cd EmotionDetectionUsingHandwriting
# Install dependencies
pip install -r requirements.txtExpected dataset layout:
../archive/DataEmothaw/
โโโ DASS_scores.xls
โโโ user00001/
โโโ user00002/
โโโ ...
# Single emotion
python main.py train --model cnn --emotion anxiety
python main.py train --model cnn --emotion depression
python main.py train --model cnn --emotion stress
# All three in one shot
python main.py train_all --model cnn
# Custom hyperparams
python main.py train --model resnet --emotion anxiety \
--epochs 50 --batch_size 32 --lr 0.0001Checkpoints save to outputs/models/ as best_cnn_anxiety.pth, etc.
python run_app.py
# or
streamlit run app.pyThe app lets you switch emotion targets, upload .svc files, see confidence scores, and explore dataset statistics โ all without touching the terminal again.
python main.py predict --svc_path "path/to/handwriting.svc" --emotion anxietyโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
HANDWRITING EMOTION PREDICTION
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Input file : u00001s00001_hw00001.svc
Data points : 1474
Dimension : Anxiety
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
PREDICTED : LOW
CONFIDENCE : 84.12%
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Low โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 0.8412
High โโโโ 0.1588
python main.py visualize --statistics # class distribution
python main.py visualize --trajectory 1 # specific user's trajectory
python main.py visualize --all # everythingpython main.py extract --svc_path file.svc # single file
python main.py extract --dataset # full datasetfrom handwriting_emotion_detection import (
load_all_svc_files, load_labels, get_dataloaders,
EmotionCNN, extract_signal_features, plot_trajectory
)
samples = load_all_svc_files(DATASET_ROOT)
labels = load_labels(DASS_SCORES_PATH, target_emotion="anxiety")
train_loader, val_loader, test_loader = get_dataloaders(samples, labels)
model = EmotionCNN(num_classes=2)
features = extract_signal_features(samples[0]["data"])Input (224ร224)
โ
โผ
Conv Block ร4 (BatchNorm + ReLU + MaxPool + Dropout)
โ
โผ
Fully Connected โ Softmax โ [Low, High]
Parameters : ~2.7M
Best for : small datasets, fast iteration
Input (224ร224)
โ
โผ
ResNet18 backbone (pretrained on ImageNet)
โ
โผ
Fine-tuned FC head โ Softmax โ [Low, High]
Parameters : ~11.2M
Best for : maximum accuracy, transfer learning
Training setup โ Adam optimizer ยท ReduceLROnPlateau scheduler ยท Cross-Entropy with class weights ยท Early stopping ยท 70 / 15 / 15 train/val/test split
All tunable params live in config.py:
| Parameter | Default | Description |
|---|---|---|
TARGET_EMOTION |
"anxiety" |
depression ยท anxiety ยท stress |
USE_BINARY |
True |
True = Low/High ยท False = 5-class |
IMAGE_SIZE |
224 |
Trajectory render resolution (px) |
BATCH_SIZE |
16 |
Training batch size |
NUM_EPOCHS |
30 |
Max training epochs |
LEARNING_RATE |
1e-4 |
Initial Adam LR |
EARLY_STOPPING_PATIENCE |
7 |
Patience before stopping |
| Problem | Fix |
|---|---|
No trained model found |
Run python main.py train --model cnn --emotion anxiety first |
Dataset not found |
Check config.py paths, ensure DASS_scores.xls exists |
streamlit: not found |
pip install streamlit |
| Out of GPU memory | Lower BATCH_SIZE in config.py or switch to CPU |
| Poor accuracy | More epochs ยท lower LR ยท switch to --model resnet |
git checkout -b feature/your-idea
# make changes, write tests, update docs
git commit -m "feat: your idea"
git push origin feature/your-idea
# open a Pull RequestPlease follow PEP 8 and add docstrings to any new functions.
APACHE 2.0 โ see LICENSE for details.
Built by kshitiz-arc
The pen is mightier than the word โ and now, smarter too.