blinklinmult.overlay¶
Draw what the pipeline saw onto the frames it saw it in.
A number in a log says a model fired; an overlay says where it was looking when it did. That distinction is what makes the demo diagnostic rather than decorative – a red eye box explains a missing score far better than a gap in a plot.
The colour scheme is the whole legend:
colour |
meaning |
|---|---|
blue |
the tracked face |
green |
an eye that was scored |
red |
an eye that was found but suppressed (head turned) |
magenta |
FaceMesh landmarks |
grey |
the readout, top-left |
The readout sits on a translucent light panel, so it stays legible over any footage without a drop shadow – which was tried and reads as visual noise.
Attributes¶
Module-level logger. |
|
Blue, RGB, for the tracked face box. |
|
Green, RGB, for an eye that was scored. |
|
Red, RGB, for an eye found but suppressed. |
|
Magenta, RGB, for the FaceMesh points. |
|
Mid grey, RGB, for the readout. |
|
Near-white, RGB, behind the readout. |
|
How opaque the panel is. Enough for contrast, translucent enough to see through. |
|
Text size. Small deliberately -- the readout must not cover the face. |
|
Pixels between readout lines. |
|
Top-left corner of the readout. |
|
478 larger dots would hide the face. |
Functions¶
Module Contents¶
- blinklinmult.overlay.logger¶
Module-level logger.
- blinklinmult.overlay.FACE_COLOUR = (60, 130, 255)¶
Blue, RGB, for the tracked face box.
- blinklinmult.overlay.USED_COLOUR = (60, 220, 90)¶
Green, RGB, for an eye that was scored.
- blinklinmult.overlay.DROPPED_COLOUR = (240, 60, 60)¶
Red, RGB, for an eye found but suppressed.
- blinklinmult.overlay.LANDMARK_COLOUR = (230, 60, 230)¶
Magenta, RGB, for the FaceMesh points.
- blinklinmult.overlay.TEXT_COLOUR = (110, 110, 110)¶
Mid grey, RGB, for the readout.
Darker than it first appears it should be. The readout is drawn on a panel (
PANEL_COLOUR) rather than straight onto the frame, so it needs contrast against that panel, not against arbitrary video. A light grey chosen to survive a dark background is what made the text vanish on a bright one.
- blinklinmult.overlay.PANEL_COLOUR = (245, 245, 245)¶
Near-white, RGB, behind the readout.
Text alone cannot be legible over unknown video: whatever colour is picked, some frame defeats it. A drop shadow is one fix and was rejected as visual noise; a flat panel is the other, and it makes legibility a property of the panel rather than a gamble on the footage.
- blinklinmult.overlay.PANEL_ALPHA = 0.55¶
How opaque the panel is. Enough for contrast, translucent enough to see through.
- blinklinmult.overlay.FONT_SCALE = 0.5¶
Text size. Small deliberately – the readout must not cover the face.
- blinklinmult.overlay.LINE_HEIGHT = 18¶
Pixels between readout lines.
- blinklinmult.overlay.TEXT_ORIGIN = (8, 38)¶
Top-left corner of the readout.
One line lower than the frame’s top edge: Gradio draws its own component label over the top of the video, which would hide a first line placed there.
- blinklinmult.overlay.LANDMARK_RADIUS = 1¶
478 larger dots would hide the face.
- Type:
Landmark dot radius. One pixel
- blinklinmult.overlay.draw(frame: numpy.ndarray, result: blinklinmult.pipeline.Result, index: int) numpy.ndarray[source]¶
Annotate one frame.
- Parameters:
frame (np.ndarray) –
(H, W, 3)uint8 RGB. Not modified.result (Result) – The finished analysis.
index (int) – Which frame this is.
- Returns:
A new annotated frame.
- Return type:
np.ndarray
- blinklinmult.overlay.render(frames: numpy.ndarray, result: blinklinmult.pipeline.Result, output_path: str | pathlib.Path) pathlib.Path[source]¶
Write the annotated video.
- Parameters:
frames (np.ndarray) –
(T, H, W, 3)uint8 RGB, the source frames.result (Result) – The finished analysis, same length.
output_path (str | Path) – Where to write the mp4.
- Returns:
The written file.
- Return type:
Path
- blinklinmult.overlay.plot(result: blinklinmult.pipeline.Result)[source]¶
Plot both eyes: closeness, thresholds and the binary prediction.
Two stacked panels sharing the frame axis, left eye above right, so the two can be read against each other – eyes blink together, and a disagreement is usually one eye being suppressed rather than a real difference.
Suppressed spans are shaded and the line breaks, because a gap means the eye was not looked at. Drawing through it would assert a measurement that was never taken.
- Parameters:
result (Result) – The finished analysis.
- Returns:
The figure. The caller owns it and should close it; leaving figures open leaks memory across repeated runs.
- Return type:
matplotlib.figure.Figure