A program that checks if a photo is suitable for use on an ID document.
English | 繁體中文
Testing Result
| Image | Image | Image | Image |
|---|---|---|---|
- Key Features
- Installation
- Usage
- Validation Options
- Configuration & Tuning
- Project Structure
- Troubleshooting
- License
- 🖥️ Dual Interface: A user-friendly Web GUI for easy uploads and a REST API for system integration.
- ✅ Flexible Validation: Checks for face position, eye state (open/closed), obstructions, background uniformity, shoulder balance, and image quality.
- 🖼️ Annotated Results: Provides clear visual feedback on the image, highlighting detected landmarks and specific validation failures.
- 🚀 Built with Power: Leverages OpenCV, MediaPipe, and scikit-learn for accurate and reliable analysis.
A virtual environment is recommended.
# 1. Clone the repository
git clone https://github.com/askiichan/IDPhotoReady.git
cd IDPhotoReady
# 2. Create and activate a virtual environment
# On Windows
python -m venv venv
venv\Scripts\activate
# On macOS / Linux
python3 -m venv venv
source venv/bin/activate
# 3. Install dependencies
pip install -r requirements.txtThe required AI models will be downloaded automatically on first run. For manual downloads, see Troubleshooting.
You can run this project as a self-contained web application or as a backend API.
The easiest way to get started. Ideal for validating single photos or batches.
- Start the application:
python main.py
- Open your browser and navigate to the local URL shown in the terminal (usually
http://127.0.0.1:7860).
The interface provides detailed failure reasons and an annotated image.
For programmatic access and integration with other services.
- Start the API server:
python start_api.py
- Access the interactive documentation in your browser at
http://localhost:8000/docs. You can test all endpoints directly from this page.
POST /validate: Upload an image file for validation.POST /validate-base64: Submit a base64-encoded image string.GET /health: Check if the API is running.
curl -X POST http://localhost:8000/validate \
-H "Accept: application/json" \
-F "file=@/path/to/photo.jpg;type=image/jpeg" \
-F "return_annotated=true" \
-F "validation_preset=custom" \
-F "face_sizing=true" \
-F "landmark_analysis=true" \
-F "eye_validation=true" \
-F "obstruction_detection=true" \
-F "mouth_validation=true" \
-F "quality_assessment=true" \
-F "background_validation=true" \
-F "shoulder_balance_validation=true"The system performs a series of checks. Most can be enabled or disabled.
| Category | What it Checks | Default |
|---|---|---|
| Face Detection | Detects exactly one face with high confidence. | Always On |
| Face Sizing | Face occupies a reasonable portion (5-80%) of the image. | On |
| Landmark Analysis | All 68 facial landmarks are visible and properly positioned. | On |
| Eye Validation | Both eyes are open using the Eye Aspect Ratio (EAR). | On |
| Obstruction Detection | Face is not covered by hands, masks, or other objects. | On |
| Mouth Validation | Mouth is visible and not unnaturally obscured. | On |
| Image Quality | Image is not a cartoon or drawing (using color analysis). | On |
| Background | Background is uniform and neutral (e.g., white). | Off |
| Shoulder Balance | Shoulders are visible, level, and framed correctly. | Off |
Most behavior is controlled by constants in id_validator/config.py and feature toggles/presets in id_validator/validation_config.py.
Runtime categories you can enable/disable (API form fields / GUI checkboxes):
face_sizing, landmark_analysis, eye_validation, obstruction_detection, mouth_validation, quality_assessment, background_validation, shoulder_balance_validation.
Face / Detection:
MIN_FACE_SIZE_RATIO/MAX_FACE_SIZE_RATIO: Acceptable face area (fraction of image). Widen if rejecting valid crops.MIN_FACE_CONFIDENCE: Min detector confidence (raise for fewer false positives; lower for tough images).
Eyes / Landmarks:
EAR_THRESHOLD: Below this Eye Aspect Ratio counts as closed.
Obstruction & Authenticity (natural vs cartoon / occlusion heuristics):
MIN_SKIN_PERCENTAGE: Minimum skin pixel ratio inside face ROI.MAX_UNIFORM_BLOCK_RATIO: Max proportion of face that can be nearly flat color.UNIFORM_COLOR_STD_THRESHOLD: Variance cutoff for detecting flat regions.MIN_EDGE_DENSITY: Low edges -> possible obstruction or synthetic/cartoon.MIN_COLOR_VARIANCE: Minimum overall color variability.MAX_DARK_PIXEL_RATIO/MAX_BRIGHT_PIXEL_RATIO: Extremes indicating poor exposure or masking.DARK_PIXEL_THRESHOLD/BRIGHT_PIXEL_THRESHOLD: Value cutoffs for the above ratios.CARTOON_THRESHOLD: K‑means color cluster count (lower = simpler palette = suspect).
Background (uniform neutral backdrop):
BG_SAMPLE_BORDER_PCT: Border thickness sampled for background stats.BG_MIN_MEAN_V: Minimum brightness (HSV V 0–255) to treat as sufficiently light.BG_MAX_MEAN_S: Max saturation (HSV S) to still count as neutral.BG_MAX_V_STD: Max brightness variation to consider background uniform.
Shoulder / Upper body alignment:
SHOULDER_VISIBILITY_THRESHOLD: Min MediaPipe visibility for each shoulder.MAX_SHOULDER_TILT_DEG: Max allowed tilt (increase to be less strict).MIN_SHOULDER_WIDTH_TO_FACE_RATIO: Ensures framing includes shoulders.
- Frequent rejections for "face too small/large": relax
MIN_FACE_SIZE_RATIO/ tightenMAX_FACE_SIZE_RATIO. - Valid open eyes flagged: lower
EAR_THRESHOLDslightly (e.g. 0.23). - Too many cartoons slipping through: lower
CARTOON_THRESHOLDor raiseMIN_EDGE_DENSITY. - Legit photos with colored (but acceptable) backgrounds rejected: raise
BG_MAX_MEAN_Sor lowerBG_MIN_MEAN_V. - Shoulder tilt false positives: raise
MAX_SHOULDER_TILT_DEGby 1–2 degrees.
Change one variable at a time; keep a short log of adjustments. If outcomes worsen, revert quickly. Consider committing a config.local.py and importing overrides (future enhancement).
.
├── main.py # Gradio Web GUI entrypoint
├── api.py # FastAPI server entrypoint
├── requirements.txt # Dependencies
├── id_validator/ # Core library
│ ├── validator.py # Validation pipeline
│ ├── config.py # Thresholds & constants
│ ├── validation_config.py # Preset option grouping
│ ├── models.py # Pydantic models
│ └── gradio_gui.py # GUI wiring
├── models/ # Downloaded model weights
└── test_imgs/ # Sample images
If the ML models do not download automatically, please check your internet connection. You can also download them manually from the links below and place them in the models/ directory.
This project is licensed under the MIT License. See the LICENSE file for details.
Disclaimer: This tool is intended for educational and development purposes. For official use, ensure compliance with all local regulations.















