pub struct EdgeMap { /* private fields */ }Expand description
Per-pixel edge strength for one frozen frame, precomputed once.
Two maps, one per axis, quantized to u8 — a frame’s worth of f32
pairs is tens of megabytes per monitor, and the extra precision buys
nothing when the answer is an integer pixel column.
Implementations§
Source§impl EdgeMap
impl EdgeMap
Sourcepub fn new(gray: &GrayImage) -> Self
pub fn new(gray: &GrayImage) -> Self
Detect edges in a frozen frame.
The operator is a forward difference — I(x) - I(x-1) —
weighted 3:10:3 across the neighbouring rows in the Scharr manner.
The weighting rejects single-pixel noise without smearing the
edge’s position; the forward difference is what makes the position
unambiguous. A centered difference peaks equally on both pixels of
a one-pixel step, and a snap that lands on whichever of the two the
cursor happened to approach from is not an answer a user can rely
on. Position is the whole product here: an edge detected one pixel
off is worse than no edge at all, because the user trusted it.
The convention this fixes is that a boundary sits on the first pixel of the new region. Snapping both sides of a 40px-wide button therefore gives 20 and 60, and the rect drawn between them is 40 wide — the button’s true width, not one pixel short.
Sourcepub const fn threshold(&self) -> u8
pub const fn threshold(&self) -> u8
The strength a gradient must reach to count as an edge: the
[EDGE_PERCENT] percentile of this frame’s own gradients, floored
at MIN_GRADIENT.
Relative, because an absolute cut that works on a light theme finds nothing on a dark one. Floored, because a nearly blank screen’s 98th percentile is noise, and snapping to noise is worse than not snapping.
Sourcepub fn snap(&self, p: Point, radius: i32) -> Snap
pub fn snap(&self, p: Point, radius: i32) -> Snap
Where p wants to go, searching radius pixels either way on
each axis independently.
A non-positive radius disables snapping outright rather than searching a degenerate window.