An end-to-end ML image classification web app deployed on AWS β 100% Free Tier ($0/month)
Upload any image and our AI will tell you whether it's a cat π± or a dog πΆ β complete with confidence probabilities!
| Service | URL |
|---|---|
| Frontend | cat-vs-dog-frontend-235899055608.s3-website.eu-west-2.amazonaws.com |
| API Health | af9aiibt3m.execute-api.eu-west-2.amazonaws.com/health |
βββββββββββββββ ββββββββββββββββ βββββββββββββββ βββββββββββββ
β Browser ββββββββΆβ S3 Static β β API Gateway ββββββββΆβ Lambda β
β (Frontend) β β Website ββββββββΆβ (HTTP API) β β (Docker) β
βββββββββββββββ ββββββββββββββββ ββββββββββββββββ βββββββ¬ββββββ
β
ββββββββββββββββ ββββββββββββββββ β
β CloudWatch βββββββββ ECR ββββββββββββββ
β Alarms β β (Container) β
ββββββββ¬ββββββββ ββββββββββββββββ
β
ββββββββΌββββββββ
β SNS Email β
β Alerts β
ββββββββββββββββ
Frontend β Static HTML/CSS/JS hosted on S3 (drag-and-drop image upload with light/dark mode)
Backend β Lambda (container image from ECR) behind API Gateway, running ONNX inference
Monitoring β CloudWatch alarms β SNS email alerts + AWS Budget guard
CI/CD β GitHub Actions builds Docker, pushes to ECR, deploys frontend to S3
- Image Preprocessing β Smart resize (128Γ128), CLAHE contrast enhancement, bilateral filtering
- Feature Extraction β 10,221 handcrafted features from 8 families:
- HOG (Histogram of Oriented Gradients) β fine + coarse
- LBP (Local Binary Patterns) β multi-scale
- Color Histograms (HSV + LAB)
- Color Moments (mean, std, skew)
- Haralick Texture Features (GLCM)
- Hu Moments (shape descriptors)
- Edge Features (Canny, Sobel, orientation histograms)
- Gabor Filter Responses (multi-frequency, multi-orientation)
- StandardScaler β Normalizes features to match training distribution
- XGBoost (ONNX) β Gradient-boosted tree ensemble for binary classification
- Probability Output β Returns per-class probabilities (cat % vs dog %)
- OOD Detection β If neither class exceeds 51% confidence, the image is flagged as "unknown"
| Metric | Score |
|---|---|
| Accuracy | >80% |
| F1 Score | >80% |
| Model Size | 2.03 MB (ONNX) |
| Inference Time | ~3-5s (Lambda cold start: ~30s first request) |
image_processing/
βββ api/ # Backend API
β βββ main.py # FastAPI app with /health and /predict endpoints
β βββ lambda_handler.py # AWS Lambda entry point
β βββ ml.py # ML pipeline (ONNX model + StandardScaler)
β βββ feature_extractor.py # Image preprocessing & 10,221-feature extraction
β βββ schemas.py # Pydantic response models
β βββ dependencies.py # Singleton model loader
βββ frontend/ # Static frontend (hosted on S3)
β βββ index.html # Main UI with drag-and-drop upload
β βββ index.css # Styles with light/dark mode
β βββ app.js # Upload logic, probability bars, theme toggle
βββ model/ # Trained model artifacts
β βββ xgboost_champion.onnx # XGBoost model in ONNX format (2.03 MB)
β βββ scaler.joblib # Fitted StandardScaler (240 KB)
βββ infra/ # Terraform Infrastructure as Code
β βββ main.tf # ECR, S3, Lambda, API Gateway, IAM
β βββ outputs.tf # Deployment URLs
β βββ monitoring.tf # CloudWatch alarms, SNS, Budget guard
βββ .github/workflows/
β βββ deploy.yml # CI/CD: build β ECR β Lambda β S3
βββ Dockerfile # Lambda Python 3.11 container
βββ requirements.txt # Pinned Python dependencies
βββ .dockerignore # Excludes data/notebooks from Docker build
βββ .gitignore # Excludes secrets, data, terraform state
- Python 3.11+
- Docker Desktop
- AWS CLI (configured with
aws configure) - Terraform 1.x+
# 1. Clone the repository
git clone https://github.com/Nduka99/image_processing_deployment.git
cd image_processing_deployment
# 2. Install dependencies
pip install -r requirements.txt
# 3. Start the API server
uvicorn api.main:app --host 127.0.0.1 --port 8000
# 4. Open the frontend
# Navigate to http://127.0.0.1:3000 (via a local HTTP server)
# Or open frontend/index.html directly# 1. Initialize and apply Terraform
cd infra
terraform init
terraform apply -auto-approve
# 2. Build and push Docker image
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.eu-west-2.amazonaws.com
docker build -t <ECR_URL>:latest ..
docker push <ECR_URL>:latest
# 3. Upload frontend to S3 (with API URL injected)
# The GitHub Actions workflow handles this automatically on push to main| # | Service | Resource | Free Tier Limit |
|---|---|---|---|
| 1-2 | ECR | Container registry + lifecycle policy | 500 MB/month |
| 3-6 | S3 | Bucket + website config + public access + policy | 5 GB, 20K GET/month |
| 7-8 | IAM | Lambda execution role + policy | Always free |
| 9 | Lambda | Container function (1024 MB, 60s) | 1M requests, 400K GB-s/month |
| 10-13 | API Gateway | HTTP API + integration + routes + stage | 1M calls/month |
| 14-15 | SNS | Alert topic + email subscription | 1M publishes/month |
| 16-19 | CloudWatch | 4 alarms (errors, duration, throttles, 5XX) | 10 alarms free |
| 20 | Budgets | Cost guard ($1/month threshold) | Always free |
GitHub Actions (.github/workflows/deploy.yml) triggers on every push to main:
- β Checkout code
- β Authenticate with AWS
- β Build Docker image β Push to ECR
- β Update Lambda function code
- β Inject API Gateway URL into frontend β Sync to S3
Setup: Add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as GitHub Secrets in your repository settings.
| Alarm | Triggers When | Action |
|---|---|---|
| Lambda Errors | Any invocation error | Email via SNS |
| Lambda Duration | Average > 50s (timeout = 60s) | Email via SNS |
| Lambda Throttles | Any throttled invocations | Email via SNS |
| API 5XX Errors | 5+ server errors in 5 minutes | Email via SNS |
| Budget Guard | Monthly cost exceeds $1 | Email notification |
| Layer | Technology |
|---|---|
| ML Model | XGBoost (ONNX Runtime) |
| Feature Extraction | OpenCV, scikit-image, mahotas, scipy |
| Backend | FastAPI + AWS Lambda |
| Frontend | Vanilla HTML/CSS/JS |
| Infrastructure | Terraform (IaC) |
| Containerization | Docker (Lambda Python 3.11 base) |
| CI/CD | GitHub Actions |
| Monitoring | CloudWatch + SNS |
| Cloud | AWS (S3, ECR, Lambda, API Gateway) |
This project was developed as part of an Applied AI assessment.
Built with β€οΈ using an agentic AI deployment pipeline