Every embedding now carries the quality of the input it came from. Both axes fall out of the AR-005 warp for free: crop_sharpness() is the normalised Laplacian variance over the aligned 112x112, so contrast and size cannot leak into it, and the alignment residual is the part of the landmark deformation a similarity transform cannot explain, so in-plane roll reads as zero and foreshortening does not. Carried, not consumed. Nothing discounts or thresholds on either number yet -- that is AR-030 and VR-012, and the knee has to be located against recorded data before a gate is chosen. What this change buys is that the data exists to locate it with. No face is admitted unscored: the -1 sentinel is preserved rather than clamped, and a degenerate landmark fit is counted rather than silently dropped. Takes the VR-001 dump to schema_version 2. The bump is not for readers, which check for the datasets by name and replay a v1 dump unchanged; it is so a consumer can tell "never scored" from "scored zero", which is not recoverable from the arrays afterwards. TRACES: AR-028, AR-029, AR-030 | VR-001 | SR-002
81 lines
3.4 KiB
CMake
81 lines
3.4 KiB
CMake
# ── Unit tests ────────────────────────────────────────────────────────────────
|
|
# Pure, GPU-free, model-free tests. The similarity tests compile the GEMM backend
|
|
# directly with SAE_GEMM_CPU so the suite builds and runs on a machine without a
|
|
# GPU regardless of the main build's SAE_GEMM_BACKEND selection.
|
|
|
|
find_package(Catch2 3 QUIET)
|
|
if(NOT Catch2_FOUND)
|
|
include(FetchContent)
|
|
FetchContent_Declare(
|
|
Catch2
|
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
|
GIT_TAG v3.5.3
|
|
)
|
|
FetchContent_MakeAvailable(Catch2)
|
|
endif()
|
|
|
|
add_executable(sae_tests
|
|
test_similarity.cpp
|
|
test_calibration.cpp
|
|
test_gallery_store.cpp
|
|
test_face_utils.cpp
|
|
test_track_gallery.cpp
|
|
test_face_tracker.cpp
|
|
test_track_registry.cpp
|
|
test_face_detector_node.cpp
|
|
test_scene_detector_node.cpp
|
|
test_replay_fixtures.cpp
|
|
test_embedding_dump.cpp
|
|
test_audio_signature.cpp
|
|
${CMAKE_SOURCE_DIR}/src/backends/gemm_backend.cpp
|
|
${CMAKE_SOURCE_DIR}/src/gallery/gallery_store.cpp
|
|
${CMAKE_SOURCE_DIR}/src/audio_signature.cpp
|
|
${CMAKE_SOURCE_DIR}/src/gallery/embedder_stamp.cpp
|
|
)
|
|
target_include_directories(sae_tests PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
|
# SAE_GEMM_CPU: build the CPU reference GEMM regardless of the main backend.
|
|
# SAE_MODELS_DIR: config.hpp (pulled in by track_gallery.hpp) bakes model paths.
|
|
# SAE_TEST_FIXTURES_DIR: the audio golden vector is read from the source tree,
|
|
# not copied, so the file the plugin repo shares is the file under test.
|
|
# AR-026/AR-027: exercise the same kernel CI actually runs. Without this the
|
|
# suite compiles the scalar fallback while the CPU builder image links OpenBLAS,
|
|
# so the tested path and the shipped path would differ.
|
|
find_package(PkgConfig QUIET)
|
|
if(PkgConfig_FOUND)
|
|
pkg_check_modules(OPENBLAS_T QUIET openblas)
|
|
endif()
|
|
if(OPENBLAS_T_FOUND)
|
|
target_include_directories(sae_tests PRIVATE ${OPENBLAS_T_INCLUDE_DIRS})
|
|
target_link_libraries(sae_tests PRIVATE ${OPENBLAS_T_LINK_LIBRARIES})
|
|
elseif(NOT SAE_ALLOW_SCALAR_GEMM)
|
|
# Same rule as the CPU backend itself: testing the scalar loop while the
|
|
# shipped CPU path is OpenBLAS means the suite is not evidence about the
|
|
# kernel that runs.
|
|
message(FATAL_ERROR
|
|
"OpenBLAS not found, and the unit tests compile the CPU GEMM kernel "
|
|
"(AR-026). Install openblas-devel, or pass -DSAE_ALLOW_SCALAR_GEMM=ON "
|
|
"to test the scalar fallback deliberately.")
|
|
endif()
|
|
|
|
target_compile_definitions(sae_tests PRIVATE
|
|
$<$<BOOL:${OPENBLAS_T_FOUND}>:SAE_GEMM_CBLAS>
|
|
SAE_GEMM_CPU
|
|
SAE_MODELS_DIR="${SAE_MODELS_DIR}"
|
|
SAE_TEST_FIXTURES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/fixtures")
|
|
# gallery_store.cpp + gallery_calibration.hpp use nlohmann/json and HDF5
|
|
# (galleries are HDF5-native, see src/gallery/gallery_store.cpp); face_utils.hpp
|
|
# and the calibration GEMM pull in OpenCV (calib3d/imgproc/core) via types.hpp.
|
|
# ffmpeg_libs: audio_signature.cpp decodes the golden fixture (avformat/avcodec/
|
|
# avutil/swresample). Still GPU-free — the audio path is pure CPU.
|
|
target_link_libraries(sae_tests PRIVATE
|
|
Catch2::Catch2WithMain
|
|
nlohmann_json::nlohmann_json
|
|
ffmpeg_libs
|
|
${OpenCV_LIBS}
|
|
${HDF5_CXX_LIBRARIES})
|
|
target_include_directories(sae_tests PRIVATE ${HDF5_INCLUDE_DIRS})
|
|
|
|
include(CTest)
|
|
include(Catch)
|
|
catch_discover_tests(sae_tests)
|