From 4deda5b10ba866467a6ee11a165ab04a2b5727f3 Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Wed, 13 Apr 2022 05:30:24 +0300 Subject: [PATCH 1/6] Update core/bindings: Color/MonoCamera `frameEvent`, Script `setScriptPath` args --- depthai-core | 2 +- src/pipeline/NodeBindings.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/depthai-core b/depthai-core index b0fd69c29..e0cc9b44e 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit b0fd69c29655c4627e07747153d7ddd3ddb7fe6d +Subproject commit e0cc9b44e836de93bb2df7296b50076f81ba007e diff --git a/src/pipeline/NodeBindings.cpp b/src/pipeline/NodeBindings.cpp index e6c02e7a4..067fafd19 100644 --- a/src/pipeline/NodeBindings.cpp +++ b/src/pipeline/NodeBindings.cpp @@ -583,6 +583,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("still", &ColorCamera::still, DOC(dai, node, ColorCamera, still)) .def_readonly("isp", &ColorCamera::isp, DOC(dai, node, ColorCamera, isp)) .def_readonly("raw", &ColorCamera::raw, DOC(dai, node, ColorCamera, raw)) + .def_readonly("frameEvent", &ColorCamera::frameEvent, DOC(dai, node, ColorCamera, frameEvent)) .def("setCamId", [](ColorCamera& c, int64_t id) { // Issue an deprecation warning PyErr_WarnEx(PyExc_DeprecationWarning, "setCamId() is deprecated, use setBoardSocket() instead.", 1); @@ -782,6 +783,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ .def_readonly("inputControl", &MonoCamera::inputControl, DOC(dai, node, MonoCamera, inputControl)) .def_readonly("out", &MonoCamera::out, DOC(dai, node, MonoCamera, out)) .def_readonly("raw", &MonoCamera::raw, DOC(dai, node, MonoCamera, raw)) + .def_readonly("frameEvent", &MonoCamera::frameEvent, DOC(dai, node, MonoCamera, frameEvent)) .def_readonly("initialControl", &MonoCamera::initialControl, DOC(dai, node, MonoCamera, initialControl)) .def("setCamId", [](MonoCamera& c, int64_t id) { // Issue an deprecation warning @@ -1146,7 +1148,7 @@ void NodeBindings::bind(pybind11::module& m, void* pCallstack){ script .def_readonly("inputs", &Script::inputs) .def_readonly("outputs", &Script::outputs) - .def("setScriptPath", &Script::setScriptPath, DOC(dai, node, Script, setScriptPath)) + .def("setScriptPath", &Script::setScriptPath, py::arg("path"), py::arg("name") = "", DOC(dai, node, Script, setScriptPath)) .def("setScript", py::overload_cast(&Script::setScript), py::arg("script"), py::arg("name") = "", DOC(dai, node, Script, setScript)) .def("setScript", py::overload_cast&, const std::string&>(&Script::setScript), py::arg("data"), py::arg("name") = "", DOC(dai, node, Script, setScript, 2)) .def("getScriptPath", &Script::getScriptPath, DOC(dai, node, Script, getScriptPath)) From 0e9633bebb5a5c60d9b32d34136cff8e4de7aac1 Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Wed, 13 Apr 2022 05:31:30 +0300 Subject: [PATCH 2/6] Add mono_preview_alternate_pro.py example, alternating IR control (dot-proj vs flood) per frame --- .../MonoCamera/mono_preview_alternate_pro.py | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 examples/MonoCamera/mono_preview_alternate_pro.py diff --git a/examples/MonoCamera/mono_preview_alternate_pro.py b/examples/MonoCamera/mono_preview_alternate_pro.py new file mode 100644 index 000000000..5ed49343f --- /dev/null +++ b/examples/MonoCamera/mono_preview_alternate_pro.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + +import cv2 +import depthai as dai + +# Create pipeline +pipeline = dai.Pipeline() + +# Define sources and outputs +monoL = pipeline.create(dai.node.MonoCamera) +monoR = pipeline.create(dai.node.MonoCamera) + +monoL.setBoardSocket(dai.CameraBoardSocket.LEFT) +monoL.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) +monoR.setBoardSocket(dai.CameraBoardSocket.RIGHT) +monoR.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) + +xoutDotL = pipeline.create(dai.node.XLinkOut) +xoutDotR = pipeline.create(dai.node.XLinkOut) +xoutFloodL = pipeline.create(dai.node.XLinkOut) +xoutFloodR = pipeline.create(dai.node.XLinkOut) + +xoutDotL.setStreamName('dot-left') +xoutDotR.setStreamName('dot-right') +xoutFloodL.setStreamName('flood-left') +xoutFloodR.setStreamName('flood-right') +streams = ['dot-left', 'dot-right', 'flood-left', 'flood-right'] + +# Script node for frame routing and IR dot/flood alternate +script = pipeline.create(dai.node.Script) +script.setProcessor(dai.ProcessorType.LEON_CSS) +script.setScript(""" + dotBright = 500 + floodBright = 200 + + node.warn(f'IR drivers detected: {str(Device.getIrDrivers())}') + + flagDot = False + while True: + # Wait first for a frame event, received at MIPI start-of-frame + event = node.io['event'].get() + + # Immediately reconfigure the IR driver. + # Note the logic is inverted, as it applies for next frame + Device.setIrLaserDotProjectorBrightness(0 if flagDot else dotBright) + Device.setIrFloodLightBrightness(floodBright if flagDot else 0) + + # Wait for the actual frames (after MIPI capture and ISP proc is done) + frameL = node.io['frameL'].get() + frameR = node.io['frameR'].get() + + # Route the frames to their respective outputs + node.io['dotL' if flagDot else 'floodL'].send(frameL) + node.io['dotR' if flagDot else 'floodR'].send(frameL) + + flagDot = not flagDot +""") + +# Linking +monoL.frameEvent.link(script.inputs['event']) +monoL.out.link(script.inputs['frameL']) +monoR.out.link(script.inputs['frameR']) + +script.outputs['dotL'].link(xoutDotL.input) +script.outputs['dotR'].link(xoutDotR.input) +script.outputs['floodL'].link(xoutFloodL.input) +script.outputs['floodR'].link(xoutFloodR.input) + +# Connect to device and start pipeline +with dai.Device(pipeline) as device: + queues = [device.getOutputQueue(name=s, maxSize=4, blocking=False) for s in streams] + + while True: + for q in queues: + pkt = q.tryGet() + if pkt is not None: + name = q.getName() + frame = pkt.getCvFrame() + cv2.imshow(name, frame) + + if cv2.waitKey(5) == ord('q'): + break From 31578b76a6611b1d0af9a48b54ff4356e8d91946 Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Wed, 13 Apr 2022 05:41:42 +0300 Subject: [PATCH 3/6] Fix a typo (incorrectly sending right frame) --- examples/MonoCamera/mono_preview_alternate_pro.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/MonoCamera/mono_preview_alternate_pro.py b/examples/MonoCamera/mono_preview_alternate_pro.py index 5ed49343f..db1bc0908 100644 --- a/examples/MonoCamera/mono_preview_alternate_pro.py +++ b/examples/MonoCamera/mono_preview_alternate_pro.py @@ -51,7 +51,7 @@ # Route the frames to their respective outputs node.io['dotL' if flagDot else 'floodL'].send(frameL) - node.io['dotR' if flagDot else 'floodR'].send(frameL) + node.io['dotR' if flagDot else 'floodR'].send(frameR) flagDot = not flagDot """) From 47f30fc50fa5d35a72ff2d2731e764fbf7a82dec Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Mon, 19 Sep 2022 14:18:10 +0300 Subject: [PATCH 4/6] MonoCamera: add frame pool size config --- depthai-core | 2 +- src/pipeline/node/MonoCameraBindings.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/depthai-core b/depthai-core index f9b1e3902..0f6f312eb 160000 --- a/depthai-core +++ b/depthai-core @@ -1 +1 @@ -Subproject commit f9b1e3902a319c0e3c5d2dd77f5690039d8b7584 +Subproject commit 0f6f312eb18a71ea0d928da7e598875efe6159c3 diff --git a/src/pipeline/node/MonoCameraBindings.cpp b/src/pipeline/node/MonoCameraBindings.cpp index 594becd97..904b12289 100644 --- a/src/pipeline/node/MonoCameraBindings.cpp +++ b/src/pipeline/node/MonoCameraBindings.cpp @@ -42,6 +42,8 @@ void bind_monocamera(pybind11::module& m, void* pCallstack){ .def_readwrite("boardSocket", &MonoCameraProperties::boardSocket) .def_readwrite("resolution", &MonoCameraProperties::resolution) .def_readwrite("fps", &MonoCameraProperties::fps) + .def_readwrite("numFramesPool", &MonoCameraProperties::numFramesPool) + .def_readwrite("numFramesPoolRaw", &MonoCameraProperties::numFramesPoolRaw) ; // Node @@ -78,6 +80,11 @@ void bind_monocamera(pybind11::module& m, void* pCallstack){ .def("getResolutionSize", &MonoCamera::getResolutionSize, DOC(dai, node, MonoCamera, getResolutionSize)) .def("getResolutionWidth", &MonoCamera::getResolutionWidth, DOC(dai, node, MonoCamera, getResolutionWidth)) .def("getResolutionHeight", &MonoCamera::getResolutionHeight, DOC(dai, node, MonoCamera, getResolutionHeight)) + .def("setNumFramesPool", &MonoCamera::setNumFramesPool, DOC(dai, node, MonoCamera, setNumFramesPool)) + .def("getNumFramesPool", &MonoCamera::getNumFramesPool, DOC(dai, node, MonoCamera, getNumFramesPool)) + .def("setRawNumFramesPool", &MonoCamera::setRawNumFramesPool, DOC(dai, node, MonoCamera, setRawNumFramesPool)) + .def("getRawNumFramesPool", &MonoCamera::getRawNumFramesPool, DOC(dai, node, MonoCamera, getRawNumFramesPool)) + ; // ALIAS daiNodeModule.attr("MonoCamera").attr("Properties") = monoCameraProperties; From 767ac968944a0f0b2bd13ff3f51f7e2b640be0d5 Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Mon, 19 Sep 2022 14:24:59 +0300 Subject: [PATCH 5/6] mono_preview_alternate_pro.py: fix sync, add logging and sync checks --- .../MonoCamera/mono_preview_alternate_pro.py | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/examples/MonoCamera/mono_preview_alternate_pro.py b/examples/MonoCamera/mono_preview_alternate_pro.py index db1bc0908..ed00c22f9 100644 --- a/examples/MonoCamera/mono_preview_alternate_pro.py +++ b/examples/MonoCamera/mono_preview_alternate_pro.py @@ -3,6 +3,10 @@ import cv2 import depthai as dai +fps = 30 +res = dai.MonoCameraProperties.SensorResolution.THE_720_P +poolSize = 8 # default 3, increased to prevent desync + # Create pipeline pipeline = dai.Pipeline() @@ -11,9 +15,13 @@ monoR = pipeline.create(dai.node.MonoCamera) monoL.setBoardSocket(dai.CameraBoardSocket.LEFT) -monoL.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) +monoL.setResolution(res) +monoL.setFps(fps) +monoL.setNumFramesPool(poolSize) monoR.setBoardSocket(dai.CameraBoardSocket.RIGHT) -monoR.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) +monoR.setResolution(res) +monoR.setFps(fps) +monoR.setNumFramesPool(poolSize) xoutDotL = pipeline.create(dai.node.XLinkOut) xoutDotR = pipeline.create(dai.node.XLinkOut) @@ -32,6 +40,7 @@ script.setScript(""" dotBright = 500 floodBright = 200 + LOGGING = False # Set `True` for latency/timings debugging node.warn(f'IR drivers detected: {str(Device.getIrDrivers())}') @@ -39,15 +48,35 @@ while True: # Wait first for a frame event, received at MIPI start-of-frame event = node.io['event'].get() + if LOGGING: tEvent = Clock.now() # Immediately reconfigure the IR driver. # Note the logic is inverted, as it applies for next frame Device.setIrLaserDotProjectorBrightness(0 if flagDot else dotBright) Device.setIrFloodLightBrightness(floodBright if flagDot else 0) + if LOGGING: tIrSet = Clock.now() # Wait for the actual frames (after MIPI capture and ISP proc is done) frameL = node.io['frameL'].get() + if LOGGING: tLeft = Clock.now() frameR = node.io['frameR'].get() + if LOGGING: tRight = Clock.now() + + if LOGGING: + latIR = (tIrSet - tEvent ).total_seconds() * 1000 + latEv = (tEvent - event.getTimestamp() ).total_seconds() * 1000 + latProcL = (tLeft - event.getTimestamp() ).total_seconds() * 1000 + diffRecvRL = (tRight - tLeft ).total_seconds() * 1000 + node.warn(f'T[ms] latEv:{latEv:5.3f} latIR:{latIR:5.3f} latProcL:{latProcL:6.3f} ' + + f' diffRecvRL:{diffRecvRL:5.3f}') + + # Sync checks + diffSeq = frameL.getSequenceNum() - event.getSequenceNum() + diffTsEv = (frameL.getTimestamp() - event.getTimestamp()).total_seconds() * 1000 + diffTsRL = (frameR.getTimestamp() - frameL.getTimestamp()).total_seconds() * 1000 + if diffSeq or diffTsEv or (abs(diffTsRL) > 0.8): + node.error(f'frame/event desync! Fr-Ev: {diffSeq} frames,' + + f' {diffTsEv:.3f} ms; R-L: {diffTsRL:.3f} ms') # Route the frames to their respective outputs node.io['dotL' if flagDot else 'floodL'].send(frameL) From 4517dc8cb96a1bf915c02705db0cee25a219e362 Mon Sep 17 00:00:00 2001 From: alex-luxonis Date: Fri, 7 Oct 2022 10:59:48 +0300 Subject: [PATCH 6/6] mono_preview_alternate_pro: default to a lower resource usage config for PoE --- examples/MonoCamera/mono_preview_alternate_pro.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/MonoCamera/mono_preview_alternate_pro.py b/examples/MonoCamera/mono_preview_alternate_pro.py index ed00c22f9..826d5d927 100644 --- a/examples/MonoCamera/mono_preview_alternate_pro.py +++ b/examples/MonoCamera/mono_preview_alternate_pro.py @@ -3,9 +3,14 @@ import cv2 import depthai as dai -fps = 30 -res = dai.MonoCameraProperties.SensorResolution.THE_720_P -poolSize = 8 # default 3, increased to prevent desync +if 1: # PoE config + fps = 30 + res = dai.MonoCameraProperties.SensorResolution.THE_400_P + poolSize = 24 # default 3, increased to prevent desync +else: # USB + fps = 30 + res = dai.MonoCameraProperties.SensorResolution.THE_720_P + poolSize = 8 # default 3, increased to prevent desync # Create pipeline pipeline = dai.Pipeline() @@ -38,7 +43,7 @@ script = pipeline.create(dai.node.Script) script.setProcessor(dai.ProcessorType.LEON_CSS) script.setScript(""" - dotBright = 500 + dotBright = 500 # Note: recommended to not exceed 765, for max duty cycle floodBright = 200 LOGGING = False # Set `True` for latency/timings debugging