diff --git a/runner/docker-compose.yml b/runner/docker-compose.yml new file mode 100644 index 00000000..c37f0387 --- /dev/null +++ b/runner/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.8' + +services: + pyro-engine: + build: + context: .. + dockerfile: ./runner/src/Dockerfile + command: python runner.py + volumes: + - ./data:/usr/src/app/data + + restart: always diff --git a/runner/src/Dockerfile b/runner/src/Dockerfile new file mode 100644 index 00000000..f91bbb04 --- /dev/null +++ b/runner/src/Dockerfile @@ -0,0 +1,19 @@ +FROM pyro-engine + +# set work directory +WORKDIR /usr/src/app + +# set environment variables +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 +ENV PYTHONPATH "${PYTHONPATH}:/usr/src/app" +ENV PATH /usr/local/bin:$PATH +ENV LANG C.UTF-8 + +# copy requirements file +COPY runner/src/requirements.txt /usr/src/app/requirements.txt + +RUN pip install -r /usr/src/app/requirements.txt \ + && rm -rf /root/.cache/pip + +COPY runner/src/runner.py /usr/src/app/runner.py diff --git a/runner/src/requirements.txt b/runner/src/requirements.txt new file mode 100644 index 00000000..62ff3c18 --- /dev/null +++ b/runner/src/requirements.txt @@ -0,0 +1,8 @@ +onnx>=1.9.0 +onnxruntime +pandas>=1.1.4 +PyYAML>=5.3.1 +tqdm>=4.41.0 +matplotlib>=3.2.2 +seaborn>=0.11.0 +ipython>=8.2.0 \ No newline at end of file diff --git a/runner/src/runner.py b/runner/src/runner.py new file mode 100644 index 00000000..c1539b59 --- /dev/null +++ b/runner/src/runner.py @@ -0,0 +1,67 @@ +# Copyright (C) 2020-2022, Pyronear. + +# This program is licensed under the Apache License version 2. +# See LICENSE or go to for full license details. + + +from PIL import Image +import requests +from io import BytesIO +from pyroengine.engine import PyronearEngine +from dotenv import load_dotenv +import os +import time +import json +import logging + +logging.basicConfig(format='%(asctime)s | %(levelname)s: %(message)s', level=logging.INFO, force=True) + + +def setup_engine(): + with open('data/config_data.json') as json_file: + config_data = json.load(json_file) + + # Loading config datas + detection_threshold = config_data['detection_threshold'] + api_url = config_data['api_url'] + save_evry_n_frame = config_data['save_evry_n_frame'] + loop_time = config_data["loop_time"] + latitude = config_data['latitude'] + longitude = config_data['longitude'] + model_path = config_data['model_path'] + + # Loading pi zeros datas + with open('data/cameras_credentials.json') as json_file: + cameras_credentials = json.load(json_file) + + engine = PyronearEngine(detection_threshold, api_url, cameras_credentials, save_evry_n_frame, latitude, longitude, model_path=model_path) + + return engine, cameras_credentials, loop_time + + +def capture(ip, CAM_USER, CAM_PWD): + url = f"http://{ip}/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=wuuPhkmUCeI9WG7C\ + &user={CAM_USER}&password={CAM_PWD}" + + response = requests.get(url, verify=False, timeout=3) + return Image.open(BytesIO(response.content)) + + +load_dotenv("data/.env") + +CAM_USER = os.environ.get("CAM_USER") +CAM_PWD = os.environ.get("CAM_PWD") + +engine, cameras_credentials, loop_time = setup_engine() + +while True: + for ip in cameras_credentials.keys(): + try: + start_time = time.time() + img = capture(ip, CAM_USER, CAM_PWD) + pred = engine.predict(img, ip) + + time.sleep(max(loop_time - time.time() + start_time, 0)) + except: + logging.warning(f"Unable to get image from camera {ip}") +