Skip to content

Football analyzer pipeline - #19

Merged
boxerab merged 47 commits into
collabora:masterfrom
zoq:soccer-analyzer
Sep 14, 2026
Merged

boxerab merged 47 commits into
collabora:masterfrom
zoq:soccer-analyzer

Conversation

@zoq

@zoq zoq commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator
  • Support player detection, referee, and ball detection, within a single model
  • Support camera movement compensation
  • Custom drawing, of the results

@zoq

zoq commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator Author

This one requires a custom trained model, do we make it part of the project, or do we upload it to HF?

@aaron-boxer

aaron-boxer commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Thanks for the PR! let's make the model a part of the project for now, if not too big.

@boxerab

boxerab commented May 1, 2026

Copy link
Copy Markdown
Collaborator

one request - is it possible to move all the module level imports to the method level instead ? This will speed up pipeline startup as gstreamer scans all python scripts for elements at startup, and module level imports are executed, so we want to avoid these imports. The other elements in the framework all avoid module level imports. 🙏

@boxerab
boxerab force-pushed the master branch 2 times, most recently from 0be9a68 to 44e42dd Compare May 3, 2026 16:26
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
@zoq
zoq force-pushed the soccer-analyzer branch 2 times, most recently from f44c413 to 59d1e51 Compare June 16, 2026 01:54
zoq added 4 commits June 16, 2026 02:05
…ine with ONNX/YOLO class-name and FP16 handling, plus the football models.

Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
…a Yocto layer for the on-board gst-python-ml stack.

Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
@boxerab

boxerab commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Looks good, thanks! I think it would be good to have an extern directory at the top level of the project for external dependencies, and to place rzv2h folder in extern. Then LGTM.

zoq and others added 17 commits June 17, 2026 03:18
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
…on the original-resolution frame, expose the detector's confidence/NMS thresholds, and harden the overlay's kit-colour referee detection, box de-duplication, missed-detection bridging and circle smoothing.

Signed-off-by: Marcus Edel <marcus.edel@collabora.com>
gst elements are just thin shells around gst base classes
Replace the inline MuxedBufferProcessor with frameio.read_frames (the
shared backend frame I/O the sibling video leaves already use). Behavior
is identical: the gst frameio wraps the same MuxedBufferProcessor call.
Removes a direct gst-utility dependency from the element shell.
Replace inline MuxedBufferProcessor with frameio.read_frames and return
the backend's FlowReturn instead of Gst.FlowReturn in the transform body
(Gst is still used for element registration). Behavior-identical.
Replace inline MuxedBufferProcessor with frameio.read_frames. Behavior-
identical (gst frameio wraps the same call). Not pipeline-smoke-tested
here (no caption model downloaded); import + lint verified.
Replace inline MuxedBufferProcessor with frameio.read_frames. Behavior-
identical; import + lint verified (no LLM model downloaded to smoke-test).
The source framerate was hardcoded to 30/1; expose it as a 'num/denom'
property (threaded into frame I/O for muxed-stream frame timing). Defaults
to 30/1, so existing pipelines are unchanged.
confluent_kafka was imported in the same guarded block as gi, so when the
optional kafka client was absent the block failed and Gst was never
imported, making the unguarded 'class KafkaSink(Gst.Element)' raise
NameError during the plugin scan. Import Producer lazily in
initialize_producer (where it is used) instead, so a missing kafka client
no longer breaks the scan and only matters when a producer is created.
Split the object-detector per-frame path into a backend-agnostic
process_frames(frames, num_sources, fmt, target) hook (inference +
metadata, identical on any backend) and a backend driver that does frame
extraction + error mapping. The gst driver moves to VideoTransform's
do_transform_ip (extract via frameio, run process_frames, map to
FlowReturn), so every gst video element that supplies process_frames is
driven uniformly; base_objectdetector now supplies only process_frames.

This is the seam the g2g backend's g2g_process already calls, so the same
detector logic runs on either backend. Validated on gst: pyml_yolo
(Torch/CUDA + NVDEC + tracking, 20-23 persons/frame) and pyml_objectdetector
(ONNX/CPU) both run clean through the hoisted driver.
Import the base class at module top level and register the GStreamer
factory only under GSTML_BACKEND=gst, so the leaf imports cleanly under a
non-gst backend (where gi is present but the class is built on shims).
Add the g2g element backend skeleton selectable via GSTML_BACKEND=g2g,
with aggregator, analytics, frame I/O, transform/video-transform shims,
and accompanying tests. Load the model on the first frame even when the
device pre-created the engine, and convert RGBA->RGB before inference.
aaron-boxer and others added 25 commits August 11, 2026 10:24
registration moves behind backend.register_gst_element, called only
under the gst backend; GObject now comes from backend wherever the
g2g shim can stand in for it.
the five audio and text families (transcribe, translate, llm, separate,
tts) share one process_payload hook that both backends drive, and each
states its pad caps once instead of spelling them for gst and for g2g
separately.

no element builds a Gst object at import time any more, which segfaulted
the interpreter under PYML_BACKEND=g2g and took the caption and vlm
families down with it.
the ml elements no longer import gi unless the gst backend is selected,
and captions get a process_frames seam so they run hosted too. the g2g
aggregator takes the same process_frames shape as the transform, and the
ml property declarations move into one ml_property_namespace so the two
backends cannot drift.

emitted payload frames inherit the anchor's meta and count sequences on
from the input's, a detection staged on a stream with no pixels is
dropped rather than becoming a zero bbox, and the frameio and analytics
bindings are per-thread since the host runs one thread per element.

pyml_launch stops applying its defaulted-property table to hosted
elements, which was eating pyml_kafkasink's sync.
the engine import sat ahead of the base class in one try, so a missing
optional dependency skipped the base too and the class body raised
NameError instead of degrading.

the import test now looks for the shadowed gi's message rather than any
stderr at all, so an unrelated degradation warning does not read as an
element reaching for GStreamer.
torch moves 2.11 to 2.13 and torchvision follows it, so the ml path
changed. verified by the unit tests and lint only, not the gpu pipeline
suites. diskcache has an advisory with no fix, so it stays.
the old floor let uv keep pytest 8.4.2 on python below 3.14. executorch
moves 1.2 to 1.4 to go with it, which drops the test plugins it used to
pull in and nothing here uses.
the run only exited early on gst, where a leaky queue was inserted after
filesrc and cut the input to 65 of 5554 frames. g2g got no such queue,
ran the whole video, and hit the timeout, so the two backends were never
compared on the same work. both now run to the cap and pass if the log is
clean.

the gap counts recorded here came from that comparison, so they go until
the suite is run again.
resolve the yolo and base_objectdetector conflicts on master's split
task/engine layout, register the football elements through the backend
shims, move cv2/numpy/ultralytics imports into the methods, move rzv2h
under extern, and fetch the models from the hugging face hub instead of
git lfs.
@boxerab
boxerab merged commit c89ae87 into collabora:master Sep 14, 2026
1 check passed
@boxerab

boxerab commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Thanks again for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants