Architecture

Layers that know as little as possible about each other

Detectors and trackers know nothing about scenes. The spatial engine knows only geometry, the rule engine assigns meaning, and analytics only read what was stored. That separation is what lets a run be analysed again, a detector be swapped, and the licensed modules plug in without the core ever importing them.

The pipeline

  1. 1

    Camera or video

    A video file, USB webcam, or RTSP or HTTP stream.

  2. 2

    Detection

    A detector finds people, vehicles and other objects in each frame.

  3. 3

    Tracking

    Detections become anonymous tracks that restart with every run.

  4. 4

    Your scene

    Lines, gates, zones and routes turn movement into interactions.

  5. 5

    Rules

    Crossings, visits, dwell, routes and sequences are decided per track.

  6. 6

    Events

    One stored record per observation, with its track, time and rule.

  7. 7

    Analysis

    Summaries, video review, evaluation, exports and the API.

Worker process, one per running camera

  1. Frame source

    vision/sources/

    Files, USB cameras and RTSP or HTTP streams behind a FrameSource interface, with reconnection.

    Knows nothing about detection.

  2. Rotation, crop, preview resizing and JPEG encoding for the browser.

  3. Ultralytics, ONNX Runtime or torchvision provider, chosen with the hardware probe and a recorded fallback chain (vision/inference/).

    Knows nothing about lines, zones or routes.

  4. ByteTrack or BoT-SORT: anonymous, session-scoped ids in tentative, tracked, lost and removed states.

  5. Entity resolver Licensed

    recognition/runtime.py

    Only with a licence: says whether a track is an enrolled person or a registered plate. The core sees an interface, never recognition code.

  6. Spatial engine

    spatial/engine.py

    Geometry only: crossings with direction, zone presence and dwell, sampled ground points, calibrated distances.

    Does not decide what an interaction means.

  7. Rule engine

    rules/engine.py

    Per-track state machines for lines, zones, route groups, sequences and dwell rules. A track without complete evidence is never forced into a route.

  8. Relationship engine Optional

    relationships/engine.py

    Observations, time-bounded relationships and correlated events, each with a confidence and its evidence.

    Imports no detector, tracker or recognition model.

API process

  1. Supervisor and storage

    storage/writer.py

    Drains the worker queues and writes events, track summaries and trajectories in batches to SQLite or PostgreSQL; restarts crashed live workers.

  2. Cross-camera correlation Optional

    crosscam/

    Joins identity sightings on different cameras into scored transitions, on a background thread.

  3. Analytics and interfaces

    analytics/

    Analytics only read stored rows. The REST API, WebSockets, webhooks and the cvscope command line sit on top.

    Never re-runs detection to answer a question.

Paths are relative to backend/pathscope/ and link to the synced commit. A GPU or decoder crash stays inside its worker process; the API keeps running.

Processes and messages

Each running camera is its own process, supervised by the API. Live previews, run events and finished tracks travel on queues; commands travel back.

CV-Scope process model The browser talks to the API process over REST, WebSockets and MJPEG. The API process supervises one worker process per running camera, receives their status, events, finished tracks, previews and recordings, and writes to SQLite or PostgreSQL. Workers read frames from the camera or video file and run detection, tracking, the spatial and rule engines and the optional engines. Browser React interface, Scene Builder canvas REST, WebSocket, MJPEG previews API process FastAPI, one per installation RunSupervisor: starts workers, drains their queues, restarts live ones that crash EventWriter: batched writes, retried on transient database errors PreviewManager: the only owner of a live camera outside runs Cross-camera correlation on a background thread; webhooks Retention sweeps for recordings and optional modules Database SQLite (WAL) or PostgreSQL Alembic migrations at start Data directory Videos, recordings, model weights up: status once a second, events, finished tracks with trajectories, previews (dropped when the API is behind), recordings down: pause, resume, stop, seek, preview settings Worker process, camera 1 source, preprocess, detect, track spatial engine, rule engine optional: relationships, anomalies, recorder Worker, camera 2 one process per running camera Camera or file USB, RTSP, HTTP, video
A GPU or decoder crash stays inside its worker process. Separate processes also keep decoding and inference off the Python interpreter lock of the API. From the developer guide.

Technology decisions

From docs/architecture.md, with the reason for each choice.

