Skip to content

Standardize workspace on opencv-python-headless to prevent missing cv2 installs #363

Description

@gtong-nv

Summary

The workspace resolves both opencv-python and opencv-python-headless into the same shared virtual environment. These are separate Python distributions but install the same top-level site-packages/cv2/ files. Installing or removing one variant can therefore delete files owned by the other while leaving its .dist-info metadata behind.

The resulting environment appears valid to uv pip list, but import cv2 fails:

ModuleNotFoundError: No module named 'cv2'

This was encountered while launching the OmniDreams WebRTC server from PR #359.

Current dependency sources

OmniDreams and the core package use the headless distribution:

  • integrations/omnidreams/pyproject.toml: opencv-python-headless>=4.5
  • flashdreams/pyproject.toml: opencv-python-headless>=4.5

The workspace also introduces the GUI distribution:

  • integrations/flashvsr/pyproject.toml: opencv-python>=4.8
  • integrations/omnidreams/ludus-renderer/pyproject.toml dev extra: opencv-python>=4.5

The root uv.lock consequently contains both distributions.

A source scan found no cv2 imports in FlashVSR. Ludus Renderer uses cv2.VideoCapture in an example, which works with the headless wheel and does not require GUI functionality.

Reproduction

From the workspace root on Windows:

uv sync --all-packages --all-extras
uv pip list | grep opencv

The shared environment can contain both:

opencv-python
opencv-python-headless

After an environment transition that removes or replaces one variant, for example syncing a narrower workspace package:

uv sync --package flashdreams-omnidreams --extra dev
uv pip list | grep opencv
uv run --package flashdreams-omnidreams python -c "import importlib.util; print(importlib.util.find_spec('cv2'))"
uv run --package flashdreams-omnidreams python -c "import cv2"

Observed state:

opencv-python-headless 4.13.0.92
None
ModuleNotFoundError: No module named 'cv2'

The headless distribution's .dist-info directory and RECORD remained, but the actual site-packages/cv2/ directory was absent. Because the requested version was still recorded as installed, a normal uv run did not reinstall it.

The environment can be repaired manually with:

uv sync \
  --package flashdreams-omnidreams \
  --extra dev \
  --reinstall-package opencv-python-headless

That workaround restores cv2, but it does not remove the workspace-level collision.

Proposed fix

  1. Remove the unused opencv-python>=4.8 dependency from integrations/flashvsr/pyproject.toml. FlashVSR currently has no direct cv2 imports.
  2. Change the Ludus Renderer dev extra from opencv-python>=4.5 to opencv-python-headless>=4.5. Its observed VideoCapture use does not require GUI support.
  3. Regenerate the root lockfile with uv lock and verify the root workspace no longer resolves opencv-python.
  4. Add a ci_cpu dependency-policy test that scans workspace-member pyproject.toml files and rejects GUI/contrib OpenCV distributions:
    • opencv-python
    • opencv-contrib-python
    • opencv-contrib-python-headless

The shared workspace should use only opencv-python-headless.

Acceptance criteria

  • Root uv.lock contains opencv-python-headless but not opencv-python.
  • uv sync --all-packages --all-extras installs only one OpenCV distribution.
  • Switching between full-workspace and OmniDreams-only syncs does not break import cv2.
  • uv run --package flashdreams-omnidreams python -c "import cv2" succeeds.
  • A CPU test prevents workspace members from reintroducing another OpenCV wheel variant.

OSS/dependency notes

This proposal does not add a new dependency. opencv-python-headless is already an approved direct dependency and already appears in THIRD-PARTY-NOTICES. The change removes opencv-python from the root workspace resolution and updates uv.lock; no new OSRB dependency approval should be required.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions