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
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ from the camera can be used.
- [get\_checkerboard\_pose\_from\_zdf](https://github.com/zivid/zivid-python-samples/tree/master/source/applications/advanced/get_checkerboard_pose_from_zdf.py) - Read point cloud data of a Zivid calibration board from a
ZDF file, estimate the
- [hand\_eye\_calibration](https://github.com/zivid/zivid-python-samples/tree/master/source/applications/advanced/hand_eye_calibration/hand_eye_calibration.py) - Perform Hand-Eye calibration.
- [mask\_point\_cloud](https://github.com/zivid/zivid-python-samples/tree/master/source/applications/advanced/mask_point_cloud.py) - Read point cloud data from a ZDF file, apply a binary
mask, and visualize it.
- [project\_and\_find\_marker](https://github.com/zivid/zivid-python-samples/tree/master/source/applications/advanced/project_and_find_marker.py) - 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](https://github.com/zivid/zivid-python-samples/tree/master/source/applications/advanced/read_project_and_capture_image.py) - Read a 2D image from file and project it using the camera
Expand Down Expand Up @@ -205,10 +203,10 @@ Note that Open3D is not available for Python 3.13 and later.
-----

1. [Install Zivid
Software](https://support.zivid.com/latest//getting-started/software-installation.html).
Software](https://support.zivid.com/en/latest//camera/getting-started/software-installation.html).

2. [Download Zivid Sample
Data](https://support.zivid.com/latest//api-reference/samples/sample-data.html).
Data](https://support.zivid.com/en/latest//camera/api-reference/samples/sample-data.html).

3. Check out the Zivid Python samples repository:

Expand Down Expand Up @@ -252,9 +250,9 @@ Note that Open3D is not available for Python 3.13 and later.
## Support

For more information about the Zivid cameras, please visit our
[Knowledge Base](https://support.zivid.com/latest). If you run into any
issues please check out
[Troubleshooting](https://support.zivid.com/latest/support/troubleshooting.html).
[Knowledge Base](https://support.zivid.com/en/latest). If you run into
any issues please check out
[Troubleshooting](https://support.zivid.com/en/latest/camera/support/troubleshooting.html).

## License

Expand Down
21 changes: 0 additions & 21 deletions modules/zividsamples/color_to_grayscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,3 @@ def convert_rgba_to_grayscale(rgba_image: np.ndarray) -> np.ndarray:
if rgba_image.ndim != 3 or rgba_image.shape[2] != 4:
raise ValueError("Input image must be a RGBA image.")
return np.dot(rgba_image[..., :3], [0.299, 0.587, 0.114])


def convert_bgra_to_grayscale(bgra_image: np.ndarray) -> np.ndarray:
"""Convert BGRA image to grayscale using the luminance method.

The luminance method uses the formula:
Y = 0.299 * R + 0.587 * G + 0.114 * B
where R, G, B are the red, green, and blue channels of the image.

Args:
bgra_image (numpy.ndarray): Input BGRA image.

Raises:
ValueError: If the input image is not a BGRA image.

Returns:
numpy.ndarray: Grayscale image.
"""
if bgra_image.ndim != 3 or bgra_image.shape[2] != 4:
raise ValueError("Input image must be a BGRA image.")
return np.dot(bgra_image[..., :3], [0.114, 0.587, 0.299])
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,6 @@ def _translation_to_string(self, translation: NDArray[Shape["3"], Float32]) -> s
return f"{translation[0]:>8.1f}, {translation[1]:>8.1f}, {translation[2]:.1f}"


def directory_has_pose_pair_data(directory: Path) -> bool:
return (
len(list(directory.glob("robot_pose_*.yaml"))) > 0
and len(list(directory.glob("calibration_object_pose_*.zdf"))) > 0
)


class _PosePairLoadWorker(QObject):
"""Loads pose pair data from disk in a background thread."""

Expand Down
22 changes: 15 additions & 7 deletions modules/zividsamples/gui/preparation/warmup_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,24 @@ def rate_of_change_data(self) -> NDArray[Shape["N"], Float32]: # type: ignore
return self.df["average_rate_of_change"].to_numpy()

def temperature_is_stable(self) -> bool:
if not self.has_enough_data_to_analyze():
return False

# Ensure minimum warmup time of 1 minute has passed
now = self.df["timestamp"].iloc[-1]
warmup_start_time = self.df["timestamp"].iloc[0]
elapsed_time = now - warmup_start_time
if elapsed_time < timedelta(minutes=1):
return False

one_minute_ago = now - timedelta(minutes=1)
last_minute_of_data = self.df[self.df["timestamp"] >= one_minute_ago]
max_rate_of_change_in_the_last_minute = last_minute_of_data["average_rate_of_change"].max()
if self.has_enough_data_to_analyze():
return (
self.df["average_rate_of_change"].iloc[-1] is not None
and max_rate_of_change_in_the_last_minute <= self.temperature_change_threshold_degrees_per_minute
)
return False
max_rate_of_change_in_the_last_minute = float(last_minute_of_data["average_rate_of_change"].max())

return (
self.df["average_rate_of_change"].iloc[-1] is not None
and max_rate_of_change_in_the_last_minute <= self.temperature_change_threshold_degrees_per_minute
)

def temperature_is_changing_fast(self) -> bool:
return self.df["average_rate_of_change"].iloc[-1] > 2 * self.temperature_change_threshold_degrees_per_minute
Expand Down
13 changes: 1 addition & 12 deletions modules/zividsamples/gui/widgets/image_viewer.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
from PyQt5.QtCore import QRectF, QSize, Qt, pyqtSlot
from PyQt5.QtCore import QRectF, Qt, pyqtSlot
from PyQt5.QtGui import QImage, QPainter, QPixmap
from PyQt5.QtWidgets import QDialog, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QVBoxLayout
from zividsamples.gui.qt_application import ZividColors, color_as_qcolor


def error_message_pixmap(error_message: str, size: QSize) -> QPixmap:
error_pixmap = QPixmap(size)
error_pixmap.fill(color_as_qcolor(ZividColors.ITEM_BACKGROUND, 0.5))
painter = QPainter(error_pixmap)
painter.setPen(color_as_qcolor(ZividColors.PINK, 1))
painter.drawText(error_pixmap.rect(), Qt.AlignCenter | Qt.TextWordWrap, error_message)
painter.end()
return error_pixmap


class ImageViewer(QGraphicsView):
Expand Down
4 changes: 2 additions & 2 deletions modules/zividsamples/gui/widgets/live_2d_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def update_exposure_based_on_relative_brightness(self, settings_2d: zivid.Settin
rgba_with_projector = self.capture_function(settings_2d).image_srgb().copy_data()
grayscale_with_projector = self.rgb_to_grayscale(rgba_with_projector)
for acquisition in settings_2d.acquisitions:
acquisition.brightness = 0.0
acquisition.brightness = 0.1
rgba_without_projector = self.capture_function(settings_2d).image_srgb().copy_data()
grayscale_without_projector = self.rgb_to_grayscale(rgba_without_projector)
grayscale_without_projector[grayscale_without_projector == 0] = np.nan
Expand All @@ -82,7 +82,7 @@ def update_exposure_based_on_relative_brightness(self, settings_2d: zivid.Settin
else relative_brightness / (exposure_increase / current_exposure_time)
)
acquisition.gain = max(1.0, min(acquisition.gain * remaining_relative_brightness, 16.0))
acquisition.brightness = 0.0
acquisition.brightness = 0.1
return settings_2d

def update_settings_2d(self, settings_2d: zivid.Settings2D, camera_model: str):
Expand Down
15 changes: 0 additions & 15 deletions modules/zividsamples/gui/widgets/pose_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,6 @@
from zividsamples.transformation_matrix import TransformationMatrix


def wrap_path(path: Path, wrap_length: int) -> str:
parts = path.parts # Get parts of the Path
wrapped_lines = []
current_line = parts[0]
divider = "/" if current_line.endswith(":") else "\\"
for part in parts[1:]:
if len(f"{current_line}{divider}{part}") > wrap_length:
wrapped_lines.append(f"{current_line}{divider}")
current_line = part
else:
current_line = f"{current_line}{divider}{part}"
wrapped_lines.append(current_line)
return "\n".join(wrapped_lines)


class PoseWidgetDisplayMode(Enum):
OnlyPose = 0
Basic = 1
Expand Down
9 changes: 1 addition & 8 deletions modules/zividsamples/gui/wizard/marker_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Dict, List, Optional

import numpy as np
from nptyping import Float32, NDArray, Shape, UInt8
from nptyping import NDArray, Shape, UInt8
from PyQt5.QtCore import QRegExp, QSettings
from PyQt5.QtGui import QImage, QPixmap, QValidator
from PyQt5.QtWidgets import (
Expand All @@ -16,7 +16,6 @@
QVBoxLayout,
QWidget,
)
from scipy.spatial.transform import Rotation
from zivid.calibration import MarkerDictionary, MarkerShape
from zivid.experimental import PixelMapping
from zividsamples.gui.qt_application import ZividQtApplication
Expand All @@ -35,12 +34,6 @@ def generate_marker_dictionary(markers: List[MarkerShape]) -> Dict[str, MarkerSh
return marker_dict


def marker_angle(rotation_matrix: NDArray[Shape["3, 3"], Float32]) -> float: # type: ignore
rotation = Rotation.from_matrix(rotation_matrix)
rotvec = rotation.as_rotvec()
return np.degrees(np.linalg.norm(rotvec))


class TouchMarkerWidget(QWidget):
marker_id: int = 1
marker_dictionary: str = MarkerDictionary.aruco4x4_50
Expand Down
117 changes: 0 additions & 117 deletions source/applications/advanced/mask_point_cloud.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def _options() -> argparse.Namespace:
parser.add_argument(
"--full-resolution",
action="store_true",
default=False,
help="Use full resolution for stitching. If not set, downsampling is applied.",
)

Expand All @@ -77,8 +78,8 @@ def _stitch_point_clouds(directory: Path, full_resolution: bool) -> zivid.Unorga
ValueError: If the number of ZDF files and robot pose files do not match.

"""
zdf_files = list(directory.rglob("capture_*.zdf"))
pose_files = list(directory.rglob("robot_pose_*.yaml"))
zdf_files = sorted(list(directory.rglob("capture_*.zdf")))
pose_files = sorted(list(directory.rglob("robot_pose_*.yaml")))

if not zdf_files or not pose_files or not (directory / "hand_eye_transform.yaml").exists():
raise FileNotFoundError("Required files are missing in the directory.")
Expand Down
Loading
Loading