A full-stack web application for matching lost and found items using AI-powered image processing, vector embeddings, and multi-signal similarity search.
- Item Management: Create and manage lost/found item listings with up to 6 images
- Smart Matching: AI-powered matching between lost and found items
- Privacy Protection: Contact info revealed only after mutual confirmation
- Real-time Notifications: Get notified when matches are found
- YOLO Object Detection: Automatic object detection and cropping
- CLIP Embeddings: Semantic similarity using OpenAI's CLIP model
- Perceptual Hashing: pHash, dHash, aHash for visual similarity
- ORB Descriptors: Geometric keypoint matching
- EXIF Extraction: GPS and metadata from photos
- Responsive Design: Works on desktop and mobile
- Camera Capture: Take photos directly from your phone
- Image Gallery: Thumbnail previews with full-size lightbox
- Drag & Drop: Easy image upload
- Backend: FastAPI (Python 3.10+)
- Database: SQLite with async support (aiosqlite)
- Frontend: Vanilla HTML/CSS/JavaScript
- Storage: Local file system
- ML Models: YOLOv8, OpenCLIP (ViT-B/32), OpenCV
- Authentication: JWT tokens with bcrypt password hashing
lost&found/
βββ app/
β βββ __init__.py
β βββ config.py # Configuration and settings
β βββ main.py # FastAPI application entry point
β βββ api/
β β βββ deps.py # Dependencies (auth, db)
β β βββ routes/
β β βββ auth.py # Authentication endpoints
β β βββ users.py # User management
β β βββ items.py # Item CRUD + image upload
β β βββ matches.py # Match confirmation/rejection
β β βββ notifications.py
β βββ db/
β β βββ database.py # Database connection
β βββ models/
β β βββ user.py # User model
β β βββ item.py # Item model
β β βββ image.py # Image model
β β βββ embedding.py # Embedding model (pgvector)
β β βββ match.py # Match model
β β βββ notification.py # Notification model
β βββ schemas/ # Pydantic schemas
β βββ services/
β β βββ auth.py # Authentication service
β β βββ storage.py # S3 storage service
β β βββ image_processing.py # Image processing pipeline
β β βββ matching.py # Matching engine
β β βββ notification.py # Email/SMS service
β βββ middleware/
β βββ security.py # Rate limiting, sanitization
βββ alembic/ # Database migrations
βββ scripts/
β βββ schema.sql # Raw SQL schema
βββ tests/ # Test files
βββ .env.example # Environment variables template
βββ requirements.txt # Python dependencies
βββ README.md
- Python 3.10+
- Conda (recommended) or pip
- CUDA-capable GPU (optional, for faster ML inference)
- Docker & Docker Compose (for containerized deployment)
# 1. Build the Docker image
docker-compose build
# 2. Start the server
docker-compose up -d
# 3. Access the application
# Frontend: http://localhost:8000
# API Docs: http://localhost:8000/docs# Production mode (detached)
docker-compose up -d
# Development mode with hot reload
docker-compose --profile dev up api-dev
# View logs
docker-compose logs -f
# Stop containers
docker-compose down
# Clean up everything
docker-compose down -v --rmi localWindows:
docker-run.bat build # Build image
docker-run.bat up # Start production
docker-run.bat dev # Start development
docker-run.bat logs # View logs
docker-run.bat down # Stop containersLinux/Mac:
./docker-run.sh build
./docker-run.sh up
./docker-run.sh dev- Copy the environment file:
cp .env.docker.example .env.docker-
Edit
.env.dockerwith your settings (especiallyJWT_SECRET_KEY) -
Data is persisted in the
./datadirectory
cd lost&found
# Using Conda (recommended)
conda create -n myenv python=3.10
conda activate myenv
# Or using venv
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activatepip install -r requirements.txtcp .env.example .env
# Edit .env with your configurationKey variables:
# Security
JWT_SECRET_KEY=your-super-secret-key-change-this
# Database (SQLite - auto-created)
DATABASE_PATH=data/lostfound.db
# File uploads
UPLOAD_DIR=uploads
MAX_IMAGE_SIZE_MB=10
# Matching defaults
DEFAULT_SEARCH_RADIUS_KM=50
DEFAULT_TIME_RANGE_DAYS=30# Development (with auto-reload)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Or simply
python -m uvicorn app.main:app --reload- Frontend: http://localhost:8000
- API Docs: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- Go to Report Item page
- Select "I Lost Something" or "I Found Something"
- Fill in the details:
- Category (phone, wallet, keys, etc.)
- Title and description
- Location (use GPS or enter manually)
- Date and time
- Upload photos:
- Choose from Gallery: Select existing photos
- Take Photo: Capture directly from camera (mobile)
- Drag & Drop: Drop images onto the upload area
- Submit the report
- Go to My Items page
- Click Find Matches on any item
- Adjust search parameters:
- Search Radius: How far to search (km)
- Time Range: Days before/after the event
- Minimum Score: Match confidence threshold (0-1)
- Click Search for Matches
- Review potential matches and confirm/reject
- When both parties confirm a match, contact info is revealed
- You'll receive a notification with the other person's email/phone
- Coordinate to return the item!
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/auth/login |
Login and get JWT token |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/users |
Register new user |
| GET | /api/v1/users/me |
Get current user profile |
| PATCH | /api/v1/users/me |
Update profile |
| DELETE | /api/v1/users/me |
Delete account |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/items |
Create lost/found item |
| GET | /api/v1/items |
List user's items |
| GET | /api/v1/items/{id} |
Get item details |
| PATCH | /api/v1/items/{id} |
Update item |
| DELETE | /api/v1/items/{id} |
Delete item |
| POST | /api/v1/items/{id}/images |
Upload image |
| GET | /api/v1/items/{id}/images |
List item images |
| DELETE | /api/v1/items/{id}/images/{image_id} |
Delete image |
| GET | /api/v1/items/{id}/matches |
Find matches |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/matches |
List all matches |
| GET | /api/v1/matches/{id} |
Get match details |
| POST | /api/v1/matches/{id}/confirm |
Confirm/reject match |
| POST | /api/v1/matches/{id}/reject |
Reject match |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/notifications |
List notifications |
| GET | /api/v1/notifications/{id} |
Get notification |
| POST | /api/v1/notifications/mark-read |
Mark as read |
| POST | /api/v1/notifications/mark-all-read |
Mark all as read |
| DELETE | /api/v1/notifications/{id} |
Delete notification |
See docs/examples.md for detailed request/response examples.
-
Metadata Filtering
- Same item type (phone, wallet, etc.)
- Within location radius (default 50km)
- Within time range (default 30 days)
- Opposite lost/found status
-
Vector Similarity Search
- Uses pgvector with HNSW index
- Cosine similarity on CLIP embeddings
- Returns top 50 candidates
-
Multi-Signal Re-ranking
- Vector similarity (40% weight)
- pHash similarity (25% weight)
- ORB keypoint matches (20% weight)
- Location proximity (15% weight)
-
Final Output
- Top 10 matches with scores
- Detailed score breakdown
- JWT authentication with configurable expiry
- Password hashing with bcrypt
- Rate limiting (100 requests/minute default)
- Input sanitization middleware
- Security headers (HSTS, CSP, etc.)
- Secure file upload validation
- Contact info hidden until mutual confirmation
| Variable | Description | Default |
|---|---|---|
JWT_SECRET_KEY |
Secret for JWT signing | Required |
JWT_ALGORITHM |
JWT algorithm | HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES |
Token expiry | 1440 (24h) |
DATABASE_PATH |
SQLite database path | data/lostfound.db |
UPLOAD_DIR |
Image upload directory | uploads |
MAX_IMAGE_SIZE_MB |
Max upload size | 10 |
DEFAULT_SEARCH_RADIUS_KM |
Match search radius | 50 |
DEFAULT_TIME_RANGE_DAYS |
Match time range | 30 |
VECTOR_SIMILARITY_THRESHOLD |
Min match score | 0.5 |
pytest tests/ -v# Delete the database file to start fresh
rm data/lostfound.db
# Restart the server - tables will be recreated
uvicorn app.main:app --reloaduploads/
βββ items/
βββ {item_id}/
βββ images/
βββ {image_id}/
βββ original.jpg
βββ processed.jpg
βββ thumbnail.jpg
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - feel free to use this project for personal or commercial purposes.
- FastAPI - Modern Python web framework
- OpenCLIP - Open source CLIP implementation
- Ultralytics YOLOv8 - Object detection
- ImageHash - Perceptual hashing