An intelligent counterfeit currency authentication MVP. Instead of returning a single genuine/counterfeit label, CounterVision AI inspects each security feature of a banknote independently (watermark, security thread, RBI emblem, governor's signature, Ashoka Pillar, microtext, serial number, colour consistency, print quality) and produces a full authentication report with a Grad-CAM/attention heatmap and a plain-language explanation.
Read this before you rely on the output: there is no public, labelled dataset of genuine vs counterfeit currency to train a classifier on, and there shouldn't be one generally available. This MVP fuses classical computer-vision checks against documented physical security properties with a pretrained Vision Transformer's visual-similarity signal. It is a decision-support/demo tool, not a certified authentication device. See
frontend's About page for the full explanation.
Frontend: React 18 (Vite), Tailwind CSS, Axios, React Router, Recharts, react-dropzone, react-hot-toast, lucide-react
Backend: Python, Flask, OpenCV, PyTorch, HuggingFace Transformers (Vision Transformer), EasyOCR, NumPy, Pillow, ReportLab, SQLite
CounterVision/
├── frontend/ React application
│ └── src/
│ ├── components/ Reusable UI (upload zone, feature cards, charts…)
│ ├── pages/ Home, Upload, Results, Dashboard, History, About
│ ├── services/ Axios API client
│ └── hooks/ Theme (light/dark) hook
├── backend/
│ ├── app.py Flask entry point
│ ├── config.py Paths, model names, constants
│ ├── routes/ /upload /analyze /report /dashboard /history
│ ├── preprocessing/ Image preprocessing + currency/denomination detection
│ ├── models/ ROI extraction + ViT-fused classifier
│ ├── ocr/ EasyOCR serial number extraction
│ ├── explainability/ Heatmap + natural-language explanation
│ ├── utils/ Security-feature checks + SQLite persistence
│ ├── reports/ PDF report generator (+ generated/ output dir)
│ ├── static/, uploads/ Runtime file storage (auto-created)
│ └── requirements.txt
├── trained_models/ Reference embedding bank + builder script
└── datasets/ (empty) place sample note images here for testing
Requires Python 3.10+ (tested with Python 3.13).
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtFirst run will download the pretrained ViT (
google/vit-base-patch16-224, ~330MB) and EasyOCR's detection/recognition weights (~65MB) from HuggingFace/EasyOCR's servers — an internet connection is required the first time only; both are then cached locally.
Run the server:
python app.pyThe API starts at http://localhost:5000. Verify it's up:
curl http://localhost:5000/health
# {"status": "ok"}Improves the ViT visual-similarity signal. Without this step the system still works, relying on the security-feature heuristics alone.
python ../trained_models/build_reference_bank.py /path/to/genuine_note_photosRequires Node.js 18+.
cd frontend
npm install
npm run devThe app starts at http://localhost:5173 and proxies /api/* and
/static/* requests to the Flask backend on port 5000 (see
vite.config.js). Make sure the backend is running first.
To build for production:
npm run build
npm run previewFor a production deployment, set VITE_API_BASE_URL to your deployed
backend's root URL (e.g. https://api.yourdomain.com) before building, and
serve frontend/dist from any static host.
- Open http://localhost:5173.
- Go to Upload Currency, drag in a JPG/PNG photo of a note (front or back).
- Click Run Authentication Analysis.
- Review the Analysis Results page: prediction, confidence, Grad-CAM/attention heatmap, security feature checklist, and serial number.
- Download the full PDF report, or revisit it later from History.
- Check Dashboard for aggregate stats across every note analyzed.
| Method | Endpoint | Description |
|---|---|---|
| POST | /upload |
Upload a note image, returns an upload_id. |
| POST | /analyze |
Body { "upload_id": "..." } (or multipart file). Runs the full pipeline. |
| GET | /report/<id> |
Downloads the PDF authentication report. |
| GET | /dashboard |
Aggregate statistics. |
| GET | /history |
Paginated list of past analyses (?limit=&offset=). |
| GET | /history/<id> |
Fetch a single stored analysis. |
| DELETE | /history/<id> |
Delete a stored analysis. |
Example:
curl -F "file=@sample_note.jpg" http://localhost:5000/upload
# { "upload_id": "...", "preview_url": "/static/uploads/....jpg", ... }
curl -X POST -H "Content-Type: application/json" \
-d '{"upload_id": "PASTE_ID_HERE"}' \
http://localhost:5000/analyze- Denomination detection uses colour palette + aspect-ratio matching against
RBI's published note specifications (classical CV, not a trained
classifier) — see
preprocessing/currency_detection.pyfor the full rationale and an upgrade path to a trained detector (e.g. YOLO) once labelled data exists. - Every security-feature check (
utils/feature_verification.py) is grounded in a real, documented physical property of that feature — none require training data, so the MVP is fully functional out of the box. - The Vision Transformer (
models/vit_classifier.py) is used as a general-purpose feature extractor via HuggingFace Transformers; its ImageNet classification head is never used. Explainability uses attention rollout (the standard ViT technique when there's no trained classification head to Grad-CAM against), fused with a classical-CV saliency map. - All of the above is designed so that swapping in a properly trained,
labelled-data-backed classifier later is a drop-in change to
models/vit_classifier.py— no other module needs to change.