ConcernDecisionReason
Backend Python 3.11+, FastAPI, Pydantic v2, SQLAlchemy 2, Alembic Mature, typed, well documented, and the vision ecosystem is Python.
Database SQLite (default, WAL mode) or PostgreSQL via PATHSCOPE_DATABASE_URL Local-first single-machine installs need zero setup; the ORM and migrations are dialect-neutral so server deployments can use PostgreSQL.
Detection Provider interface with three implementations: Ultralytics (YOLO11 / YOLOv8 / RT-DETR), ONNX Runtime (exported detectors), torchvision (SSDLite, Faster R-CNN) Ultralytics is the most practical maintained YOLO ecosystem but is AGPL-3.0, so it is an optional extra and its licence is shown in the model catalog. ONNX Runtime and torchvision give permissively licensed paths.
Tracking In-house ByteTrack (default) and BoT-SORT (camera motion compensation, optional appearance matching) behind a Tracker interface The ByteTrack algorithm is simple, MIT-licensed in its reference form, robust for people and vehicles, and an in-house implementation exposes the track states and statistics the research UI needs. Other trackers can be registered.
Inference runtime Provider probe (PyTorch CUDA / MPS / CPU, ONNX Runtime CPU / CUDA / TensorRT execution providers) with AUTO selection and graceful fallback Hardware-aware recommendation is a core requirement; no single runtime is available everywhere.
Video I/O OpenCV VideoCapture for files, USB and RTSP/HTTP Cross-platform and mature. Sources implement a small FrameSource interface so more can be added.
Workers One multiprocessing process per running camera, supervised by the API process A GPU or decoder crash must not take the API down; separate processes also avoid the GIL for decoding and inference.
Frontend React 19, TypeScript 5.9, Vite 7, react-router 7, TanStack Query 5, Zustand 5, Konva 10 / react-konva, Recharts 3 Mature, maintained, permissively licensed. Konva is a proper canvas scene graph with hit testing, which the editor needs.
Styling Hand-written CSS with design tokens, system font stack, no component framework Restrained industrial/scientific look, information density, no external requests at runtime.
Packaging pyproject.toml, setup scripts, Dockerfile (CPU and CUDA), docker-compose with optional PostgreSQL Reproducible installs without cloud services.

Extension points

Small interfaces, each documented, each with a single place to register an implementation.

Repository layout

backend/
  pathscope/
    api/            FastAPI routers and request/response schemas
    db/             SQLAlchemy models, session management
    domain/         Pydantic domain models (scene config, rules, geometry)
    hardware/       Hardware probe and recommendation engine
    models/         Model catalog, installation, benchmarking
    vision/
      detectors/    Detector providers (ultralytics, onnxruntime, torchvision)
      trackers/     Tracker interface, ByteTrack, BoT-SORT, camera motion, appearance encoders
      sources/      Frame sources (file, usb, rtsp/http)
      inference/    Runtime/device probing and selection
      pipeline.py   Frame -> detector -> tracker -> spatial -> rules
    spatial/        Geometry, spatial engine, calibration
    rules/          Rule engine, route state machine, actions
    analytics/      Aggregation, behaviour metrics, export
    workers/        Camera worker process, supervisor, message types
    storage/        Event writer and retention
    recognition/    Licensed modules (locked without a licence): common/, licensing/,
                    face/ (detector, alignment, quality, embeddings, matcher, enrollment),
                    plate/ (detector, preprocessing, ocr, parser, temporal), registry/,
                    events/, api/, runtime.py, service.py, catalog.py
    relationships/  Relationship & Event Correlation Engine: entities, observations,
                    relation registry, spatial, temporal, confidence, rules, correlation,
                    engine, replay, graph, visual (interactive graph queries), patterns,
                    summary, access, service, api
    location/       Location Engine: site hierarchy, layouts, camera topology, zone mapping,
                    plausibility and travel time, cross-camera settings, /api/locations
    crosscam/       Cross-camera correlation: sightings, transitions, journeys, topology deviations
  alembic/          Database migrations
  tests/            Unit and integration tests
frontend/
  src/
    api/            Typed API client
    components/     Reusable UI primitives
    pages/          Projects, Live, Experiments, Data, Analysis, Cameras, Models, Hardware, Settings, Setup
    scene-builder/  Canvas editor, tools, inspector, editor store (undo/redo)
    rule-builder/   Structured rule editor (subject and HAS RELATIONSHIP clauses)
    relationships/  Relationship explorer, timeline, search, rule editor, settings
    locations/      Interactive graph (canvas, model, workbench), journeys, site plan,
                    topology editor, site view
docs/               Architecture, installation, models, data model, privacy, developer guide
samples/            Sample scene and experiment configurations
scripts/            Setup and development scripts

Quality gates

Every pull request must pass four checks: a repository guard (no binaries, weights, secrets, invisible Unicode or media outside docs/), the backend tests and linter, the frontend type check, tests and build, and a dependency review. Then a code owner reviews it.

The conventions are strict about truthfulness: never present an estimate as a measurement, and label anything unfinished in the interface.

Search CV-Scope

Type to search the documentation, the 26 guides and the site.

Search runs in your browser against an index built with the site. Nothing is sent anywhere.