* Convert face crops to RGB before embedding
Face crops flow through the cv2 pipeline as BGR arrays, but
_process_image passes ndarrays to PIL without any channel conversion,
so the FaceNet and ArcFace embedders receive BGR input while both
models expect RGB. The error is symmetric between enrollment and
recognition so it partially cancels, but it still costs accuracy.
* Move BGR to RGB conversion into a shared helper
Deduplicate the channel swap from both _preprocess_inputs methods
into a BaseEmbedding._bgr_to_rgb static helper, as suggested in
review.
FaceDetectorYN was created with a hardcoded score_threshold of 0.5, so
configured face_recognition.detection_threshold values below 0.5 had no
effect: lower-confidence faces were discarded inside OpenCV before the
config threshold was applied as a post-filter.
On cameras with low-resolution detect streams (e.g. 736x416 substreams),
real faces routinely score 0.3-0.5 in YuNet, so face recognition never
ran on them even though the embedding model handles such crops well.
Cap the internal threshold at the configured value instead.