// Unit tests for the geometric/numeric helpers in types.hpp and face_utils.hpp: // cosine_similarity and the ArcFace 5-point alignment transform. GPU-free, // model-free. #include #include #include "face_utils.hpp" #include "types.hpp" #include #include using Catch::Matchers::WithinAbs; TEST_CASE("cosine_similarity of a unit vector with itself is 1", "[types]") { std::array raw{}; raw[3] = 2.f; raw[7] = -1.f; Embedding e = l2_normalise(raw.data()); CHECK_THAT(cosine_similarity(e, e), WithinAbs(1.0f, 1e-6f)); } TEST_CASE("cosine_similarity of orthogonal vectors is 0", "[types]") { Embedding a{}, b{}; a[0] = 1.f; b[1] = 1.f; CHECK_THAT(cosine_similarity(a, b), WithinAbs(0.0f, 1e-6f)); } TEST_CASE("cosine_similarity of opposite vectors is -1", "[types]") { Embedding a{}, b{}; a[5] = 1.f; b[5] = -1.f; CHECK_THAT(cosine_similarity(a, b), WithinAbs(-1.0f, 1e-6f)); } TEST_CASE("align_face maps the reference landmarks onto the 112x112 canvas", "[face_utils]") { // Build a synthetic image where the five landmarks sit at known positions. // Feeding align_face the *reference* positions themselves should yield an // (near-)identity similarity transform, so the output is 112x112. cv::Mat img(200, 200, CV_8UC3, cv::Scalar(0, 0, 0)); std::array lm; for (int i = 0; i < 5; ++i) { lm[i] = {kArcFaceRef[i][0], kArcFaceRef[i][1]}; cv::circle(img, lm[i], 2, cv::Scalar(255, 255, 255), -1); } cv::Mat crop = align_face(img, lm); REQUIRE_FALSE(crop.empty()); CHECK(crop.cols == 112); CHECK(crop.rows == 112); } TEST_CASE("align_face is translation-equivariant", "[face_utils]") { // Shifting all landmarks by a constant offset must still produce a valid // 112x112 crop (the similarity transform absorbs the translation). cv::Mat img(300, 300, CV_8UC3, cv::Scalar(30, 30, 30)); std::array lm; const float dx = 100.f, dy = 80.f; for (int i = 0; i < 5; ++i) lm[i] = {kArcFaceRef[i][0] + dx, kArcFaceRef[i][1] + dy}; cv::Mat crop = align_face(img, lm); REQUIRE_FALSE(crop.empty()); CHECK(crop.cols == 112); CHECK(crop.rows == 112); } TEST_CASE("align_face returns empty on degenerate (collinear) landmarks", "[face_utils]") { // All five landmarks identical → the affine fit is degenerate. cv::Mat img(200, 200, CV_8UC3, cv::Scalar(0, 0, 0)); std::array lm; for (auto& p : lm) p = {50.f, 50.f}; cv::Mat crop = align_face(img, lm); CHECK(crop.empty()); }