Files
Daniel Avila 1bcb3e5daa improve: modernize computer-vision-engineer agent (#821)
* improve: enhance computer-vision-engineer based on automated review

- Fix deprecated TensorRT 10.x API (build_serialized_network, set_memory_pool_limit)
- Add Foundation & Zero-Shot Vision Models section (SAM2/SAM3, Grounding DINO,
  CLIP, Florence-2, multimodal LLMs) with a model selection framework
- Update default detector to YOLO11 with AGPL-3.0 licensing note and
  RT-DETRv2/RF-DETR alternatives
- Modernize face recognition guidance to InsightFace/DeepFace, keep dlib
  face_recognition as a lightweight fallback only
- Add multi-object tracking (ByteTrack via model.track) to video analysis
- Replace unimplemented document-structure stub methods with a layoutparser-based
  approach and pointers to unstructured/VLM alternatives
- Add a Compliance & Ethical Considerations section for biometric/PII data
- Align frontmatter/structure with sibling data-ai agents: add model: sonnet,
  Glob/Grep tools, multi-example description, and an Integration with Other
  Agents section with explicit boundaries vs ai-engineer and ml-engineer

Automated review cycle | Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: reset ByteTrack state between independent video streams

Reusing a VideoAnalyzer instance for a new stream would otherwise carry
stale track IDs from the previous session, since persist=True caches
tracker state on the model's predictor.

Addresses review feedback on PR #821.

* fix: stop prior stream's threads before starting a new one

start_real_time_analysis previously only reset tracker state but left
any earlier capture/process threads running against the same
frame_queue/result_queue/model, so a reused VideoAnalyzer instance could
mix frames and tracker state across streams. Add stop_processing() to
join the old threads and drain the queues before starting a new stream.

Addresses further review feedback on PR #821.

* fix: correct layoutparser color channel and text-region filter

- Convert BGR (cv2.imread) to RGB before Detectron2LayoutModel.detect(),
  since PubLayNet was trained on RGB
- Include PubLayNet's 'Title' and 'List' labels in text_regions, not
  just 'Text', so headings and list blocks aren't dropped

Addresses cubic review feedback on PR #821.

* fix: unblock capture thread on stop and fail loudly if it won't die

cap.read() blocks until a frame arrives, so join(timeout=5.0) alone
could return with the capture thread still alive and start_real_time_analysis
would then reuse the shared model/queues underneath it. stop_processing
now releases the VideoCapture to unblock read() immediately, and raises
if a thread still hasn't exited after the join timeout instead of
silently proceeding.

Addresses further greptile review feedback on PR #821.

* fix: re-check thread liveness on retry instead of the processing flag

stop_processing() sets self.processing = False before it can guarantee
the old threads have exited (e.g. one is still blocked in model.track()
past the join timeout and it raises). A caller retrying
start_real_time_analysis after that RuntimeError would see
self.processing already False and skip straight to relaunch, letting
the still-alive worker resume against the shared model/queues once it
unblocks. Guard on actual thread.is_alive() instead so a retry keeps
re-joining until the old threads are confirmed dead.

Addresses further greptile review feedback on PR #821.

* fix: call stop_processing unconditionally to always drain queues

Gating stop_processing() on thread liveness skipped the queue drain
whenever the previous call's stuck thread had exited by the time of a
retry (the liveness check would then be False), leaking stale
frames/results from the old stream into the new one. stop_processing is
idempotent for dead/None threads, so call it unconditionally instead.

Addresses cubic review feedback on PR #821.

* fix: guard tracker reset against predictor without trackers attribute

Ultralytics only registers .trackers on the predictor once model.track()
has run at least once. If this model instance was previously used with
model.predict()/model() (plain inference, no tracking), self.model.predictor
exists but lacks a trackers attribute, so the direct attribute access
raised AttributeError and aborted stream startup. Use getattr with a
default instead of assuming the attribute exists.

Addresses further greptile review feedback on PR #821.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-21 11:00:49 -04:00
..