Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
108 changes: 56 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ tested compatibility with earlier SDK versions, please check out
- [File Camera]
- [Projector]
- **Maintenance and Prevention**
- [Benchmarking Your System]
- [Infield Correction]
- [Warm-up]
- [Firmware Update]
Expand Down Expand Up @@ -83,24 +84,21 @@ from the camera can be used.
- **info_util_other**
- [adapt_settings_for_flickering_ambient_light] - Adapt camera
acquisition settings based on known ambient light conditions.
- [camera_info] - Print version information for Python, zivid-python
and Zivid SDK, then list cameras and print camera info and state
for each connected camera.
- [camera_info] - Print Python, zivid-python and Zivid SDK versions,
then list each connected camera with info and state.
- [camera_user_data] - Store user data on the Zivid camera.
- [capture_with_diagnostics] - Capture a 2D+3D frame and a 2D frame
from the Zivid camera with diagnostics enabled.
- [check_health] - Poll the camera health check from a separate
thread while capturing in the main thread, printing the statuses
and values every second.
thread while capturing, printing statuses and values each second.
- [context_manager_with_zivid] - Sample showing how to use a context
manager with Zivid Application and safely return processed data.
- [firmware_updater] - Update firmware on the Zivid camera.
- [frame_info] - Read frame info from the Zivid camera.
- [get_camera_intrinsics] - Read intrinsic parameters from the Zivid
camera (OpenCV model) or estimate them from the point cloud.
- [measure_scene_conditions] - Measure ambient light conditions in
the scene and output the measured flickering frequency of the
ambient light if flickering is detected.
- [measure_scene_conditions] - Measure ambient light in the scene
and report the flickering frequency when flickering is detected.
- [warmup] - Short example of a basic way to warm up the camera with
specified time and capture cycle.
- **network**
Expand All @@ -117,6 +115,8 @@ from the camera can be used.
camera.
- [verify_camera_in_field_from_zdf] - Check the dimension trueness
of a Zivid camera from a ZDF file.
- [visualize_benchmark_results] - Visualize the CSV results produced
by the ZividBenchmark sample.
- **applications**
- **basic**
- **visualization**
Expand All @@ -132,7 +132,7 @@ from the camera can be used.
visualize it.
- **file_formats**
- [convert_zdf] - Convert point cloud data from a ZDF file to your
preferred format
preferred format.
- [read_iterate_zdf] - Read point cloud data from a ZDF file,
iterate through it, and extract individual points.
- **advanced**
Expand Down Expand Up @@ -161,23 +161,24 @@ from the camera can be used.
- [capture_and_process_image_with_cupy_on_cuda] - Demonstrate GPU
interop with CuPy: wrap a Zivid GPU image buffer as a CuPy array
without copying it through CPU memory.
- [capture_and_render_point_cloud_with_opengl_on_cuda] -
Demonstrate GPU point cloud rendering with CUDA-OpenGL interop:
capture a Zivid point cloud, copy it device-to-device
- [capture_and_segment_image_with_pytorch_on_cuda] - Demonstrate
zero-copy GPU interop between Zivid and PyTorch/CuPy by feeding
a Zivid 2D image into a third-party
- [capture_and_render_point_cloud_with_opengl_on_cuda] - Render a
Zivid point cloud interactively by copying it device-to-device
into OpenGL buffers with CUDA interop.
- [capture_and_segment_image_with_pytorch_on_cuda] - Feed a Zivid
2D image into a third-party segmentation model on the GPU
without a CPU round-trip.
- **transform**
- [get_checkerboard_pose_from_zdf] - Read point cloud data of a
Zivid calibration board from a ZDF file, estimate the
- [get_checkerboard_pose_from_zdf] - Estimate the checkerboard
pose from a ZDF file of a Zivid calibration board and save it to
YAML.
- [transform_point_cloud_from_millimeters_to_meters] - Transform
point cloud data from millimeters to meters.
- [transform_point_cloud_via_aruco_marker] - Transform a point
cloud from camera to ArUco marker coordinate frame by estimating
the marker's pose from the point cloud.
cloud from camera to ArUco marker coordinate frame using the
marker's estimated pose.
- [transform_point_cloud_via_checkerboard] - Transform a point
cloud from camera to checkerboard (Zivid Calibration Board)
coordinate frame by getting checkerboard pose from the API.
cloud from camera to checkerboard coordinate frame using the
pose from the API.
- **roi**
- [roi_box_via_aruco_marker] - Filter the point cloud based on a
ROI box given relative to the ArUco marker on a Zivid
Expand All @@ -186,8 +187,8 @@ from the camera can be used.
ROI box given relative to the Zivid Calibration Board.
- **stitching**
- [stitch_continuously_rotating_object] - Stitch point clouds from
a continuously rotating object without pre-alignment using Local
Point Cloud Registration and apply Voxel Downsample.
a continuously rotating object using Local Point Cloud
Registration, then downsample.
- [stitch_using_robot_mounted_camera] - Stitch multiple point
clouds captured with a robot mounted camera.
- [stitch_via_local_point_cloud_registration] - Stitch two point
Expand All @@ -198,16 +199,17 @@ from the camera can be used.
barcodes from a 2D capture.
- **hand_eye_calibration**
- [hand_eye_calibration] - Perform Hand-Eye calibration.
- [hand_eye_gui] - Hand-Eye Calibration GUI
- [hand_eye_gui] - Hand-Eye Calibration GUI.
- [pose_conversion_gui] - Convert between different rotation
formats with a GUI:
formats with a GUI.
- [pose_conversions] - Convert to/from Transformation Matrix
(Rotation Matrix + Translation Vector).
- [utilize_hand_eye_calibration] - Transform single data point or
entire point cloud from camera to robot base reference frame
using Hand-Eye calibration
- [utilize_hand_eye_calibration] - Transform a data point or
entire point cloud from camera to robot base frame using the
Hand-Eye calibration matrix.
- [verify_hand_eye_with_visualization] - Verify hand-eye
calibration by transforming all dataset point clouds and
visualizing them overlapped.
- **ur_hand_eye_calibration**
- [universal_robots_perform_hand_eye_calibration] - Script to
generate a dataset and perform hand-eye calibration using a
Expand All @@ -219,49 +221,49 @@ from the camera can be used.
with a robot to verify Hand-Eye Calibration using the RoboDK
interface.
- **multi_camera**
- [multi_camera_calibration] - Use captures of a calibration
object to generate transformation matrices to a single
coordinate frame, from multiple connected cameras.
- [multi_camera_calibration_from_zdf] - Use captures of a
calibration object to generate transformation matrices to a
single coordinate frame, from ZDF files captured with multiple
- [multi_camera_calibration] - Generate transformation matrices to
a single coordinate frame from captures by multiple connected
cameras.
- [stitch_by_transformation] - Use transformation matrices from
Multi-Camera calibration to transform point clouds into a single
coordinate frame, from connected cameras.
- [stitch_by_transformation_from_zdf] - Use transformation
matrices from Multi-Camera calibration to transform point clouds
into single coordinate frame, from a ZDF files.
- [multi_camera_calibration_from_zdf] - Generate transformation
matrices to a single coordinate frame from multi-camera ZDF
captures.
- [stitch_by_transformation] - Transform point clouds from
connected cameras into one coordinate frame using Multi-Camera
calibration.
- [stitch_by_transformation_from_zdf] - Transform point clouds
from ZDF files into one coordinate frame using Multi-Camera
calibration.
- **projector**
- [project_and_find_marker] - Show a marker using the projector,
capture a set of 2D images to find the marker coordinates (2D
and 3D).
- [read_project_and_capture_image] - Read a 2D image from file and
project it using the camera projector.
- [reproject_points] - Illuminate checkerboard (Zivid Calibration
Board) centers by getting the checkerboard feature points
Board) centers by getting the checkerboard feature points.
- **robot_guidance**
- [robodk_robot_guidance] - Guide the robot to follow a path on
the Zivid Calibration Board.
- **modules**
- **zividsamples**
- [calibration_board_utils] - Utility functions for the Zivid
calibration board.
- [camera_verification] - def capture_and_measure_from_frame(frame:
zivid.Frame) -\> VerificationAndState:
- [color_to_grayscale] - if rgba_image.ndim != 3 or
rgba_image.shape\[2\] != 4:
- [camera_verification] - Capture and measure the infield
verification state of a Zivid camera.
- [color_to_grayscale] - Convert Zivid RGBA color images to
grayscale.
- [display] - Display relevant data for Zivid Samples.
- [paths] - Get relevant paths for Zivid Samples.
- [robodk_tools] - Robot Control Module
- [robodk_tools] - Connect to a robot through RoboDK, list its
targets and set its speeds.
- [save_load_matrix] - Save and load Zivid 4x4 transformation
matrices from and to YAML files.
- [save_load_transformation_matrix] -
assert_affine_matrix_and_save(transformation_matrix.as_matrix(),
yaml_path)
- [save_residuals] - per_pose_residuals = \[
- [settings_utils] - categories =
zivid.presets.categories2d(camera.info.model)
- [save_load_transformation_matrix] - Save and load Zivid
transformation matrices to and from YAML files.
- [save_residuals] - Save per-pose hand-eye calibration residuals to
a YAML file.
- [settings_utils] - Pick and adjust Zivid capture settings for the
samples.
- [transformation_matrix] - Convenience functions and a class for
4x4 transformation matrices.
- [white_balance_calibration] - Balance color for 2D capture using
Expand Down Expand Up @@ -340,6 +342,7 @@ Zivid Samples are distributed under the [BSD license].
[2D + 3D Capture Strategy]: https://support.zivid.com/en/latest/camera/academy/camera/2d3d-capture-strategy.html
[File Camera]: https://support.zivid.com/en/latest/camera/academy/camera/file-camera.html
[Projector]: https://support.zivid.com/en/latest/camera/academy/camera/2d-image-projection.html
[Benchmarking Your System]: https://support.zivid.com/en/latest/camera/api-reference/benchmarks/benchmarking-your-system.html
[Infield Correction]: https://support.zivid.com/en/latest/camera/academy/camera/infield-correction.html
[Warm-up]: https://support.zivid.com/en/latest/camera/academy/camera/warmup.html
[Firmware Update]: https://support.zivid.com/en/latest/camera/academy/camera/firmware-update.html
Expand Down Expand Up @@ -378,6 +381,7 @@ Zivid Samples are distributed under the [BSD license].
[reset_camera_in_field]: https://github.com/zivid/zivid-python-samples/tree/master/source/camera/maintenance/reset_camera_in_field.py
[verify_camera_in_field]: https://github.com/zivid/zivid-python-samples/tree/master/source/camera/maintenance/verify_camera_in_field.py
[verify_camera_in_field_from_zdf]: https://github.com/zivid/zivid-python-samples/tree/master/source/camera/maintenance/verify_camera_in_field_from_zdf.py
[visualize_benchmark_results]: https://github.com/zivid/zivid-python-samples/tree/master/source/camera/maintenance/visualize_benchmark_results.py
[capture_and_visualize_normals]: https://github.com/zivid/zivid-python-samples/tree/master/source/applications/basic/visualization/capture_and_visualize_normals.py
[capture_from_file_camera_vis_3d]: https://github.com/zivid/zivid-python-samples/tree/master/source/applications/basic/visualization/capture_from_file_camera_vis_3d.py
[capture_vis_3d]: https://github.com/zivid/zivid-python-samples/tree/master/source/applications/basic/visualization/capture_vis_3d.py
Expand Down
1 change: 1 addition & 0 deletions modules/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies = [
"pyqtgraph",
"robodk",
"scipy",
"seaborn",
"zivid",
"urrtde @ git+https://github.com/UniversalRobots/RTDE_Python_Client_Library.git@v2.7.12"
]
Expand Down
5 changes: 5 additions & 0 deletions modules/zividsamples/camera_verification.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Capture and measure the infield verification state of a Zivid camera.

"""

import random
from dataclasses import dataclass
from datetime import datetime, timedelta
Expand Down
5 changes: 5 additions & 0 deletions modules/zividsamples/color_to_grayscale.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Convert Zivid RGBA color images to grayscale.

"""

import numpy as np


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def run(self) -> None:
break

detection_result = (
zivid.calibration.detect_feature_points(camera_frame.point_cloud())
zivid.calibration.detect_calibration_board(camera_frame)
if self._calibration_object == CalibrationObject.Checkerboard
else zivid.calibration.detect_markers(
camera_frame, self._marker_configuration.id_list, self._marker_configuration.dictionary
Expand Down Expand Up @@ -303,7 +303,7 @@ def run(self) -> None:
break

detection_result = (
zivid.calibration.detect_feature_points(camera_frame.point_cloud())
zivid.calibration.detect_calibration_board(camera_frame)
if self._calibration_object == CalibrationObject.Checkerboard
else zivid.calibration.detect_markers(
camera_frame, self._marker_configuration.id_list, self._marker_configuration.dictionary
Expand Down
3 changes: 2 additions & 1 deletion modules/zividsamples/robodk_tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""
Robot Control Module
Connect to a robot through RoboDK, list its targets and set its speeds.

Module interfaces with the python API for RoboDK and the RoboDK software.
It can be used to connect to the specified robot, get a list of targets and set robot speeds.

Expand Down
5 changes: 5 additions & 0 deletions modules/zividsamples/save_load_transformation_matrix.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Save and load Zivid transformation matrices to and from YAML files.

"""

from pathlib import Path

from zividsamples.save_load_matrix import assert_affine_matrix_and_save, load_and_assert_affine_matrix
Expand Down
5 changes: 5 additions & 0 deletions modules/zividsamples/save_residuals.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Save per-pose hand-eye calibration residuals to a YAML file.

"""

from pathlib import Path
from typing import Iterable

Expand Down
5 changes: 5 additions & 0 deletions modules/zividsamples/settings_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Pick and adjust Zivid capture settings for the samples.

"""

from datetime import timedelta

import numpy as np
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
results on the GPU and pass them straight to the next consumer (PyTorch, OpenGL, a CUDA kernel, etc.) -- see the related
samples `capture_and_segment_image_with_pytorch_on_cuda.py` and `capture_and_render_point_cloud_with_opengl_on_cuda.py`.

zivid-python implements `__cuda_array_interface__` on DeviceArray, so `cp.asarray(device_array)` is the whole handoff:
CuPy picks up the device pointer, dtype, shape and strides, and holds the DeviceArray as the buffer's owner. Avoid
building the array from `cp.cuda.UnownedMemory` with something else passed as `owner` -- the buffer belongs to the
DeviceArray, not to the frame or point cloud it came from, and getting that wrong frees GPU memory that CuPy still
points at.

Requirements:
- CUDA-capable GPU
- CuPy installed: pip install cupy-cuda12x (adjust for your CUDA version)
Expand Down Expand Up @@ -49,46 +55,28 @@ def _main() -> None:
cuda_stream = zivid.CUDAStreamPtr() # Default stream

print("Getting GPU device buffer in float format (RGBAf32)")
# The DeviceArray is synchronized into cuda_stream at acquisition, so the
# device pointer below is a plain accessor that needs no further synchronization.
# The DeviceArray is synchronized into cuda_stream at acquisition, so it can be handed
# to CuPy directly without any further synchronization.
device_array = frame_2d.image_device_array(cuda_stream, zivid.PixelFormat.RGBAF)

print("Getting device pointer")
device_ptr = device_array.device_pointer()
height = device_array.shape[0]
width = device_array.shape[1]
row_stride_bytes = device_array.strides_in_bytes[0]
row_stride_elements = device_array.strides[0]
total_size_bytes = device_array.size_bytes

print(f"Device pointer: {hex(device_ptr)}")
print(f"Device pointer: {hex(device_array.device_pointer())}")
print(
f"Buffer: {width}x{height}, stride={row_stride_bytes} bytes, {row_stride_elements} elements, total size={total_size_bytes} bytes"
f"Buffer: {device_array.shape[1]}x{device_array.shape[0]}, "
f"stride={device_array.strides_in_bytes[0]} bytes, total size={device_array.size_bytes} bytes"
)

print(
"Wrapping Zivid's GPU buffer as a CuPy memory pointer (this is the zero-copy step; Zivid still owns the memory)"
)
# Note: RGBAf32 format = 4 channels of float32
unowned_memory = cp.cuda.UnownedMemory(device_ptr, total_size_bytes, owner=device_array)
unowned_memory_ptr = cp.cuda.MemoryPointer(unowned_memory, 0)

print("Creating array with correct shape accounting for stride")
row_elements = row_stride_elements
# pylint: disable-next=unexpected-keyword-arg
flat_array = cp.ndarray(shape=(height * row_elements,), dtype=cp.float32, memptr=unowned_memory_ptr)

print("Reshaping array to image size (height, width, 4 channels)")
# If stride equals width*16, direct reshape is possible
if row_stride_bytes == width * 16:
image_array = flat_array.reshape((height, width, 4))
else:
# Handling stride memory by slicing
image_array = flat_array.reshape((height, row_elements))[:, : width * 4].reshape((height, width, 4))
print("Wrapping Zivid's GPU buffer as a CuPy array (this is the zero-copy step; Zivid still owns the memory)")
print("cp.asarray reads __cuda_array_interface__, so shape, dtype and strides come across automatically,")
print("and CuPy holds the DeviceArray as the buffer's owner so the GPU memory cannot be freed too early")
image_array = cp.asarray(device_array)

print(f"CuPy array shape: {image_array.shape}")
print(f"CuPy array dtype: {image_array.dtype}")

if image_array.data.ptr != device_array.device_pointer():
raise RuntimeError("Zero-copy check failed: CuPy array does not share the Zivid device pointer")
print("Zero-copy verified: CuPy array shares the Zivid device pointer")

print("Example: Computing mean color on GPU")
mean_rgba = cp.mean(image_array, axis=(0, 1))
print(f"Mean RGBA values: R={mean_rgba[0]:.3f}, G={mean_rgba[1]:.3f}, B={mean_rgba[2]:.3f}, A={mean_rgba[3]:.3f}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""
Demonstrate GPU point cloud rendering with CUDA-OpenGL interop: capture a Zivid point cloud, copy it device-to-device
into OpenGL vertex buffers, and render it interactively.
Render a Zivid point cloud interactively by copying it device-to-device into OpenGL buffers with CUDA interop.

The point cloud data never goes through CPU memory: Zivid produces it on the GPU as a DeviceArray, CUDA copies it
directly into the OpenGL VBOs (the interop step), and OpenGL renders from those buffers. The CUDA-OpenGL interop happens
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""
Demonstrate zero-copy GPU interop between Zivid and PyTorch/CuPy by feeding a Zivid 2D image into a third-party
segmentation model without a CPU round-trip.
Feed a Zivid 2D image into a third-party segmentation model on the GPU without a CPU round-trip.

DISCLAIMER: Zivid does not provide segmentation, and Zivid does not support the third-party libraries used in this
sample. The segmentation model (DeepLabV3 from torchvision) and the GPU interop libraries (PyTorch, CuPy) are external
Expand Down
Loading
Loading