I’m building a Django microservice where one step needs to check whether an uploaded image contains a face, and return a confidence score. I don’t need face recognition/identification — just detection (“is there a face here, and how confident are you?”).
Requirements:
- Free/open-source, commercially usable license
- CPU-friendly (no GPU in production)
- Lightweight enough to containerize easily
- Returns a numeric confidence score per detection
- Actively maintained / production-proven
So far I’m considering:
- YuNet (
opencv/face_detection_yunet on Hugging Face, via cv2.FaceDetectorYN) — MIT license, tiny (~230KB ONNX), fast, decent WIDER Face scores (0.834/0.824/0.708 easy/medium/hard AP)
- RetinaFace (e.g.
py-feat/retinaface or the retina-face PyPI package) — Apache 2.0/MIT, higher accuracy but heavier, better on small/angled/occluded faces
- MediaPipe BlazeFace — fast but not clearly hosted on HF, distributed via pip package
Questions for the community:
- Has anyone run YuNet vs RetinaFace in production for a pure “has-face” gate check? Any accuracy/latency numbers on CPU?
- Is YuNet’s confidence score reliable enough to threshold on directly, or does it need calibration?
- Any other lightweight, actively maintained face detectors I should be considering that I’m missing?
Thanks in advance!
For a simple “does this image contain a face?” check, I’d probably start with YuNet. It’s very lightweight, MIT-licensed, CPU-friendly, and OpenCV provides a direct CPU implementation.
For your use case, I’d benchmark YuNet against RetinaFace on your own images. The confidence score can be used as a threshold, but I wouldn’t assume that a score like 0.9 means “90% probability” without calibration.
If you mainly need a fast yes/no gate in a Django microservice, YuNet seems like a very good starting point. BlazeFace is another lightweight option, especially for camera/mobile scenarios.
Thanks for the recommendation! I followed your suggestion and benchmarked YuNet against RetinaFace and MTCNN on my dataset.
The results were quite interesting. YuNet performed the best overall for my use case. At a confidence threshold of 0.8, YuNet achieved 97.67% accuracy, 95.45% precision, 100% recall, and a 97.67% F1 score, with only 1 false positive out of 43 images.
I also measured inference time on CPU. YuNet averaged around 11.6 ms per image, compared with about 175 ms for MTCNN and approximately 1051 ms for RetinaFace. So YuNet was roughly 15× faster than MTCNN and 90× faster than RetinaFace in my testing.
I also tested different confidence thresholds. Interestingly, 0.8 gave the best balance for my current dataset, while 0.9 eliminated the false positive but started missing actual faces. This also reinforced your point that the confidence score shouldn’t automatically be interpreted as a calibrated probability.
The dataset is still small (43 images), so I don’t consider these production-level accuracy numbers yet. My next step is to test YuNet on a much larger and more diverse dataset and determine the final threshold based on the acceptable false-positive/false-negative tradeoff.
Thanks again — your suggestion to start with YuNet was very helpful!