fix: spare natural webcam scene edges
This commit is contained in:
parent
5024a2eb54
commit
698063506b
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1658,7 +1658,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_client"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@ -1692,7 +1692,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_common"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
@ -1704,7 +1704,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_server"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
||||
|
||||
[package]
|
||||
name = "lesavka_client"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "lesavka_common"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ bench = false
|
||||
|
||||
[package]
|
||||
name = "lesavka_server"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
edition = "2024"
|
||||
autobins = false
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ fn partial_seam_run_pct_threshold() -> usize {
|
||||
///
|
||||
/// Inputs: optional pixel-guard tuning. Output: luma stddev threshold. Why:
|
||||
/// natural shelf/chair/table edges can look like a partial seam on one row,
|
||||
/// but damaged codec slabs usually have a low-texture block on one side.
|
||||
/// but damaged codec slabs usually keep both sides of the tear low-texture.
|
||||
fn partial_seam_block_stddev_threshold() -> f64 {
|
||||
f64::from(
|
||||
env_u32(
|
||||
@ -177,8 +177,9 @@ fn region_luma_stddev(
|
||||
/// Measure texture around a candidate partial-width seam.
|
||||
///
|
||||
/// Inputs: sampled frame, seam row, and candidate horizontal run. Output:
|
||||
/// standard deviation for the lower suspect block. Why: real scene detail can
|
||||
/// have a sharp edge, but damaged UVC tiles tend to be broad low-texture slabs.
|
||||
/// standard deviation for the least slab-like side of the suspect block. Why:
|
||||
/// real wall/furniture edges often have one smooth side, but damaged UVC tiles
|
||||
/// tend to create broad low-texture slabs on both sides of the tear.
|
||||
fn partial_seam_block_stddev(
|
||||
frame: &SampledFrame,
|
||||
row: usize,
|
||||
@ -191,9 +192,8 @@ fn partial_seam_block_stddev(
|
||||
let below_end = row.saturating_add(window).min(frame.height);
|
||||
let below = region_luma_stddev(frame, row, below_end, col_start, col_end);
|
||||
match (above, below) {
|
||||
(Some(above), Some(below)) => Some(above.min(below)),
|
||||
(Some(value), None) | (None, Some(value)) => Some(value),
|
||||
(None, None) => None,
|
||||
(Some(above), Some(below)) => Some(above.max(below)),
|
||||
(Some(_), None) | (None, Some(_)) | (None, None) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -329,6 +329,66 @@ fn pixel_guard_accepts_textured_partial_scene_edges() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Verifies smooth wall plus textured furniture edges are not frozen as tears.
|
||||
fn pixel_guard_accepts_wall_over_couch_scene_edges() {
|
||||
temp_env::with_vars(
|
||||
[
|
||||
("LESAVKA_UVC_MJPEG_PIXEL_GUARD", Some("1")),
|
||||
(
|
||||
"LESAVKA_UVC_MJPEG_PIXEL_GUARD_PARTIAL_SEAM_DELTA",
|
||||
Some("28"),
|
||||
),
|
||||
(
|
||||
"LESAVKA_UVC_MJPEG_PIXEL_GUARD_PARTIAL_SEAM_COVERAGE_PCT",
|
||||
Some("32"),
|
||||
),
|
||||
(
|
||||
"LESAVKA_UVC_MJPEG_PIXEL_GUARD_PARTIAL_SEAM_RUN_PCT",
|
||||
Some("12"),
|
||||
),
|
||||
(
|
||||
"LESAVKA_UVC_MJPEG_PIXEL_GUARD_PARTIAL_SEAM_BLOCK_STDDEV",
|
||||
Some("14"),
|
||||
),
|
||||
],
|
||||
|| {
|
||||
let width = 320;
|
||||
let height = 180;
|
||||
let mut frame = vec![0u8; width * height * 3];
|
||||
let seam_y = height.saturating_mul(77) / 100;
|
||||
let start_x = width.saturating_mul(61) / 100;
|
||||
let end_x = width.saturating_mul(80) / 100;
|
||||
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let offset = (y * width + x) * 3;
|
||||
if y < seam_y || !(start_x..end_x).contains(&x) {
|
||||
// Keep the wall naturally smooth but not slab-flat; the
|
||||
// regression is specifically about one smooth side plus
|
||||
// one textured side, not about blank-frame detection.
|
||||
let shade = 174u8.saturating_add(((x + y) % 28) as u8);
|
||||
frame[offset] = shade;
|
||||
frame[offset + 1] = shade.saturating_add(6);
|
||||
frame[offset + 2] = shade.saturating_sub(5);
|
||||
} else {
|
||||
let texture = ((x * 23 + y * 17) % 74) as u8;
|
||||
let base = 54u8.saturating_add(texture);
|
||||
frame[offset] = base;
|
||||
frame[offset + 1] = base.saturating_add((x % 27) as u8);
|
||||
frame[offset + 2] = base.saturating_sub((y % 21) as u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
super::mjpeg_visual_guard::sampled_rgb_frame_for_test(width, height, &frame),
|
||||
None
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Verifies low-detail gray slabs freeze out before UVC handoff.
|
||||
fn pixel_guard_rejects_flat_lower_block_frames() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user