https://github.com/pyronear/pyro-engine
Wildfire detection on edge devices
https://github.com/pyronear/pyro-engine
docker image-classification onnxruntime python raspberry-pi wildfire
Last synced: 4 days ago
JSON representation
Wildfire detection on edge devices
- Host: GitHub
- URL: https://github.com/pyronear/pyro-engine
- Owner: pyronear
- License: apache-2.0
- Created: 2020-09-03T06:08:11.000Z (over 5 years ago)
- Default Branch: develop
- Last Pushed: 2026-04-14T05:40:43.000Z (8 days ago)
- Last Synced: 2026-04-14T07:28:36.180Z (8 days ago)
- Topics: docker, image-classification, onnxruntime, python, raspberry-pi, wildfire
- Language: Python
- Homepage: https://pyronear.org/pyro-engine
- Size: 13.2 MB
- Stars: 15
- Watchers: 5
- Forks: 7
- Open Issues: 28
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README

# 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
```python
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
* `linovision` adapter, for Linovision/Hikvision PTZ cameras using ISAPI
* `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
```python
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
```bash
git clone https://github.com/pyronear/pyro-engine.git
pip install -e pyro-engine/.
```
### Environment variables
Deployments usually rely on a `.env` file. A `.env.example` is provided at the root of the repository as a reference:
```text
API_URL=https://api.pyronear.org
CAM_USER=my_dummy_login
CAM_PWD=my_dummy_pwd
MEDIAMTX_SERVER_IP=1.2.3.4
PYRO_ENGINE_VERSION=latest
```
`PYRO_ENGINE_VERSION` controls which Docker image tag is pulled for both services (defaults to `latest` if unset).
### Data directory
A `./data` directory is expected with at least:
* `credentials.json`, see [Camera configuration ](#camera-configuration-and-backends) 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`, `pose_ids`, `poses`, or `bbox_mask_url` are used by the engine and the API.
`pose_ids` contains the pose IDs from the pyro-api database. For static cameras it is a list with a single element; for PTZ cameras each entry corresponds positionally to the matching physical preset in `poses`. If `bbox_mask_url` is set, occlusion mask files are fetched at `{bbox_mask_url}_{pose_id}.json`.
Below is one generic example for each adapter: `url`, `rtsp`, `reolink` static, `reolink` PTZ and `mock`.
```json
{
"url_camera_1": {
"name": "url_camera_1",
"adapter": "url",
"url": "http://user:password@camera-host:1234/cgi-bin/snapshot.cgi",
"pose_ids": [10],
"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",
"pose_ids": [11],
"id": "11",
"bbox_mask_url": "https://example.com/occlusion-masks/rtsp_camera_1",
"poses": [],
"token": "JWT_TOKEN_HERE",
"type": "static"
},
"192.168.1.11": {
"name": "reolink_static_1",
"adapter": "reolink",
"type": "static",
"pose_ids": [12],
"id": "12",
"poses": [],
"bbox_mask_url": "https://example.com/occlusion-masks/reolink_static_1",
"token": "JWT_TOKEN_HERE"
},
"192.168.1.12": {
"name": "reolink_ptz_1",
"adapter": "reolink",
"type": "ptz",
"id": "13",
"poses": [0, 1, 2, 3],
"pose_ids": [20, 21, 22, 23],
"bbox_mask_url": "https://example.com/occlusion-masks/reolink_ptz_1",
"token": "JWT_TOKEN_HERE"
},
"192.168.1.13": {
"name": "linovision_ptz_1",
"adapter": "linovision",
"type": "ptz",
"poses": [0, 1, 2, 3],
"pose_ids": [30, 31, 32, 33],
"azimuth_offset_deg": 90,
"bbox_mask_url": "https://example.com/occlusion-masks/linovision_ptz_1",
"token": "JWT_TOKEN_HERE"
},
"mock_camera_1": {
"name": "mock_camera_1",
"adapter": "mock",
"type": "static",
"pose_ids": [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. For Linovision/Hikvision, `username`/`password` override the global `CAM_USER`/`CAM_PWD`, `azimuth_offset_deg` aligns camera coordinates to real azimuths, and `snapshot_channel`/`ptz_channel` let you pick the right ISAPI channels.
---
## Documentation
The full package documentation is available here:
[https://pyronear.org/pyro-engine/](https://pyronear.org/pyro-engine/)
It covers engine usage, configuration and deployment details.
---
## Contributing
Please refer to [`CONTRIBUTING`](CONTRIBUTING.md) if you wish to contribute to this project.
---
## License
Distributed under the Apache 2 License. See [`LICENSE`](LICENSE) for more information.