6 Commits

7 changed files with 1420 additions and 1461 deletions

View File

@ -1,4 +1,4 @@
FROM docker.io/library/python:3.10-slim as base
FROM docker.io/library/python:3.11-slim as base
# Configure piwheels repo to use pre-compiled numpy wheels for arm
RUN echo -n "[global]\n" > /etc/pip.conf &&\
@ -19,7 +19,7 @@ RUN blobconverter --zoo-name mobile_object_localizer_192x192 --zoo-type depthai
FROM base as builder
RUN apt-get install -y git && \
pip3 install poetry==1.2.0 && \
pip3 install poetry && \
poetry self add "poetry-dynamic-versioning[plugin]"
ADD poetry.lock .
@ -35,6 +35,8 @@ RUN poetry build
#################
FROM base
COPY camera_tunning /camera_tuning
RUN mkdir /models
COPY --from=model-builder /models/mobile_object_localizer_192x192_openvino_2021.4_6shave.blob /models/mobile_object_localizer_192x192_openvino_2021.4_6shave.blob

View File

@ -10,7 +10,11 @@ import typing, types
import depthai as dai
import paho.mqtt.client as mqtt
from . import depthai as cam # pylint: disable=reimported
from camera import oak_pipeline as cam
CAMERA_EXPOSITION_DEFAULT = "default"
CAMERA_EXPOSITION_8300US = "8300us"
CAMERA_EXPOSITION_500US = "500us"
logger = logging.getLogger(__name__)
@ -45,6 +49,14 @@ def _parse_args_cli() -> argparse.Namespace:
help="threshold to filter detected objects",
type=float,
default=_get_env_float_value("OBJECTS_THRESHOLD", 0.2))
parser.add_argument("-f", "--camera-fps",
help="set rate at which camera should produce frames",
type=int,
default=30)
parser.add_argument("--camera-tuning-exposition", type=str,
default=CAMERA_EXPOSITION_DEFAULT,
help="override camera exposition configuration",
choices=[CAMERA_EXPOSITION_DEFAULT, CAMERA_EXPOSITION_500US, CAMERA_EXPOSITION_8300US])
parser.add_argument("-H", "--image-height", help="image height",
type=int,
default=_get_env_int_value("IMAGE_HEIGHT", 120))
@ -94,6 +106,12 @@ def execute_from_command_line() -> None:
objects_threshold=args.objects_threshold)
pipeline = dai.Pipeline()
if args.camera_tuning_exposition == CAMERA_EXPOSITION_500US:
pipeline.setCameraTuningBlobPath('/camera_tuning/tuning_exp_limit_500us.bin')
elif args.camera_tuning_exposition == CAMERA_EXPOSITION_8300US:
pipeline.setCameraTuningBlobPath('/camera_tuning/tuning_exp_limit_8300us.bin')
pipeline_controller = cam.PipelineController(pipeline=pipeline,
frame_processor=frame_processor,
object_processor=object_processor,
@ -101,6 +119,7 @@ def execute_from_command_line() -> None:
camera=cam.CameraSource(pipeline=pipeline,
img_width=args.image_width,
img_height=args.image_height,
fps=args.camera_fps,
))
def sigterm_handler(signum: int, frame: typing.Optional[

View File

@ -5,6 +5,7 @@ import abc
import datetime
import logging
import pathlib
import time
import typing
from dataclasses import dataclass
@ -22,6 +23,9 @@ _NN_PATH = "/models/mobile_object_localizer_192x192_openvino_2021.4_6shave.blob"
_NN_WIDTH = 192
_NN_HEIGHT = 192
_PREVIEW_WIDTH = 640
_PREVIEW_HEIGHT = 480
class ObjectProcessor:
"""
@ -196,20 +200,22 @@ class ObjectDetectionNN:
class CameraSource(Source):
"""Image source based on camera preview"""
def __init__(self, pipeline: dai.Pipeline, img_width: int, img_height: int):
def __init__(self, pipeline: dai.Pipeline, img_width: int, img_height: int, fps: int):
self._cam_rgb = pipeline.createColorCamera()
self._xout_rgb = pipeline.createXLinkOut()
self._xout_rgb.setStreamName("rgb")
# Properties
self._cam_rgb.setBoardSocket(dai.CameraBoardSocket.RGB)
self._cam_rgb.setPreviewSize(width=img_width, height=img_height)
self._cam_rgb.setPreviewSize(width=_PREVIEW_WIDTH, height=_PREVIEW_HEIGHT)
self._cam_rgb.setInterleaved(False)
self._cam_rgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.RGB)
self._cam_rgb.setFps(30)
self._cam_rgb.setFps(fps)
self._resize_manip = self._configure_manip(pipeline=pipeline, img_width=img_width, img_height=img_height)
# link camera preview to output
self._cam_rgb.preview.link(self._xout_rgb.input)
self._cam_rgb.preview.link(self._resize_manip.inputImage)
self._resize_manip.out.link(self._xout_rgb.input)
def link(self, input_node: dai.Node.Input) -> None:
self._cam_rgb.preview.link(input_node)
@ -217,6 +223,15 @@ class CameraSource(Source):
def get_stream_name(self) -> str:
return self._xout_rgb.getStreamName()
@staticmethod
def _configure_manip(pipeline: dai.Pipeline, img_width: int, img_height: int) -> dai.node.ImageManip:
# Resize image
manip = pipeline.createImageManip()
manip.initialConfig.setResize(img_width, img_height)
manip.initialConfig.setFrameType(dai.ImgFrame.Type.RGB888p)
manip.initialConfig.setKeepAspectRatio(False)
return manip
@dataclass
class MqttConfig:
@ -330,6 +345,10 @@ class PipelineController:
q_nn = dev.getOutputQueue(name=self._object_node.get_stream_name(), maxSize=queue_size, # type: ignore
blocking=False)
start_time = time.time()
counter = 0
fps = 0
display_time = time.time()
self._stop = False
while True:
if self._stop:
@ -341,6 +360,16 @@ class PipelineController:
except Exception as ex:
logger.exception("unexpected error: %s", str(ex))
counter += 1
if (time.time() - start_time) > 1:
fps = counter / (time.time() - start_time)
counter = 0
start_time = time.time()
if (time.time() - display_time) >= 10:
display_time = time.time()
logger.info("fps: %s", fps)
def _loop_on_camera_events(self, q_nn: dai.DataOutputQueue, q_rgb: dai.DataOutputQueue) -> None:
logger.debug("wait for new frame")
@ -361,6 +390,7 @@ class PipelineController:
self._object_processor.process(in_nn, frame_ref)
logger.debug("objects processed")
def stop(self) -> None:
"""
Stop event loop, if loop is not running, do nothing

Binary file not shown.

Binary file not shown.

2806
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -9,15 +9,14 @@ packages = [
]
[tool.poetry.dependencies]
python = "^3.10"
python = "^3.11"
paho-mqtt = "^1.6.1"
depthai = "^2.19.0"
depthai = "^2.22.0"
protobuf3 = "^0.2.1"
google = "^3.0.0"
blobconverter = "^1.3.0"
protobuf = "^4.21.8"
opencv-python-headless = "^4.6.0.66"
robocar-protobuf = {version = "^1.1.2", source = "robocar"}
robocar-protobuf = {version = "^1.3.0", source = "robocar"}
[tool.poetry.group.test.dependencies]
@ -35,8 +34,7 @@ types-protobuf = "^3.20.4.2"
[[tool.poetry.source]]
name = "robocar"
url = "https://git.cyrilix.bzh/api/packages/robocars/pypi/simple"
default = false
secondary = false
priority = "explicit"
[build-system]
requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning"]