Building a passport/ID photo maker that never uploads the photo (MediaPipe in the browser)
Описание и применение
Браузерное приложение для создания паспортных фотографий, которое полностью работает на клиенте, соблюдает официальные требования к высоте головы, заменяет фон, корректно задаёт DPI и генерирует печатный PDF без загрузки изображения на сервер.
Задача
Most online passport photo services require uploading a selfie and then charging to remove watermarks, exposing users’ photos to external servers.
Результат
A browser‑only passport photo maker that respects privacy, meets official head‑height specifications, replaces background, writes correct DPI, and outputs a printable PDF with multiple copies.
Рабочий процесс
- 1. Detect face landmarks with MediaPipe FaceLandmarker to get chin (point 152) and crown (point 10).
- 2. De‑rotate image using the eye line.
- 3. Run a person segmenter on a window around the head; identify the top of hair from the first row where the mask covers a central band of the face.
- 4. Clamp crown height for specs that measure to the skull (e.g., Canada, ICAO).
- 5. Compute crop dimensions based on head height and spec margins using the provided computeCrop function.
- 6. Run a lightweight segmenter (selfie_segmenter, 250 KB) first, then load a higher‑quality model (selfie_multiclass_256x256, 16 MB) in the background unless the connection is slow.
- 7. Apply the segment mask to replace the background with a flat white color.
- 8. Export the cropped image as JPEG, patching the JFIF header to set the correct DPI for print size.
- 9. Generate a one‑page A4 PDF by embedding the JPEG with /DCTDecode and placing 30 copies using a cm operator.
- 10. Provide feedback to the user using MediaPipe blendshapes and simple measurements to warn about closed eyes, smiling, turned head, or uneven lighting before printing.
Доказательства
Most "passport photo online" sites ask you to upload a selfie and then charge to remove the watermark.
Once you know the chin and the crown in pixels, the crop is just arithmetic:
MediaPipe's FaceLandmarker gives 478 points. Point 152 is the chin, but the highest point (10) sits mid-forehead.
selfie_segmenter is 250 KB and good enough for a flat white background. selfie_multiclass_256x256 is 16 MB and handles curly hair much better.
canvas.toBlob('image/jpeg') doesn't set a useful density, so print shops print the file at the wrong size. Patch the JFIF header bytes directly:
- Дата записи: 2026-10-05T17:55:45.949Z