#pragma once #include "face_utils.hpp" #include // ── FaceAlignerFunc ─────────────────────────────────────────────────────────── // KPN node: applies a 5-point similarity transform to each detected face, // producing a 112×112 BGR crop suitable for ArcFace inference. // // Alignment uses cv::estimateAffinePartial2D (RANSAC) to fit the detected // landmarks to ArcFace canonical positions. Degenerate detections (where the // affine fit fails) are silently dropped from the output vectors. struct FaceAlignerFunc { static constexpr std::string_view label() { return "face_aligner"; } AlignedSceneFrame operator()(SceneFrame sf) { if (sf.source.eof || sf.faces.empty()) return {std::move(sf.source), {}, {}}; std::vector good_faces; std::vector crops; good_faces.reserve(sf.faces.size()); crops.reserve(sf.faces.size()); for (auto& face : sf.faces) { cv::Mat crop = align_face(sf.source.image, face.landmarks); if (crop.empty()) { std::cerr << "[face_aligner] degenerate detection skipped\n"; continue; } good_faces.push_back(face); crops.push_back(std::move(crop)); } return {std::move(sf.source), std::move(good_faces), std::move(crops)}; } };