diff --git a/core/dr-face/src/detect.rs b/core/dr-face/src/detect.rs index e1d9881..e6727a9 100644 --- a/core/dr-face/src/detect.rs +++ b/core/dr-face/src/detect.rs @@ -46,13 +46,13 @@ pub struct DetectOptions { /// it is measured on the aligned crop rather than the box. This one exists /// only to throw away the obviously hopeless before paying for a warp, so /// it is deliberately set *below* what the real floor will accept: the - /// aligned crop spans roughly 1.3x the box's shorter edge, so 48 here - /// cannot reject a face that would have cleared 64 there. + /// aligned crop spans roughly 1.3x the box's shorter edge, so 24 here + /// cannot reject a face that would have cleared 32 there. pub min_face_px: f32, /// Smallest face the embedder may be given, in **source pixels across the /// aligned crop** — `crop_px` in the catalog. /// - /// The honest statement of "a face must be at least 64x64", because this is + /// The honest statement of "a face must be at least 32x32", because this is /// the number of real pixels behind the 112x112 the model actually sees. /// The box's own size is not that: the ArcFace template reaches past the /// box for forehead and chin, so a 64-pixel box and a 64-pixel crop are @@ -74,6 +74,26 @@ pub struct DetectOptions { /// and a caller cannot enable one gate while forgetting the other. /// /// Zero disables it, which is what a measurement run wants. + /// + /// # It has to move with the size floor + /// + /// The two are coupled, because an upsampled face scores low here whatever + /// its original sharpness. Measured over the reference library, with the + /// size floor at 32 source pixels: + /// + /// | min sharpness | of what the size floor left, this removes | + /// |---|---| + /// | 0.002 | 3% | + /// | 0.005 | 8% | + /// | 0.010 | 16% | + /// | 0.020 | 27% | + /// + /// At a 64-pixel floor, 0.020 removed 7% — the same *kind* of face, the + /// large-but-soft one this gate exists for. Holding 0.020 while dropping + /// the size floor to 32 would have thrown away a quarter of the newly + /// admitted faces for being small rather than for being blurred, undoing + /// most of the point of lowering it. 0.005 removes 8% at 32, which is the + /// same job. pub min_sharpness: f32, } @@ -82,9 +102,9 @@ impl Default for DetectOptions { Self { confidence: 0.5, nms_iou: 0.4, - min_face_px: 48.0, - min_source_px: 64.0, - min_sharpness: 0.020, + min_face_px: 24.0, + min_source_px: 32.0, + min_sharpness: 0.005, } } } diff --git a/ui/dr-ui/examples/face_index.rs b/ui/dr-ui/examples/face_index.rs index 1e9ac70..7c1f4a9 100644 --- a/ui/dr-ui/examples/face_index.rs +++ b/ui/dr-ui/examples/face_index.rs @@ -464,13 +464,14 @@ fn report_quality( println!("{}", "-".repeat(52)); for (min_px, min_sharp) in [ (0.0_f32, 0.0_f32), - (64.0, 0.0), - (0.0, 0.010), - (64.0, 0.005), + (32.0, 0.0), + (32.0, 0.002), + (32.0, 0.005), + (32.0, 0.010), + (32.0, 0.020), + (48.0, 0.005), (64.0, 0.010), (64.0, 0.020), - (80.0, 0.010), - (96.0, 0.010), ] { let by_size = found.iter().filter(|f| f.0 < min_px).count(); let by_blur = found