From 6995a8dee162ec3dd6b6631fad1a449a156833bd Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Fri, 31 Jul 2026 17:50:27 -0400 Subject: [PATCH] feat(faceswap): expose yaw on enumeration too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- imagegen/faceswap.go | 8 ++++++++ provider/llamaswap/faceswap.go | 13 +++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/imagegen/faceswap.go b/imagegen/faceswap.go index 024fec2..4755505 100644 --- a/imagegen/faceswap.go +++ b/imagegen/faceswap.go @@ -55,6 +55,14 @@ type DetectedFace struct { Box [4]int // Score is the detector's confidence, 0-1. 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 diff --git a/provider/llamaswap/faceswap.go b/provider/llamaswap/faceswap.go index 2f7fb57..8434ce8 100644 --- a/provider/llamaswap/faceswap.go +++ b/provider/llamaswap/faceswap.go @@ -41,11 +41,12 @@ type faceSwapModel struct { type facesResponse struct { Count int `json:"count"` Faces []struct { - Index int `json:"index"` - Box []int `json:"box"` - Score float64 `json:"score"` - Width int `json:"width"` - Height int `json:"height"` + Index int `json:"index"` + Box []int `json:"box"` + Score float64 `json:"score"` + Width int `json:"width"` + Height int `json:"height"` + Yaw *float64 `json:"yaw"` } `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)) 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 // malformed entry as a protocol error rather than zero-filling it, // because a wrong box sends the caller at the wrong face.