A comprehensive end-to-end machine learning system for detecting counterfeit medicines from images using deep learning. This project includes a complete training pipeline, REST API services, and a modern web frontend for real-time medicine authentication.
- Overview
- Architecture
- Features
- Project Structure
- Prerequisites
- Quick Start
- Detailed Setup
- Training the Model
- API Documentation
- Configuration
- Development
- Deployment
- Troubleshooting
- Dataset
- License
This system uses Transfer Learning with a pre-trained ResNet-18 model to classify medicine images as either Authentic or Counterfeit. The solution is built with a microservices architecture, separating concerns into:
- ML Service: FastAPI-based inference service for model predictions
- Backend API: Express.js server handling authentication, user management, and ML service proxying
- Frontend: React application with Vite for fast development and production builds
- Pharmaceutical quality control
- Supply chain verification
- Consumer protection tools
- Regulatory compliance checking
βββββββββββββββ ββββββββββββββββ βββββββββββββββ
β Client βββββββΆβ Server βββββββΆβ ML Service β
β (React) ββββββββ (Express) ββββββββ (FastAPI) β
βββββββββββββββ ββββββββββββββββ βββββββββββββββ
Port 3000 Port 5000 Port 8000
Data Flow:
- User uploads medicine image via React frontend
- Frontend sends request to Express backend (with authentication)
- Backend validates request and proxies to ML service
- ML service processes image through ResNet-18 model
- Prediction results flow back through the stack
- User sees classification result (Authentic/Counterfeit) with confidence score
- Image Classification: Binary classification (Authentic vs Counterfeit) using ResNet-18
- Real-time Inference: Fast API responses with confidence scores and probability distributions
- User Authentication: JWT-based authentication system with role-based access control
- Image Upload: Secure file upload with validation and processing
- Transfer Learning: Pre-trained ResNet-18 model fine-tuned on medicine dataset
- RESTful APIs: Well-structured API endpoints following REST principles
- Microservices: Decoupled services for scalability and maintainability
- Docker Support: Containerized deployment for easy setup
- Error Handling: Comprehensive error handling and validation
- Logging: Structured logging for debugging and monitoring
AiMl/
βββ client/ # React frontend application
β βββ src/
β β βββ components/ # Reusable React components
β β β βββ UploadComponent.jsx # Image upload component
β β βββ pages/ # Page components
β β βββ services/ # API client services
β β β βββ api.js # Axios API client
β β βββ App.jsx # Main app component
β β βββ main.jsx # Entry point
β β βββ index.css # Global styles
β βββ public/ # Static assets
β βββ index.html # HTML template
β βββ vite.config.js # Vite configuration
β βββ package.json
β βββ Dockerfile # Docker configuration
β
βββ server/ # Express.js backend API
β βββ src/
β β βββ config/ # Configuration files
β β β βββ config.js # Environment config
β β β βββ mongoose.js # Database connection
β β β βββ passport.js # JWT authentication
β β β βββ logger.js # Winston logger
β β βββ controllers/ # Request handlers
β β β βββ authController.js # Authentication logic
β β β βββ mlController.js # ML service integration
β β β βββ userController.js # User management
β β β βββ imageController.js # Image handling
β β βββ middlewares/ # Express middlewares
β β β βββ authenticate.js # JWT verification
β β β βββ uploadImage.js # File upload handling
β β β βββ validate.js # Request validation
β β βββ models/ # Mongoose models
β β β βββ userModel.js # User schema
β β β βββ roleModel.js # Role schema
β β β βββ tokenModel.js # Token schema
β β βββ routes/ # API routes
β β β βββ v1/
β β β βββ authRoute.js # Auth endpoints
β β β βββ mlRoute.js # ML endpoints
β β β βββ userRoute.js # User endpoints
β β β βββ index.js # Route aggregator
β β βββ services/ # Business logic
β β β βββ jwtService.js # JWT utilities
β β β βββ tokenService.js # Token management
β β βββ utils/ # Utility functions
β β β βββ apiError.js # Error handling
β β βββ validations/ # Validation schemas
β β β βββ authValidation.js # Request validation
β β βββ app.js # Express app setup
β β βββ index.js # Server entry point
β βββ package.json
β βββ ecosystem.config.js # PM2 configuration
β βββ Dockerfile
β
βββ ml_service/ # ML training & inference service
β βββ main.ipynb # Jupyter notebook (training)
β βββ app.py # FastAPI inference service
β βββ utils.py # Preprocessing utilities
β βββ model/ # Trained model files
β β βββ best_cls_resnet18.pt # ResNet-18 checkpoint
β βββ requirements.txt # Python dependencies
β βββ Dockerfile
β
βββ data/ # Dataset (gitignored)
β βββ raw/ # Original dataset
β β βββ train/ # Training images (89M)
β β βββ valid/ # Validation images (14M)
β β βββ test/ # Test images (6.8M)
β βββ processed/ # Processed data (empty)
β
βββ docker-compose.yml # Docker Compose configuration
βββ .gitignore # Git ignore rules
βββ README.md # This file
- Python 3.10+ - For ML service
- Node.js 20+ - For backend and frontend
- npm or yarn - Package manager
- MongoDB - Database (or use MongoDB Atlas)
- Git - Version control
The fastest way to get started:
# Clone the repository
git clone <repository-url>
cd AiMl
# Start all services
docker compose up --build
# Services will be available at:
# - Frontend: http://localhost:3000
# - Backend API: http://localhost:5000
# - ML Service: http://localhost:8000See Detailed Setup section below.
git clone <repository-url>
cd AiMlcd ml_service
# Create virtual environment
python -m venv .venv
# Activate virtual environment
# On macOS/Linux:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Ensure model file exists
# The model should be at: ml_service/model/best_cls_resnet18.pt
# If not, train the model first (see Training section)
# Start the service
python app.pyThe ML service will run on http://localhost:8000
Verify it's working:
curl http://localhost:8000/healthcd server
# Install dependencies
npm install
# Create .env file (copy from .env.example if available)
# Or set environment variables:
export ML_SERVICE_URL=http://localhost:8000
export DATABASE_URI=mongodb://127.0.0.1:27017/aiml_db
export JWT_ACCESS_TOKEN_SECRET_PRIVATE=<your-secret>
export JWT_ACCESS_TOKEN_SECRET_PUBLIC=<your-public-key>
# Generate JWT keys (if needed)
ssh-keygen -t rsa -P "" -b 2048 -m PEM -f storage/jwtRS256.key
ssh-keygen -e -m PEM -f storage/jwtRS256.key > storage/jwtRS256.key.pub
cat storage/jwtRS256.key | base64 # Use this for JWT_ACCESS_TOKEN_SECRET_PRIVATE
cat storage/jwtRS256.key.pub | base64 # Use this for JWT_ACCESS_TOKEN_SECRET_PUBLIC
# Start MongoDB (if running locally)
# macOS: brew services start mongodb-community
# Linux: sudo systemctl start mongod
# Windows: net start MongoDB
# Start the server
npm start
# Or for development with hot reload:
npm run devThe server will run on http://localhost:5000 (or PORT from .env)
Verify it's working:
curl http://localhost:5000/api/v1/ml/healthcd client
# Install dependencies
npm install
# Create .env file (optional)
# VITE_API_URL=http://localhost:5000
# Start development server
npm run devThe frontend will run on http://localhost:3000
- ML Service: http://localhost:8000/health
- Backend API: http://localhost:5000/api/v1/ml/health
- Frontend: http://localhost:3000
- Jupyter Notebook installed
- Dataset in
data/raw/directory - GPU recommended (but not required)
-
Open Jupyter Notebook:
cd ml_service jupyter notebook main.ipynb -
Run All Cells:
- The notebook will:
- Load and explore the dataset from
data/raw/ - Create image-level labels from detection boxes
- Set up data loaders with augmentation
- Initialize ResNet-18 model
- Train for 10 epochs (configurable)
- Evaluate on test set
- Save best model to
ml_service/model/best_cls_resnet18.pt
- Load and explore the dataset from
- The notebook will:
-
Model Checkpoint:
- Best model is saved based on validation accuracy
- Location:
ml_service/model/best_cls_resnet18.pt - Contains: model state, classes, and metadata
Edit the notebook to adjust:
EPOCHS: Number of training epochs (default: 10)BATCH_SIZE: Batch size for training (default: 32)LEARNING_RATE: Optimizer learning rate (default: 0.001)DATA_DIR: Dataset directory path
- Training accuracy: ~85-95%
- Validation accuracy: ~80-90%
- Test accuracy: ~75-85%
Note: Results may vary based on dataset and training configuration
GET /healthResponse:
{
"ok": true,
"classes": ["authentic", "counterfeit"],
"checkpoint": "/path/to/model/best_cls_resnet18.pt"
}POST /classify
Content-Type: multipart/form-dataRequest:
- Form data with
filefield containing image (JPG, PNG, etc.)
Response:
{
"label": "authentic",
"confidence": 0.95,
"probabilities": {
"authentic": 0.95,
"counterfeit": 0.05
}
}Example (cURL):
curl -X POST http://localhost:8000/classify \
-F "file=@path/to/image.jpg"All endpoints are prefixed with /api/v1
Sign Up:
POST /api/v1/auth/signup
Content-Type: application/jsonRequest Body:
{
"email": "user@example.com",
"password": "securepassword",
"name": "John Doe"
}Sign In:
POST /api/v1/auth/signin
Content-Type: application/jsonRequest Body:
{
"email": "user@example.com",
"password": "securepassword"
}Response:
{
"user": {
"id": "user_id",
"email": "user@example.com",
"name": "John Doe"
},
"tokens": {
"access": {
"token": "jwt_token_here",
"expires": "2024-01-01T00:00:00.000Z"
},
"refresh": {
"token": "refresh_token_here",
"expires": "2024-01-02T00:00:00.000Z"
}
}
}Health Check:
GET /api/v1/ml/healthResponse:
{
"ok": true,
"classes": ["authentic", "counterfeit"],
"checkpoint": "/path/to/model"
}Classify Image:
POST /api/v1/ml/classify
Authorization: Bearer <jwt_token>
Content-Type: multipart/form-dataRequest:
- Header:
Authorization: Bearer <jwt_token> - Form data:
filefield with image
Response:
{
"success": true,
"data": {
"label": "authentic",
"confidence": 0.95,
"probabilities": {
"authentic": 0.95,
"counterfeit": 0.05
}
}
}Example (cURL):
curl -X POST http://localhost:5000/api/v1/ml/classify \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-F "file=@path/to/image.jpg"Get All Users:
GET /api/v1/users
Authorization: Bearer <jwt_token>Get User by ID:
GET /api/v1/users/:userId
Authorization: Bearer <jwt_token>Update User:
PUT /api/v1/users/:userId
Authorization: Bearer <jwt_token>
Content-Type: application/jsonDelete User:
DELETE /api/v1/users/:userId
Authorization: Bearer <jwt_token>No environment variables required (uses default paths)
# Application
NODE_ENV=development
APP_NAME=Counterfeit Medicine Detection API
HOST=0.0.0.0
PORT=5000
# Database
DATABASE_URI=mongodb://127.0.0.1:27017/aiml_db
# JWT Authentication
JWT_ACCESS_TOKEN_SECRET_PRIVATE=<base64-encoded-private-key>
JWT_ACCESS_TOKEN_SECRET_PUBLIC=<base64-encoded-public-key>
JWT_ACCESS_TOKEN_EXPIRATION_MINUTES=240
# Token Expiration
REFRESH_TOKEN_EXPIRATION_DAYS=1
VERIFY_EMAIL_TOKEN_EXPIRATION_MINUTES=60
RESET_PASSWORD_TOKEN_EXPIRATION_MINUTES=30
# Email (Optional - for email verification)
SMTP_HOST=smtp.googlemail.com
SMTP_PORT=465
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
EMAIL_FROM=noreply@example.com
# URLs
FRONTEND_URL=http://localhost:3000
IMAGE_URL=http://localhost:5000/images
# ML Service
ML_SERVICE_URL=http://localhost:8000VITE_API_URL=http://localhost:5000Edit docker-compose.yml to customize:
- Port mappings
- Volume mounts
- Environment variables
- Resource limits
-
Start ML Service:
cd ml_service source .venv/bin/activate python app.py
-
Start Backend (with hot reload):
cd server npm run dev -
Start Frontend (with hot reload):
cd client npm run dev
- Backend: Follows MVC pattern with clear separation of concerns
- Frontend: Component-based React architecture
- ML Service: Simple FastAPI service with model loading
# Backend tests (if available)
cd server
npm test
# Frontend tests (if available)
cd client
npm test# Backend linting
cd server
npm run lint
# Backend formatting
npm run formatcd server
npm run build
npm run prod # Uses PM2cd client
npm run build
# Output in client/dist/# Build and start all services
docker compose up -d --build
# View logs
docker compose logs -f
# Stop services
docker compose down- Use HTTPS in production
- Store secrets in environment variables (never commit)
- Enable CORS only for trusted domains
- Use rate limiting (already configured)
- Validate all user inputs
- Keep dependencies updated
Problem: Model file not found
Error: [Errno 2] No such file or directory: 'model/best_cls_resnet18.pt'Solution:
- Train the model first (see Training section)
- Or download pre-trained model
- Check model path in
app.py
Problem: Connection refused error
Solution:
- Verify ML service is running:
curl http://localhost:8000/health - Check
ML_SERVICE_URLin backend.env - Ensure no firewall blocking port 8000
Problem: MongoDB connection failed
Solution:
- Verify MongoDB is running:
mongoshormongo - Check
DATABASE_URIin.env - Ensure MongoDB is accessible from server
Problem: CORS errors or 404s
Solution:
- Check
VITE_API_URLin frontend.env - Verify backend is running
- Check browser console for detailed errors
Problem: Port 3000, 5000, or 8000 already in use
Solution:
# Find process using port
lsof -i :8000 # macOS/Linux
netstat -ano | findstr :8000 # Windows
# Kill process or change port in configuration-
Check logs:
- Backend:
server/logs/or console output - ML Service: Console output
- Docker:
docker compose logs
- Backend:
-
Verify all services are running
-
Check environment variables
-
Review API documentation
-
Check GitHub issues (if applicable)
- Source: Roboflow Universe (Counterfeit_med_detection)
- License: CC BY 4.0
- Format: TensorFlow Object Detection format (CSV)
- Size: ~110MB total
- Training: 89MB (1,367 images)
- Validation: 14MB (123 images)
- Test: 6.8MB (65 images)
data/raw/
βββ train/
β βββ _annotations.csv # Annotation file
β βββ *.jpg # Training images
βββ valid/
β βββ _annotations.csv # Annotation file
β βββ *.jpg # Validation images
βββ test/
βββ _annotations.csv # Annotation file
βββ *.jpg # Test images
Each row in _annotations.csv contains:
filename,width,height,class,xmin,ymin,xmax,ymax
filename: Image filenamewidth,height: Image dimensionsclass: Label (authentic/counterfeit)xmin,ymin,xmax,ymax: Bounding box coordinates
- Dataset: CC BY 4.0 (Roboflow Universe)
- Code: See repository license file