Adds TRACES tags to code that already satisfies a Done requirement, so coverage reflects what exists rather than starting from zero: AR-001 face detection, AR-005 ArcFace alignment, AR-023 calibration fit, DP-001/DP-002 the single analysis core behind the CLI, IR-001 truth-file emission, IR-006 the Jellyfin round trip, GR-001/GR-002 gallery build and incremental merge, VR-001 the embedding dump, VR-002 replay through the real nodes, VR-003 per-second scoring. Only Done requirements are tagged. A tag on Planned work would inflate coverage with fiction that looks plausible — the same failure family as a gate that cannot fail, and harder to spot. GR-005 (gallery never leaves the instance) stays untagged deliberately: it is a prohibition satisfied by the absence of an egress path, so there is no unit that decides it. Same shape as PR-005 in the system spec, which has no software row for the same reason. A goal held only by prohibitions cannot be verified by pointing at code. Coverage 5/63 to 14/63. The three VR tags are reported as tagged-but-unexecuted and excluded from the numerator, since their tier cannot run on the CI host — tagging deliberately cannot raise the number on its own. Suite still 64 cases, 3199 assertions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> TRACES: AR-001, AR-005, AR-023, DP-001, DP-002, IR-001, IR-006, GR-001, GR-002, VR-001, VR-002, VR-003
60 lines
2.5 KiB
C++
60 lines
2.5 KiB
C++
#pragma once
|
||
/// TRACES: AR-005 | SR-002
|
||
#include "types.hpp"
|
||
|
||
#include <opencv2/calib3d.hpp>
|
||
#include <opencv2/imgproc.hpp>
|
||
|
||
#include <cmath>
|
||
|
||
// ── align_face ────────────────────────────────────────────────────────────────
|
||
// Produces a 112×112 BGR crop using the ArcFace 5-point similarity transform.
|
||
// Returns an empty Mat if the affine fit fails (degenerate detection).
|
||
inline cv::Mat align_face(const cv::Mat& img,
|
||
const std::array<cv::Point2f, 5>& landmarks) {
|
||
std::vector<cv::Point2f> src(landmarks.begin(), landmarks.end());
|
||
std::vector<cv::Point2f> dst(5);
|
||
for (int i = 0; i < 5; ++i) dst[i] = {kArcFaceRef[i][0], kArcFaceRef[i][1]};
|
||
|
||
cv::Mat M = cv::estimateAffinePartial2D(src, dst, cv::noArray(), cv::RANSAC, 3.0);
|
||
if (M.empty()) return {};
|
||
|
||
cv::Mat crop;
|
||
cv::warpAffine(img, crop, M, {112, 112},
|
||
cv::INTER_LINEAR, cv::BORDER_CONSTANT, {0, 0, 0});
|
||
return crop;
|
||
}
|
||
|
||
// ── enhance_for_retry ────────────────────────────────────────────────────────
|
||
// Used when initial face detection finds nothing. Pads the image by 50%
|
||
// (border-replicated, so the detector doesn't see a hard edge) and applies
|
||
// CLAHE to boost local contrast, giving the detector a second try.
|
||
inline cv::Mat enhance_for_retry(const cv::Mat& img) {
|
||
cv::Mat padded;
|
||
const int pad_x = img.cols / 4;
|
||
const int pad_y = img.rows / 4;
|
||
cv::copyMakeBorder(img, padded, pad_y, pad_y, pad_x, pad_x, cv::BORDER_REPLICATE);
|
||
|
||
cv::Mat lab;
|
||
cv::cvtColor(padded, lab, cv::COLOR_BGR2Lab);
|
||
std::vector<cv::Mat> channels;
|
||
cv::split(lab, channels);
|
||
cv::createCLAHE(2.0, cv::Size(8, 8))->apply(channels[0], channels[0]);
|
||
cv::merge(channels, lab);
|
||
|
||
cv::Mat out;
|
||
cv::cvtColor(lab, out, cv::COLOR_Lab2BGR);
|
||
return out;
|
||
}
|
||
|
||
// ── l2_normalise ──────────────────────────────────────────────────────────────
|
||
inline Embedding l2_normalise(const float* row) {
|
||
float norm = 0.f;
|
||
for (int d = 0; d < 512; ++d) norm += row[d] * row[d];
|
||
norm = std::sqrt(norm);
|
||
if (norm < 1e-6f) norm = 1e-6f;
|
||
Embedding emb;
|
||
for (int d = 0; d < 512; ++d) emb[d] = row[d] / norm;
|
||
return emb;
|
||
}
|