Face Recognition / People Integration #61
26
src/faces.rs
26
src/faces.rs
@@ -2234,6 +2234,17 @@ async fn update_face_handler<D: FaceDao>(
|
|||||||
orientation: None,
|
orientation: None,
|
||||||
model_version: Some(current.model_version.clone()),
|
model_version: Some(current.model_version.clone()),
|
||||||
};
|
};
|
||||||
|
// Soft contract on the re-embed: we'd LIKE a fresh ArcFace
|
||||||
|
// vector for the new crop, but the operator's bbox edit is
|
||||||
|
// sacred. If detection finds no face in the new region (they
|
||||||
|
// dragged the box slightly off-center, or moved it to a back-
|
||||||
|
// of-head shot they've already manually tagged), or returns a
|
||||||
|
// bad embedding, we keep the old embedding and apply the bbox
|
||||||
|
// anyway. Cost: stale embedding for that row, which slightly
|
||||||
|
// pollutes clustering for files re-detected against this
|
||||||
|
// person — accepted because dropping the user's drag is a
|
||||||
|
// worse UX. Transient failures (cuda_oom, engine unavailable)
|
||||||
|
// still 503 so the operator can retry once Apollo recovers.
|
||||||
match face_client.embed(crop_bytes, meta).await {
|
match face_client.embed(crop_bytes, meta).await {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
if let Some(face) = resp.faces.first() {
|
if let Some(face) = resp.faces.first() {
|
||||||
@@ -2241,20 +2252,23 @@ async fn update_face_handler<D: FaceDao>(
|
|||||||
Ok(b) => new_embedding = Some(b),
|
Ok(b) => new_embedding = Some(b),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(
|
warn!(
|
||||||
"PATCH /image/faces/{}: bad embedding from face service: {:?}",
|
"PATCH /image/faces/{}: bad embedding from face service ({:?}); keeping old embedding, bbox still applied",
|
||||||
id, e
|
id, e
|
||||||
);
|
);
|
||||||
return HttpResponse::BadGateway()
|
|
||||||
.body("invalid embedding from face service");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return HttpResponse::UnprocessableEntity()
|
info!(
|
||||||
.body("no face in new bbox");
|
"PATCH /image/faces/{}: no face detected in new bbox — keeping old embedding, bbox still applied",
|
||||||
|
id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(FaceDetectError::Permanent(e)) => {
|
Err(FaceDetectError::Permanent(e)) => {
|
||||||
return HttpResponse::UnprocessableEntity().body(format!("{}", e));
|
info!(
|
||||||
|
"PATCH /image/faces/{}: embed permanent error ({}); keeping old embedding, bbox still applied",
|
||||||
|
id, e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(FaceDetectError::Transient(e)) => {
|
Err(FaceDetectError::Transient(e)) => {
|
||||||
return HttpResponse::ServiceUnavailable().body(format!("{}", e));
|
return HttpResponse::ServiceUnavailable().body(format!("{}", e));
|
||||||
|
|||||||
Reference in New Issue
Block a user