From 7726b69e1db3edbf89e27d66bff35e2064d2e261 Mon Sep 17 00:00:00 2001 From: John Ingve Olsen Date: Wed, 20 Nov 2024 16:45:33 +0100 Subject: [PATCH] Implement Frame.frame_2d --- modules/zivid/frame.py | 31 +++++++++++++++++++++++ src/ReleasableFrame.cpp | 3 ++- src/include/ZividPython/ReleasableFrame.h | 10 ++++++++ test/test_camera_capture.py | 9 +++++++ test/test_frame.py | 8 ++++++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/modules/zivid/frame.py b/modules/zivid/frame.py index 751675fb..048c6324 100644 --- a/modules/zivid/frame.py +++ b/modules/zivid/frame.py @@ -8,6 +8,7 @@ from zivid.camera_state import _to_camera_state from zivid.frame_info import _to_frame_info from zivid.point_cloud import PointCloud +from zivid.frame_2d import Frame2D class Frame: @@ -52,6 +53,36 @@ def point_cloud(self): """ return PointCloud(self.__impl.point_cloud()) + def frame_2d(self): + """Get 2D frame from 2D+3D frame. + + If the frame is the result of a 2D+3D capture, this method returns the 2D frame contained in the 2D+3D frame. In + the case of a 3D-only capture, this method returns None. + + If the frame was captured by an SDK version prior to 2.14.0, then this method will return None. + + If the 2D frame is not yet available because the capture is still in-progress, then this method will block until + acquisition of the entire 2D+3D capture is done. If you need to access the 2D frame before the 3D acquisition + has finished, then it is required to do separate 2D and 3D captures. + + In a 2D+3D capture, the 2D color image and 3D point cloud may have different resolutions depending on the pixel + sampling settings used. The 2D pixel sampling setting determines the resolution of the 2D color image whereas + the 3D pixel sampling setting and the resampling setting determines the resolution of the 3D point cloud. The 2D + color image returned in this 2D frame will always have the same resolution as the 2D color image that was + captured. On the other hand, the point cloud colors will be sampled from the 2D color image to match the + resolution of the 3D point cloud. The point cloud colors will always have a 1:1 correspondence with the 3D point + cloud resolution. See `PointCloud` for more information. + + Returns: + A Frame instance containing the 2D frame, or None if the frame was captured without 2D color or by an SDK + version prior to 2.14.0. + """ + return ( + Frame2D(self.__impl.frame_2d()) + if self.__impl.frame_2d() is not None + else None + ) + def save(self, file_path): """Save the frame to file. The file type is determined from the file extension. diff --git a/src/ReleasableFrame.cpp b/src/ReleasableFrame.cpp index 339a56ac..aa8266bb 100644 --- a/src/ReleasableFrame.cpp +++ b/src/ReleasableFrame.cpp @@ -16,6 +16,7 @@ namespace ZividPython .def_property_readonly("state", &ReleasableFrame::state) .def_property_readonly("info", &ReleasableFrame::info) .def_property_readonly("camera_info", &ReleasableFrame::cameraInfo) - .def("point_cloud", &ReleasableFrame::pointCloud); + .def("point_cloud", &ReleasableFrame::pointCloud) + .def("frame_2d", &ReleasableFrame::frame2D); } } // namespace ZividPython diff --git a/src/include/ZividPython/ReleasableFrame.h b/src/include/ZividPython/ReleasableFrame.h index 56a87294..0c175ecc 100644 --- a/src/include/ZividPython/ReleasableFrame.h +++ b/src/include/ZividPython/ReleasableFrame.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -15,6 +16,15 @@ namespace ZividPython ZIVID_PYTHON_FORWARD_1_ARGS(save, const std::string &, fileName) ZIVID_PYTHON_FORWARD_1_ARGS(load, const std::string &, fileName) ZIVID_PYTHON_FORWARD_0_ARGS_WRAP_RETURN(ReleasablePointCloud, pointCloud) + std::optional frame2D() + { + auto frame = impl().frame2D(); + if(!frame.has_value()) + { + return std::nullopt; + } + return ReleasableFrame2D{ std::move(frame.value()) }; + } ZIVID_PYTHON_FORWARD_0_ARGS(settings) ZIVID_PYTHON_FORWARD_0_ARGS(state) ZIVID_PYTHON_FORWARD_0_ARGS(info) diff --git a/test/test_camera_capture.py b/test/test_camera_capture.py index 6a1e6706..eeed4a4e 100644 --- a/test/test_camera_capture.py +++ b/test/test_camera_capture.py @@ -16,6 +16,8 @@ def test_capture_2d_3d_one_2d_and_one_3d(shared_file_camera): assert len(frame.settings.acquisitions) == 1 assert frame.settings.color assert len(frame.settings.color.acquisitions) == 1 + assert frame.frame_2d() + assert isinstance(frame.frame_2d(), zivid.Frame2D) def test_capture_2d_3d_two_2d_and_one_3d(shared_file_camera): @@ -33,6 +35,8 @@ def test_capture_2d_3d_two_2d_and_one_3d(shared_file_camera): assert len(frame.settings.acquisitions) == 1 assert frame.settings.color assert len(frame.settings.color.acquisitions) == 2 + assert frame.frame_2d() + assert isinstance(frame.frame_2d(), zivid.Frame2D) def test_capture_2d_3d_one_2d_and_two_3d(shared_file_camera): @@ -50,6 +54,8 @@ def test_capture_2d_3d_one_2d_and_two_3d(shared_file_camera): assert len(frame.settings.acquisitions) == 2 assert frame.settings.color assert len(frame.settings.color.acquisitions) == 1 + assert frame.frame_2d() + assert isinstance(frame.frame_2d(), zivid.Frame2D) def test_capture_2d_3d_two_2d_and_two_3d(shared_file_camera): @@ -67,6 +73,8 @@ def test_capture_2d_3d_two_2d_and_two_3d(shared_file_camera): assert len(frame.settings.acquisitions) == 2 assert frame.settings.color assert len(frame.settings.color.acquisitions) == 2 + assert frame.frame_2d() + assert isinstance(frame.frame_2d(), zivid.Frame2D) def test_capture_3d_one_acquisition(shared_file_camera): @@ -79,6 +87,7 @@ def test_capture_3d_one_acquisition(shared_file_camera): assert isinstance(frame, zivid.frame.Frame) assert len(frame.settings.acquisitions) == 1 assert frame.settings.color is None + assert frame.frame_2d() is None def test_capture_2d_with_settings_2d(shared_file_camera): diff --git a/test/test_frame.py b/test/test_frame.py index bc4f27e2..487cdfcb 100644 --- a/test/test_frame.py +++ b/test/test_frame.py @@ -19,6 +19,14 @@ def test_point_cloud(frame): assert isinstance(point_cloud, zivid.PointCloud) +def test_frame_2d(frame): + import zivid + + frame_2d = frame.frame_2d() + assert frame_2d + assert isinstance(frame_2d, zivid.Frame2D) + + def test_path_init(application, frame_file): from pathlib import Path import zivid