Turn face boxes back into sensor space before matching regions
Faces are found on the thumbnail, which is cached the right way up -- the grid would lie on its side otherwise. Segmentation runs on a proxy rendered through a neutral edit graph, which carries no orientation and is therefore in sensor order. For anything shot in portrait the two differ by a quarter turn, so a face and the person containing it were being compared in spaces 90 degrees apart: no match, or worse, a match against somebody else's region. The transform goes on the face rather than on the proxy. Instance masks are defined in the proxy's space and sampled long afterwards, so turning that space would be a far larger change than naming a region warrants. Also two things the first screenshot of the running app showed that no test would have: 110 of 23,528 displayed as "0%", which reads as the feature having done nothing. One decimal below ten percent, and a floor so real progress never shows as none. The rail picked some near-black covers, because the largest face in a group is often the nearest one in a badly lit frame and a black square beside a name identifies nobody. It now cuts the best few and takes the first legible one, falling back to the largest when a person's every photograph is dark -- which happens, and showing it beats showing nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+49
-6
@@ -127,13 +127,21 @@ impl IndexAudit {
|
||||
if c.images == 0 {
|
||||
return "no images in the library".into();
|
||||
}
|
||||
// Whole numbers read fine at 40% and lie at 0.47%, which rounds to
|
||||
// "0%" beside a count of 110 — a figure that says the feature is
|
||||
// broken when it is merely early. One decimal below ten percent, and
|
||||
// a floor so real progress never displays as none.
|
||||
let pct = c.fraction() * 100.0;
|
||||
let shown = if c.indexed > 0 && pct < 0.1 {
|
||||
"<0.1%".to_string()
|
||||
} else if pct < 10.0 {
|
||||
format!("{pct:.1}%")
|
||||
} else {
|
||||
format!("{pct:.0}%")
|
||||
};
|
||||
let mut s = format!(
|
||||
"{}/{} images indexed ({:.0}%), {} face(s), {} image(s) with none",
|
||||
c.indexed,
|
||||
c.images,
|
||||
c.fraction() * 100.0,
|
||||
c.faces,
|
||||
c.without_faces,
|
||||
"{}/{} images indexed ({shown}), {} face(s), {} image(s) with none",
|
||||
c.indexed, c.images, c.faces, c.without_faces,
|
||||
);
|
||||
if self.ready > 0 {
|
||||
s.push_str(&format!("; {} ready to index", self.ready));
|
||||
@@ -651,6 +659,7 @@ mod tests {
|
||||
let s = a.summary();
|
||||
assert!(s.contains("60/100"), "{s}");
|
||||
assert!(s.contains("60%"), "{s}");
|
||||
assert!(!s.contains("60.0%"), "whole numbers above ten percent: {s}");
|
||||
assert!(s.contains("30 ready"), "{s}");
|
||||
assert!(s.contains("10 awaiting"), "{s}");
|
||||
}
|
||||
@@ -673,6 +682,40 @@ mod tests {
|
||||
assert!(s.contains("10/10"), "{s}");
|
||||
}
|
||||
|
||||
/// The figure the real library actually produced: 110 of 23,528 rounds to
|
||||
/// "0%" at whole-number precision, which reads as nothing having happened.
|
||||
#[test]
|
||||
fn early_progress_does_not_display_as_zero() {
|
||||
let a = IndexAudit {
|
||||
coverage: faces::Coverage {
|
||||
images: 23_528,
|
||||
indexed: 110,
|
||||
without_faces: 64,
|
||||
faces: 125,
|
||||
},
|
||||
ready: 69,
|
||||
awaiting_proxy: 23_349,
|
||||
};
|
||||
let s = a.summary();
|
||||
assert!(s.contains("0.5%"), "{s}");
|
||||
assert!(!s.contains("(0%)"), "{s}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_single_image_in_a_huge_library_still_shows_something() {
|
||||
let a = IndexAudit {
|
||||
coverage: faces::Coverage {
|
||||
images: 100_000,
|
||||
indexed: 1,
|
||||
without_faces: 1,
|
||||
faces: 0,
|
||||
},
|
||||
ready: 99_999,
|
||||
awaiting_proxy: 0,
|
||||
};
|
||||
assert!(a.summary().contains("<0.1%"), "{}", a.summary());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_empty_library_says_so_rather_than_reporting_zero_of_zero() {
|
||||
assert_eq!(IndexAudit::default().summary(), "no images in the library");
|
||||
|
||||
Reference in New Issue
Block a user