Skip to content

pyronear/pyro-engine

PyroNear Logo

CI Status Documentation Status Test coverage percentage black

PyPi Version DockerHub version Supported Python versions license

PyroEngine repository

This repository contains two main components used in Pyronear wildfire detection deployments: pyroengine and pyro_camera_api

Directory Description
pyroengine/ Detection engine that runs the wildfire model on edge devices
pyro_camera_api/ Camera control API that exposes a unified interface for multiple adapters
scripts/ Shell scripts for deployment and debugging
src/ Helper scripts for camera control, focus, calibration and experiments
tests/ Test suite for the detection engine

Both components can run independently or together in the same deployment.


PyroEngine: wildfire detection on edge devices

PyroEngine provides a high level interface to use deep learning models in production while being connected to the alert API.

Quick example

from pyroengine.core import Engine
from PIL import Image

engine = Engine()

im = Image.open("path/to/your/image.jpg").convert("RGB")

prediction = engine.predict(im)

PyroCamera API: unified camera control

The pyro_camera_api package provides a REST API and a Python client to control cameras and retrieve images in a unified way.

The API supports multiple camera adapters through a common abstraction:

  • reolink adapter, for Reolink PTZ or static cameras
  • rtsp adapter, for RTSP streams
  • url adapter, for HTTP snapshot URLs
  • mock adapter, for development and tests

Each adapter has its own class and inherits from the same base interface. The system selects the correct implementation at runtime based on the adapter field in credentials.json. The API routes are the same for all camera types. PTZ cameras use pose and movement, other cameras ignore pose parameters without failing.

Simple API usage example

from pyro_camera_api_client import Client

client = Client("http://localhost:8000")

# Move a PTZ camera to a pose
client.move("ptz_camera_1", pose=2)

# Get a snapshot as bytes
image_bytes = client.snapshot("url_camera_1")

Setup

Python 3.11 or higher and pip or conda are required.

Developer installation

git clone https://github.com/pyronear/pyro-engine.git
pip install -e pyro-engine/.

Environment variables

Deployments usually rely on a .env file with information such as:

API_URL=https://api.pyronear.org
CAM_USER=my_dummy_login
CAM_PWD=my_dummy_pwd

Data directory

A ./data directory is expected with at least:

  • credentials.json, see Camera configuration to understand how to fill it
  • optionally model.onnx to override weights from Hugging Face
  • optionally config.json to override model configuration

Camera configuration and adapters

The camera configuration is stored in credentials.json. Each key represents a camera identifier and the entry defines how to access and control it.

The important field for the camera API is:

  • adapter which selects the camera implementation

Other fields such as type, azimuth, poses, or bbox_mask_url are used by the engine and the API.

Below is one generic example for each adapter: url, rtsp, reolink static, reolink PTZ and mock.

{
  "url_camera_1": {
    "name": "url_camera_1",
    "adapter": "url",
    "url": "http://user:password@camera-host:1234/cgi-bin/snapshot.cgi",
    "azimuth": 0,
    "id": "10",
    "bbox_mask_url": "",
    "poses": [],
    "token": "JWT_TOKEN_HERE",
    "type": "static"
  },

  "rtsp_camera_1": {
    "name": "rtsp_camera_1",
    "adapter": "rtsp",
    "rtsp_url": "rtsp://user:password@camera-host:554/live/STREAM_ID",
    "azimuth": 0,
    "id": "11",
    "bbox_mask_url": "https://example.com/occlusion-masks/rtsp_camera_1",
    "poses": [],
    "token": "JWT_TOKEN_HERE",
    "type": "static"
  },

  "reolink_static_1": {
    "name": "reolink_static_1",
    "adapter": "reolink",
    "type": "static",
    "azimuth": 45,
    "id": "12",
    "poses": [],
    "bbox_mask_url": "https://example.com/occlusion-masks/reolink_static_1",
    "token": "JWT_TOKEN_HERE"
  },

  "reolink_ptz_1": {
    "name": "reolink_ptz_1",
    "adapter": "reolink",
    "type": "ptz",
    "id": "13",
    "poses": [0, 1, 2, 3],
    "azimuths": [0, 90, 180, 270],
    "bbox_mask_url": "https://example.com/occlusion-masks/reolink_ptz_1",
    "token": "JWT_TOKEN_HERE"
  },

  "mock_camera_1": {
    "name": "mock_camera_1",
    "adapter": "mock",
    "type": "static",
    "azimuth": 0,
    "id": "14",
    "poses": [],
    "bbox_mask_url": "",
    "token": "JWT_TOKEN_HERE"
  }
}

These examples are only for illustration. Real deployments use real URLs and real tokens generated by the alert API.


Documentation

The full package documentation is available here:

https://pyronear.org/pyro-engine/

It covers engine usage, configuration and deployment details.


Contributing

Please refer to CONTRIBUTING if you wish to contribute to this project.


License

Distributed under the Apache 2 License. See LICENSE for more information.