feat(faceswap): expose yaw on enumeration too
Gadfly review (reusable) / review (pull_request) Successful in 4m54s
Adversarial Review (Gadfly) / review (pull_request) Successful in 4m55s
CI / Tidy (pull_request) Successful in 9m23s
CI / Build & Test (pull_request) Successful in 9m48s

ListFaces now carries head yaw, so a caller choosing WHICH face to swap can
see the thing that decides whether the swap will read — not only learn it
afterwards from the swap report. In the run that prompted this the target's
three faces sat at -82, -8 and -11 degrees; only the first was hopeless, and
nothing in a bounding box said so.
This commit is contained in:
2026-07-31 17:50:27 -04:00
parent ae2615ca68
commit 6995a8dee1
2 changed files with 15 additions and 6 deletions
+8
View File
@@ -55,6 +55,14 @@ type DetectedFace struct {
Box [4]int Box [4]int
// Score is the detector's confidence, 0-1. // Score is the detector's confidence, 0-1.
Score float64 Score float64
// Yaw is how far the head is turned from camera, in degrees, or nil when
// the provider does not report pose. Exposed on ENUMERATION, not just
// after the fact, because it is how a caller picks a face a swap will
// actually work on: past roughly ±45° the features carrying identity are
// edge-on, and the result reads as a generic person however good the
// transfer is. A bounding box cannot show this.
Yaw *float64
} }
// Size returns the box dimensions. Derived rather than stored: carrying // Size returns the box dimensions. Derived rather than stored: carrying
+2 -1
View File
@@ -46,6 +46,7 @@ type facesResponse struct {
Score float64 `json:"score"` Score float64 `json:"score"`
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
Yaw *float64 `json:"yaw"`
} `json:"faces"` } `json:"faces"`
} }
@@ -74,7 +75,7 @@ func (m *faceSwapModel) ListFaces(ctx context.Context, img imagegen.Image) ([]im
} }
out := make([]imagegen.DetectedFace, 0, len(parsed.Faces)) out := make([]imagegen.DetectedFace, 0, len(parsed.Faces))
for _, f := range parsed.Faces { for _, f := range parsed.Faces {
df := imagegen.DetectedFace{Index: f.Index, Score: f.Score} df := imagegen.DetectedFace{Index: f.Index, Score: f.Score, Yaw: f.Yaw}
// A short box would silently index out of range below; treat a // A short box would silently index out of range below; treat a
// malformed entry as a protocol error rather than zero-filling it, // malformed entry as a protocol error rather than zero-filling it,
// because a wrong box sends the caller at the wrong face. // because a wrong box sends the caller at the wrong face.