Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
017beae
Initial pointcloud implementation
Jun 15, 2023
9c6a5ce
Merge remote-tracking branch 'origin/develop' into HEAD
Jun 15, 2023
70b821a
Update core
Jun 15, 2023
be16a68
Merge remote-tracking branch 'origin/develop' into HEAD
Jul 5, 2023
855e020
Merge pull request #939 from luxonis/main
moratom Dec 14, 2023
a6963c9
Merge branch 'develop' of github.com:luxonis/depthai-python into poin…
asahtik Dec 20, 2023
1da4317
Fixed large buffer processing in MessageGroups
asahtik Jan 8, 2024
fbb9e3d
Added PointCloudDataBindings
asahtik Jan 8, 2024
4516699
Bump core
asahtik Jan 8, 2024
ac9ea49
Merge pull request #945 from luxonis/msg_grp_bugfix
asahtik Jan 10, 2024
369c01a
clangformat
asahtik Jan 10, 2024
0517a4d
Run HIL tests after all wheels are available
jakgra Jan 10, 2024
4ff848c
Make notify hil workflow depend only on builds it needs
jakgra Jan 15, 2024
845880b
Bugfixes, added python pointcloud visualization example with open3d
asahtik Jan 15, 2024
50a6485
Update core
Jan 15, 2024
8545d25
Update core
Jan 15, 2024
8c1a729
Merge pull request #956 from luxonis/bootloader_watchdog_bugfix
moratom Jan 15, 2024
4802dfa
Merge pull request #950 from luxonis/run_hil_workflow_after_build
jakgra Jan 16, 2024
54e8575
Added rgb pointcloud capability
asahtik Jan 17, 2024
c21f783
Revert "Added rgb pointcloud capability"
asahtik Jan 18, 2024
fba5559
Bump core
asahtik Jan 18, 2024
e357a76
Revert shared
asahtik Jan 22, 2024
d1d3754
Bump core
asahtik Jan 22, 2024
dbb1d9a
Sparse pointcloud bindings
asahtik Jan 22, 2024
c6c2032
Bump core
asahtik Jan 22, 2024
72b0b72
[RVC2] Added getStereoPairs and getAvailableStereoPairs API (#959)
zrezke Jan 24, 2024
30630ef
Added c++ tests for pointcloud
asahtik Jan 26, 2024
bea383e
Add intensity output
whoactuallycares Jan 31, 2024
adbd8c7
Bump core
asahtik Feb 1, 2024
36abd80
Merge pull request #967 from luxonis/tof_intensity
whoactuallycares Feb 2, 2024
cbe0c76
Added ability to set the lens position via a float, to enable a more …
zrezke Feb 5, 2024
2a4bff2
Update depthai-core
whoactuallycares Feb 9, 2024
ba29e0a
Merge pull request #977 from luxonis/tof_intensity
moratom Feb 9, 2024
99fca06
FW: fix CAM_C failing to stream in certain cases,
alex-luxonis Feb 13, 2024
c682f16
Added the initial version of the depthai binary. (#979)
zrezke Feb 15, 2024
c014e27
OAK-T Support (#957)
zrezke Feb 20, 2024
53601fb
Merge branch 'develop' of github.com:luxonis/depthai-python into poin…
asahtik Feb 21, 2024
393aa6d
Example fixes & improvements, bump fw
asahtik Feb 22, 2024
57c36aa
Clangformat
asahtik Feb 22, 2024
9f67ed8
Bugfix
asahtik Feb 22, 2024
8b8a4da
Default cam test (#845)
zrezke Feb 25, 2024
ebca0f2
Reduce amount of pointcloud copying
asahtik Feb 26, 2024
ee001db
Make cam_test.py available through the depthai binary. (#983)
zrezke Feb 26, 2024
b592eeb
Fix tests
asahtik Feb 26, 2024
4af09fd
Add colorized example for pointcloud
Feb 26, 2024
8bfa675
Implemented transformation matrix for pointcloud
asahtik Feb 28, 2024
daa90fb
Merge branch 'pointcloud' of github.com:luxonis/depthai-python into p…
asahtik Feb 28, 2024
1d8d790
Merge pull request #961 from luxonis/pointcloud
asahtik Feb 29, 2024
5248efe
Fixed windows build
asahtik Mar 4, 2024
3dcae95
Optimized getPoints
asahtik Mar 4, 2024
42c3a2d
Minor fixes
asahtik Mar 4, 2024
6a26eee
Enhance camera features (#987)
zrezke Mar 4, 2024
00f0d32
FW: -fix `setAutoExposureLimit` flicker during AF lens move,
alex-luxonis Mar 4, 2024
9cb7719
Merge pull request #989 from luxonis/pcl_fix_build
moratom Mar 4, 2024
e37db4f
Improve the pointcloud example to work with 30FPS
Mar 5, 2024
b505473
Change the example to camel case for consistency
Mar 5, 2024
50e3683
Minor fixes
Mar 5, 2024
ae4fa01
Merge pull request #991 from luxonis/improve_pointcloud_example
moratom Mar 5, 2024
7b33b42
Merge pull request #990 from luxonis/main
moratom Mar 5, 2024
37f6553
Print a nice error of Open3D is not installed
Mar 5, 2024
11b925f
Update the handling for uninstalled open3d
Mar 5, 2024
a2e419e
Merge pull request #992 from luxonis/improve_pointcloud_example
moratom Mar 5, 2024
e13e231
Bump version to 2.25.0.0
Mar 6, 2024
d3917a7
Add manylinux wheels for 32 bit arm
Mar 6, 2024
a03c585
Add only the wheel for bookworm
Mar 6, 2024
8402008
Don't install global packages
Mar 6, 2024
5a8a85d
Add missing PCL API & change th RH system
Mar 7, 2024
a579364
Update FW to develop
Mar 8, 2024
2b24633
Merge remote-tracking branch 'origin/main' into release_v2.25.0.0
Mar 8, 2024
0465260
Update core to main
Mar 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ jobs:
needs: build-docstrings
strategy:
matrix:
rpi-os: [rpi-buster, rpi-bullseye]
rpi-os: [rpi-buster, rpi-bullseye, rpi-bookworm]
runs-on: ${{ matrix.rpi-os }}
steps:
- name: Print home directory
Expand All @@ -155,7 +155,7 @@ jobs:
run: python3 -m pip wheel . -w ./wheelhouse/ --verbose
- name: Auditing wheels and adding armv6l tag (Running on RPi, binaries compiled as armv6l)
run: |
python3 -m pip install -U wheel auditwheel
# python3 -m pip install -U wheel auditwheel # Called once when setting up the runner
for whl in wheelhouse/*.whl; do auditwheel repair "$whl" --plat linux_armv7l -w wheelhouse/preaudited/; done
for whl in wheelhouse/preaudited/*.whl; do python3 -m wheel tags --platform-tag +linux_armv6l "$whl"; done
mkdir -p wheelhouse/audited/
Expand Down Expand Up @@ -556,8 +556,8 @@ jobs:
# event-type: python-hil-event
# client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'

notify_hil_workflow_linux_x86_64:
needs: [build-linux-x86_64]
notify_hil_workflow:
needs: [build-linux-armhf, build-linux-x86_64]
runs-on: ubuntu-latest
steps:
- name: Dispatch an action and get the run ID
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ depthai-core/build/

# builds
_builds/

.cache/
#git
*.orig
*_REMOTE_*
Expand All @@ -44,4 +44,4 @@ env.bak/
venv.bak/

# PyCharm
.idea/
.idea/
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ pybind11_add_module(${TARGET_NAME}
src/pipeline/node/WarpBindings.cpp
src/pipeline/node/UVCBindings.cpp
src/pipeline/node/ToFBindings.cpp
src/pipeline/node/PointCloudBindings.cpp
src/pipeline/node/SyncBindings.cpp
src/pipeline/node/MessageDemuxBindings.cpp

Expand All @@ -154,7 +155,8 @@ pybind11_add_module(${TARGET_NAME}
src/pipeline/datatype/SystemInformationBindings.cpp
src/pipeline/datatype/TrackedFeaturesBindings.cpp
src/pipeline/datatype/TrackletsBindings.cpp

src/pipeline/datatype/PointCloudConfigBindings.cpp
src/pipeline/datatype/PointCloudDataBindings.cpp
)

if(WIN32)
Expand Down
2 changes: 1 addition & 1 deletion depthai-core
Submodule depthai-core updated 37 files
+85 −2 CMakeLists.txt
+7 −2 README.md
+1 −1 cmake/Depthai/DepthaiDeviceSideConfig.cmake
+12 −0 cmake/config.hpp.in
+10 −0 cmake/depthaiDependencies.cmake
+108 −97 examples/CMakeLists.txt
+102 −0 examples/Camera/thermal_cam.cpp
+90 −0 examples/PointCloud/visualize_pointcloud.cpp
+2 −2 examples/bootloader/bootloader_version.cpp
+29 −1 include/depthai/common/CameraFeatures.hpp
+25 −0 include/depthai/common/StereoPair.hpp
+17 −0 include/depthai/device/DeviceBase.hpp
+13 −0 include/depthai/pipeline/datatype/CameraControl.hpp
+6 −0 include/depthai/pipeline/datatype/EncodedFrame.hpp
+5 −0 include/depthai/pipeline/datatype/ImgFrame.hpp
+69 −0 include/depthai/pipeline/datatype/PointCloudConfig.hpp
+205 −0 include/depthai/pipeline/datatype/PointCloudData.hpp
+3 −0 include/depthai/pipeline/datatypes.hpp
+69 −0 include/depthai/pipeline/node/PointCloud.hpp
+1 −0 include/depthai/pipeline/node/ToF.hpp
+2 −0 include/depthai/pipeline/nodes.hpp
+1 −1 shared/depthai-shared
+2 −2 src/device/DataQueue.cpp
+83 −16 src/device/DeviceBase.cpp
+1 −1 src/device/DeviceBootloader.cpp
+23 −0 src/pcl/PointCloudData.cpp
+10 −0 src/pipeline/datatype/CameraControl.cpp
+3 −0 src/pipeline/datatype/EncodedFrame.cpp
+4 −0 src/pipeline/datatype/ImgFrame.cpp
+47 −0 src/pipeline/datatype/PointCloudConfig.cpp
+118 −0 src/pipeline/datatype/PointCloudData.cpp
+16 −0 src/pipeline/datatype/StreamMessageParser.cpp
+27 −0 src/pipeline/node/PointCloud.cpp
+1 −1 src/pipeline/node/ToF.cpp
+2 −0 tests/CMakeLists.txt
+37 −0 tests/src/message_group_test.cpp
+70 −0 tests/src/pointcloud_test.cpp
Empty file added depthai_cli/__init__.py
Empty file.
49 changes: 49 additions & 0 deletions depthai_cli/depthai_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
from pathlib import Path
import subprocess

here = os.path.dirname(os.path.realpath(__file__))

if os.path.exists(os.path.join(here, "cam_test.py")): # Installed package
CAM_TEST_PATH = Path(here) / "cam_test.py"
else:
CAM_TEST_PATH = (
Path(here) / ".." / "utilities" / "cam_test.py"
) # Execution from source
CAM_TEST_PATH = str(CAM_TEST_PATH)


def cli() -> int:
import argparse
import sys
import depthai as dai
parser = argparse.ArgumentParser(description="DepthAI CLI", add_help=True)
parser.add_argument("-v", "--version", action="store_true", help="Print version and exit.")
parser.add_argument("-l", "--list-devices", action="store_true", help="List connected devices.")
subparsers = parser.add_subparsers(dest="command", help="Sub-commands")
# Define the parser for the "cam_test" command
cam_test_parser = subparsers.add_parser("cam_test", help="Commands and options for cam_test", add_help=False)
cam_test_parser.add_argument("args", nargs=argparse.REMAINDER, help="Arguments to pass to cam_test")

# subparser REMINDER args would get parsed too if we used parse_args, so we have to handle unknown args manually
args, unknown_args = parser.parse_known_args()
if args.command == "cam_test":
cam_test_path = CAM_TEST_PATH
return subprocess.run([sys.executable, cam_test_path] + cam_test_parser.parse_args().args[1:]).returncode
# Parse other subcommands here
elif unknown_args:
parser.error(f"Unrecognized arguments: {unknown_args}") # handles exit internally
elif args.version:
print(dai.__version__)
return 0
elif args.list_devices:
print(dai.Device.getAllConnectedDevices())
return 0
else:
# No recognized commands, print help
parser.print_help()
return 1


if __name__ == "__main__":
exit(cli())
107 changes: 107 additions & 0 deletions examples/Camera/thermal_cam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import depthai as dai
import cv2
import numpy as np

mouseX, mouseY = 0, 0


def onMouse(event, x, y, *args):
global mouseX, mouseY
mouseX = x
mouseY = y


device = dai.Device()
pipeline = dai.Pipeline()

# Thermal camera
thermalCam = pipeline.create(dai.node.Camera)
width, height = -1, -1
thermalFound = False
for features in device.getConnectedCameraFeatures():
if dai.CameraSensorType.THERMAL in features.supportedTypes:
thermalFound = True
thermalCam.setBoardSocket(features.socket)
width, height = features.width, features.height
break
if not thermalFound:
raise RuntimeError("No thermal camera found!")
thermalCam.setPreviewSize(width, height)

# Output raw: FP16 temperature data (degrees Celsius)
xoutRaw = pipeline.create(dai.node.XLinkOut)
xoutRaw.setStreamName("thermal_raw")
thermalCam.raw.link(xoutRaw.input)

# Output preview,video, isp: RGB or NV12 or YUV420 thermal image.
xoutImage = pipeline.create(dai.node.XLinkOut)
xoutImage.setStreamName("image")
thermalCam.preview.link(xoutImage.input)
device.startPipeline(pipeline)

qRaw = device.getOutputQueue("thermal_raw", 2, False)
qImage = device.getOutputQueue("image", 2, False)


RAW_WINDOW_NAME = "temperature"
IMAGE_WINDOW_NAME = "image"
# Scale 4x and position one next to another
cv2.namedWindow(RAW_WINDOW_NAME, cv2.WINDOW_NORMAL)
cv2.namedWindow(IMAGE_WINDOW_NAME, cv2.WINDOW_NORMAL)
cv2.moveWindow(RAW_WINDOW_NAME, 0, 0)
cv2.resizeWindow(RAW_WINDOW_NAME, width * 4, height * 4)
cv2.moveWindow(IMAGE_WINDOW_NAME, width * 4, 0)
cv2.resizeWindow(IMAGE_WINDOW_NAME, width * 4, height * 4)
cv2.setMouseCallback(RAW_WINDOW_NAME, onMouse)
cv2.setMouseCallback(IMAGE_WINDOW_NAME, onMouse)

while True:
inRaw = qRaw.get()
inImg = qImage.get()

# Retrieve one point of fp16 data
frame = inRaw.getCvFrame().astype(np.float32)
colormappedFrame = cv2.normalize(frame, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
colormappedFrame = cv2.applyColorMap(colormappedFrame, cv2.COLORMAP_MAGMA)
if (
mouseX < 0
or mouseY < 0
or mouseX >= frame.shape[1]
or mouseY >= frame.shape[0]
):
mouseX = max(0, min(mouseX, frame.shape[1] - 1))
mouseY = max(0, min(mouseY, frame.shape[0] - 1))
textColor = (255, 255, 255)
# Draw crosshair
cv2.line(
colormappedFrame,
(mouseX - 10, mouseY),
(mouseX + 10, mouseY),
textColor,
1,
)
cv2.line(
colormappedFrame,
(mouseX, mouseY - 10),
(mouseX, mouseY + 10),
textColor,
1,
)
# Draw deg C
text = f"{frame[mouseY, mouseX]:.2f} deg C"
putTextLeft = mouseX > colormappedFrame.shape[1] / 2
cv2.putText(
colormappedFrame,
text,
(mouseX - 100 if putTextLeft else mouseX + 10, mouseY - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
textColor,
1,
)
cv2.imshow(RAW_WINDOW_NAME, colormappedFrame)

cv2.imshow(IMAGE_WINDOW_NAME, inImg.getCvFrame())

if cv2.waitKey(1) == ord("q"):
break
114 changes: 114 additions & 0 deletions examples/PointCloud/visualize_pointcloud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import depthai as dai
from time import sleep
import numpy as np
import cv2
import time
import sys
try:
import open3d as o3d
except ImportError:
sys.exit("Critical dependency missing: Open3D. Please install it using the command: '{} -m pip install open3d' and then rerun the script.".format(sys.executable))

FPS = 30
class FPSCounter:
def __init__(self):
self.frameCount = 0
self.fps = 0
self.startTime = time.time()

def tick(self):
self.frameCount += 1
if self.frameCount % 10 == 0:
elapsedTime = time.time() - self.startTime
self.fps = self.frameCount / elapsedTime
self.frameCount = 0
self.startTime = time.time()
return self.fps

pipeline = dai.Pipeline()
camRgb = pipeline.create(dai.node.ColorCamera)
monoLeft = pipeline.create(dai.node.MonoCamera)
monoRight = pipeline.create(dai.node.MonoCamera)
depth = pipeline.create(dai.node.StereoDepth)
pointcloud = pipeline.create(dai.node.PointCloud)
sync = pipeline.create(dai.node.Sync)
xOut = pipeline.create(dai.node.XLinkOut)
xOut.input.setBlocking(False)


camRgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
camRgb.setBoardSocket(dai.CameraBoardSocket.CAM_A)
camRgb.setIspScale(1,3)
camRgb.setFps(FPS)

monoLeft.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
monoLeft.setCamera("left")
monoLeft.setFps(FPS)
monoRight.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
monoRight.setCamera("right")
monoRight.setFps(FPS)

depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
depth.initialConfig.setMedianFilter(dai.MedianFilter.KERNEL_7x7)
depth.setLeftRightCheck(True)
depth.setExtendedDisparity(False)
depth.setSubpixel(True)
depth.setDepthAlign(dai.CameraBoardSocket.CAM_A)

monoLeft.out.link(depth.left)
monoRight.out.link(depth.right)
depth.depth.link(pointcloud.inputDepth)
camRgb.isp.link(sync.inputs["rgb"])
pointcloud.outputPointCloud.link(sync.inputs["pcl"])
sync.out.link(xOut.input)
xOut.setStreamName("out")




with dai.Device(pipeline) as device:
isRunning = True
def key_callback(vis, action, mods):
global isRunning
if action == 0:
isRunning = False

q = device.getOutputQueue(name="out", maxSize=4, blocking=False)
pc = o3d.geometry.PointCloud()
vis = o3d.visualization.VisualizerWithKeyCallback()
vis.create_window()
vis.register_key_action_callback(81, key_callback)
pcd = o3d.geometry.PointCloud()
coordinateFrame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1000, origin=[0,0,0])
vis.add_geometry(coordinateFrame)

first = True
fpsCounter = FPSCounter()
while isRunning:
inMessage = q.get()
inColor = inMessage["rgb"]
inPointCloud = inMessage["pcl"]
cvColorFrame = inColor.getCvFrame()
# Convert the frame to RGB
cvRGBFrame = cv2.cvtColor(cvColorFrame, cv2.COLOR_BGR2RGB)
fps = fpsCounter.tick()
# Display the FPS on the frame
cv2.putText(cvColorFrame, f"FPS: {fps:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
cv2.imshow("color", cvColorFrame)
key = cv2.waitKey(1)
if key == ord('q'):
break
if inPointCloud:
t_before = time.time()
points = inPointCloud.getPoints().astype(np.float64)
pcd.points = o3d.utility.Vector3dVector(points)
colors = (cvRGBFrame.reshape(-1, 3) / 255.0).astype(np.float64)
pcd.colors = o3d.utility.Vector3dVector(colors)
if first:
vis.add_geometry(pcd)
first = False
else:
vis.update_geometry(pcd)
vis.poll_events()
vis.update_renderer()
vis.destroy_window()
25 changes: 23 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

### NAME
MODULE_NAME = 'depthai'
DEPTHAI_CLI_MODULE_NAME = 'depthai_cli'

### VERSION
here = os.path.abspath(os.path.dirname(__file__))
Expand Down Expand Up @@ -92,6 +93,20 @@ def run(self):
self.build_extension(ext)

def build_extension(self, ext):
if ext.name == DEPTHAI_CLI_MODULE_NAME:
# Copy cam_test.py and it's dependencies to depthai_cli/
cam_test_path = os.path.join(here, "utilities", "cam_test.py")
cam_test_dest = os.path.join(self.build_lib, DEPTHAI_CLI_MODULE_NAME, "cam_test.py")
cam_test_gui_path = os.path.join(here, "utilities", "cam_test_gui.py")
cam_test_gui_dest = os.path.join(self.build_lib, DEPTHAI_CLI_MODULE_NAME, "cam_test_gui.py")
stress_test_path = os.path.join(here, "utilities", "stress_test.py")
stress_test_dest = os.path.join(self.build_lib, DEPTHAI_CLI_MODULE_NAME, "stress_test.py")
files_to_copy = [(cam_test_path, cam_test_dest), (cam_test_gui_path, cam_test_gui_dest), (stress_test_path, stress_test_dest)]
for src, dst in files_to_copy:
with open(src, "r") as f:
with open(dst, "w") as f2:
f2.write(f.read())
return

extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
# required for auto-detection of auxiliary "native" libs
Expand Down Expand Up @@ -205,10 +220,11 @@ def build_extension(self, ext):
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/luxonis/depthai-python",
ext_modules=[CMakeExtension(MODULE_NAME)],
ext_modules=[CMakeExtension(MODULE_NAME), Extension(DEPTHAI_CLI_MODULE_NAME, sources=[])],
cmdclass={
'build_ext': CMakeBuild
'build_ext': CMakeBuild,
},
packages=[DEPTHAI_CLI_MODULE_NAME],
zip_safe=False,
classifiers=[
"Development Status :: 4 - Beta",
Expand All @@ -235,4 +251,9 @@ def build_extension(self, ext):
"Topic :: Software Development",
],
python_requires='>=3.6',
entry_points={
"console_scripts": [
f'depthai={DEPTHAI_CLI_MODULE_NAME}.depthai_cli:cli'
]
}
)
Loading