A web-based biometric photo capture tool that ensures compliance with EU passport and visa photo requirements. Uses advanced face detection with MediaPipe to validate photo criteria in real-time.
Temporary demo link: photo.myhalici.com
- Head Height Validation: Ensures head occupies 71-80% of frame
- Top Margin Check: Validates 4-10% space above head
- Eye Level Positioning: Confirms eyes are at 35-45% from top
- Center Alignment: Detects and corrects horizontal centering
- Front/Back Camera Toggle: Switch between device cameras
- Digital Stabilization: Smooths face tracking for steady captures
- Distance Adjustment: Slider control (30-80%) to simulate camera distance
- Multiple Output Resolutions:
- 413x531 px (300 dpi - standard 35x45 mm)
- 620x800 px (~450 dpi - recommended)
- 827x1063 px (600 dpi - high quality)
- Grid Overlay: Rule of thirds composition guide
- Face Position Silhouette: Shows ideal head placement
- Live Eye Level Line: Real-time eye position tracking
- Color-Coded Feedback: Green (pass) / Red (fail) indicators
- Landmark Visualization: Optional face mesh display for debugging
- Automatic 3:4 Aspect Ratio: Crops to standard biometric dimensions
- Dual Format Export: PNG (lossless) and JPEG (compressed)
- Gallery View: Review and download multiple captures
- Face Detection: MediaPipe FaceLandmarker (468 facial landmarks)
- Framework: Vanilla JavaScript with ES6 modules
- Styling: Custom CSS with dark theme
- Architecture: Modular structure (HTML/CSS/JS separation)
biometric-photo/
├── css/
│ └── styles.css # All styling and responsive design
├── js/
│ └── app.js # Core application logic and face detection
├── README.md # Documentation
└── index.html # Main HTML structure
- Camera Initialization: Requests camera access and loads MediaPipe WASM model
- Face Detection Loop: Processes video frames at 60 FPS
- Landmark Analysis: Extracts 468 facial points to calculate:
- Face boundaries with padding for hair/chin
- Eye position from specific landmark indices
- Head center and dimensions
- Compliance Validation: Compares measurements against EU specifications
- Photo Capture: Crops and scales to selected resolution maintaining 3:4 ratio
- Modern browser with WebRTC support
- Camera/webcam access permission
- JavaScript enabled
- Recommended: Chrome, Firefox, Safari (latest versions)
- Open
index.htmlin a web browser - Allow camera permissions when prompted
- Position face within the guide frame
- Wait for all criteria to show green checkmarks
- Click "Take Photo" to capture
- Download in PNG or JPEG format
- Use white or light-colored background
- Ensure even, shadowless lighting
- Position camera at eye level
- Disable portrait mode on mobile devices
- Keep neutral facial expression
- Remove glasses if they cause reflections
- Model: MediaPipe FaceLandmarker (Float16)
- Source: Google Cloud Storage (official MediaPipe models)
- Processing: Real-time video analysis with temporal smoothing
- Accuracy: 468 landmark points for precise facial feature detection
HEAD_MIN: 71% // Minimum head height
HEAD_MAX: 80% // Maximum head height
TOP_MIN: 4% // Minimum top margin
TOP_MAX: 10% // Maximum top margin
EYE_MIN: 35% // Minimum eye level
EYE_MAX: 45% // Maximum eye level
CENTER_TOL: 12% // Maximum center offsetThis project uses MediaPipe under Apache 2.0 License.
The application is built with vanilla JavaScript and requires no build process. Simply edit the files and refresh the browser to see changes.
- setStatus(): Updates UI status messages
- loadModel(): Initializes MediaPipe face detector
- analyzeLandmarks(): Processes facial landmarks for compliance
- drawGuides(): Renders visual overlay guides
- capture(): Handles photo capture and cropping
- Requires good lighting conditions for accurate face detection
- Single face detection only (multiple faces not supported)
- Browser must support WebRTC getUserMedia API
- Mobile browser performance may vary (tested on iPad Pro 11-inch, 2022, iPadOS 26 - 23A5330a)
- Remove background somehow with a proper backend.
- Create a printable 15x10cm photo paper for direct printout 8 portrait photos.
Note: I'm not a JavaScript expert – this project is just the best I could do.
If you have ideas or improvements, feel free to open an issue or submit a pull request.
Contributions are very welcome! 🎉
This project is released under the MIT License.
You are free to use, modify, and contribute.
