From deb99c6ef009515b0a6be8678fb23a7f9f636548 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 20 Feb 2024 09:49:46 +0530 Subject: [PATCH 01/21] video on a cube --- docs/examples/viz_play_cube.py | 77 ++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 docs/examples/viz_play_cube.py diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py new file mode 100644 index 000000000..63832a9f1 --- /dev/null +++ b/docs/examples/viz_play_cube.py @@ -0,0 +1,77 @@ +""" +======================================================= +Play a video in the 3D world +======================================================= + +The goal of this demo is to show how to visualize a video +on a cube by updating a texture. +""" + +import cv2 +import vtk + +import numpy as np + +from fury import actor, window +from fury.lib import numpy_support + +def texture_on_cube(image): + """ + Map an RGB texture on a cube. + + Parameters: + ----------- + image : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + + Returns: + -------- + actor : Actor + """ + + grid = vtk.vtkImageData() + grid.SetDimensions(image.shape[1], image.shape[0], 1) + vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) + vtkarr.SetName('Image') + grid.GetPointData().AddArray(vtkarr) + grid.GetPointData().SetActiveScalars('Image') + + vtex = vtk.vtkTexture() + vtex.SetInputDataObject(grid) + vtex.Update() + + cubeSource = vtk.vtkCubeSource() + + mapper = vtk.vtkPolyDataMapper() + mapper.SetInputConnection(cubeSource.GetOutputPort()) + + actor = vtk.vtkActor() + actor.SetMapper(mapper) + actor.SetTexture(vtex) + + return actor + +# timer_callback is called by window.showManager +def timer_callback(caller, timer_event): + _, image = cam.read() + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + actor.texture_update(cube, image) + showmanager.render() + +# openCV video capture and conversion to RGB +cam = cv2.VideoCapture('http://commondatastorage.googleapis.com/' + + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') +_, image = cam.read() +image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + +# Scene creation +scene = window.Scene() + +# actor for fury +cube = texture_on_cube(image) + +# working with window.ShowManager to setup timer_callbacks +scene.add(cube) +showmanager = window.ShowManager(scene, size=(600, 600), reset_camera=False) +showmanager.add_timer_callback(True, int(1/60), timer_callback) +showmanager.start() \ No newline at end of file From 41848f72c17327688111d4f7d0791241e8a964c5 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 20 Feb 2024 21:40:26 +0530 Subject: [PATCH 02/21] import vtk through fury lib.py, added some comments on possible improvements, fixed the bug when video ends --- docs/examples/viz_play_cube.py | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 63832a9f1..0e5186da4 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -8,12 +8,19 @@ """ import cv2 -import vtk +import vtk # only for vtkCubeSource which needs to be added to lib.py import numpy as np from fury import actor, window -from fury.lib import numpy_support +from fury.lib import ( + numpy_support, + ImageData, + Texture, + # lib.py needs to have CubeSource, + PolyDataMapper, + Actor +) def texture_on_cube(image): """ @@ -22,30 +29,31 @@ def texture_on_cube(image): Parameters: ----------- image : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB array. Dtype should be uint8. Returns: -------- actor : Actor """ - grid = vtk.vtkImageData() + grid = ImageData() grid.SetDimensions(image.shape[1], image.shape[0], 1) - vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) + # we need a numpy array -> vtkTexture function in numpy_support + vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) vtkarr.SetName('Image') grid.GetPointData().AddArray(vtkarr) grid.GetPointData().SetActiveScalars('Image') - vtex = vtk.vtkTexture() + vtex = Texture() vtex.SetInputDataObject(grid) vtex.Update() cubeSource = vtk.vtkCubeSource() - mapper = vtk.vtkPolyDataMapper() + mapper = PolyDataMapper() mapper.SetInputConnection(cubeSource.GetOutputPort()) - actor = vtk.vtkActor() + actor = Actor() actor.SetMapper(mapper) actor.SetTexture(vtex) @@ -54,13 +62,19 @@ def texture_on_cube(image): # timer_callback is called by window.showManager def timer_callback(caller, timer_event): _, image = cam.read() - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - actor.texture_update(cube, image) - showmanager.render() + + if image is None: + showmanager.exit() + else: + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + actor.texture_update(cube, image) + showmanager.render() # openCV video capture and conversion to RGB cam = cv2.VideoCapture('http://commondatastorage.googleapis.com/' + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') +fps = int(cam.get(cv2.CAP_PROP_FPS)) + _, image = cam.read() image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) @@ -73,5 +87,5 @@ def timer_callback(caller, timer_event): # working with window.ShowManager to setup timer_callbacks scene.add(cube) showmanager = window.ShowManager(scene, size=(600, 600), reset_camera=False) -showmanager.add_timer_callback(True, int(1/60), timer_callback) +showmanager.add_timer_callback(True, int(1000/fps), timer_callback) showmanager.start() \ No newline at end of file From 27737297f49b178a4a5bb19e9f7c51d1f6e93b4f Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 20 Feb 2024 21:48:31 +0530 Subject: [PATCH 03/21] fixing pep8 one line at a time --- docs/examples/viz_play_cube.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 0e5186da4..949cccef5 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -8,9 +8,9 @@ """ import cv2 -import vtk # only for vtkCubeSource which needs to be added to lib.py +import vtk # only for vtkCubeSource which needs to be added to lib.py -import numpy as np +import numpy as np from fury import actor, window from fury.lib import ( @@ -22,6 +22,7 @@ Actor ) + def texture_on_cube(image): """ Map an RGB texture on a cube. @@ -30,7 +31,7 @@ def texture_on_cube(image): ----------- image : ndarray Input 2D RGB array. Dtype should be uint8. - + Returns: -------- actor : Actor @@ -39,7 +40,7 @@ def texture_on_cube(image): grid = ImageData() grid.SetDimensions(image.shape[1], image.shape[0], 1) # we need a numpy array -> vtkTexture function in numpy_support - vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) + vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F')) vtkarr.SetName('Image') grid.GetPointData().AddArray(vtkarr) grid.GetPointData().SetActiveScalars('Image') @@ -59,6 +60,7 @@ def texture_on_cube(image): return actor + # timer_callback is called by window.showManager def timer_callback(caller, timer_event): _, image = cam.read() @@ -70,9 +72,10 @@ def timer_callback(caller, timer_event): actor.texture_update(cube, image) showmanager.render() + # openCV video capture and conversion to RGB cam = cv2.VideoCapture('http://commondatastorage.googleapis.com/' - + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') + + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') fps = int(cam.get(cv2.CAP_PROP_FPS)) _, image = cam.read() @@ -88,4 +91,4 @@ def timer_callback(caller, timer_event): scene.add(cube) showmanager = window.ShowManager(scene, size=(600, 600), reset_camera=False) showmanager.add_timer_callback(True, int(1000/fps), timer_callback) -showmanager.start() \ No newline at end of file +showmanager.start() From 6feeeb0208cfc2594241ef2a4d9857c140abb720 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 20 Feb 2024 21:54:51 +0530 Subject: [PATCH 04/21] fixing pep8 one line at a time (part 2) --- docs/examples/viz_play_cube.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 949cccef5..b8c50ed9c 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -39,9 +39,12 @@ def texture_on_cube(image): grid = ImageData() grid.SetDimensions(image.shape[1], image.shape[0], 1) + # we need a numpy array -> vtkTexture function in numpy_support - vtkarr = numpy_support.numpy_to_vtk(np.flip(image.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F')) + arr = np.flip(image.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F') + vtkarr = numpy_support.numpy_to_vtk(arr) vtkarr.SetName('Image') + grid.GetPointData().AddArray(vtkarr) grid.GetPointData().SetActiveScalars('Image') @@ -75,7 +78,7 @@ def timer_callback(caller, timer_event): # openCV video capture and conversion to RGB cam = cv2.VideoCapture('http://commondatastorage.googleapis.com/' - + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') + + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') fps = int(cam.get(cv2.CAP_PROP_FPS)) _, image = cam.read() From f58f41dca5e765a51224b41f7a27eb5ca9c89242 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 3 Mar 2024 15:36:50 +0530 Subject: [PATCH 05/21] modified cube viz with different textures on all 6 sides --- docs/examples/viz_play_cube.py | 168 +++++++++++++++++---------------- 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index b8c50ed9c..3f090772e 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -7,91 +7,93 @@ on a cube by updating a texture. """ -import cv2 -import vtk # only for vtkCubeSource which needs to be added to lib.py - -import numpy as np - -from fury import actor, window -from fury.lib import ( - numpy_support, - ImageData, - Texture, - # lib.py needs to have CubeSource, - PolyDataMapper, - Actor -) +import vtk +from fury import window +from fury.lib import Texture, PolyDataMapper, Actor, JPEGReader #vtkPlaneSource to be added here -def texture_on_cube(image): +class TexturedCube: """ - Map an RGB texture on a cube. - - Parameters: - ----------- - image : ndarray - Input 2D RGB array. Dtype should be uint8. - - Returns: - -------- - actor : Actor + A class to represent a textured cube. """ - grid = ImageData() - grid.SetDimensions(image.shape[1], image.shape[0], 1) - - # we need a numpy array -> vtkTexture function in numpy_support - arr = np.flip(image.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F') - vtkarr = numpy_support.numpy_to_vtk(arr) - vtkarr.SetName('Image') - - grid.GetPointData().AddArray(vtkarr) - grid.GetPointData().SetActiveScalars('Image') - - vtex = Texture() - vtex.SetInputDataObject(grid) - vtex.Update() - - cubeSource = vtk.vtkCubeSource() - - mapper = PolyDataMapper() - mapper.SetInputConnection(cubeSource.GetOutputPort()) - - actor = Actor() - actor.SetMapper(mapper) - actor.SetTexture(vtex) - - return actor - - -# timer_callback is called by window.showManager -def timer_callback(caller, timer_event): - _, image = cam.read() - - if image is None: - showmanager.exit() - else: - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - actor.texture_update(cube, image) - showmanager.render() - - -# openCV video capture and conversion to RGB -cam = cv2.VideoCapture('http://commondatastorage.googleapis.com/' - + 'gtv-videos-bucket/sample/BigBuckBunny.mp4') -fps = int(cam.get(cv2.CAP_PROP_FPS)) - -_, image = cam.read() -image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - -# Scene creation -scene = window.Scene() - -# actor for fury -cube = texture_on_cube(image) - -# working with window.ShowManager to setup timer_callbacks -scene.add(cube) -showmanager = window.ShowManager(scene, size=(600, 600), reset_camera=False) -showmanager.add_timer_callback(True, int(1000/fps), timer_callback) -showmanager.start() + def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: str): + """ + Initializes a TexturedCube object. + + Args: + negx (str): Path to the negative X-axis texture file. + negy (str): Path to the negative Y-axis texture file. + negz (str): Path to the negative Z-axis texture file. + posx (str): Path to the positive X-axis texture file. + posy (str): Path to the positive Y-axis texture file. + posz (str): Path to the positive Z-axis texture file. + """ + + self.negx = negx + self.negy = negy + self.negz = negz + self.posx = posx + self.posy = posy + self.posz = posz + + self.planes = [vtk.vtkPlaneSource() for _ in range(6)] + + self.plane_centers = [ + (0, 0.5, 0), + (0, 0, 0.5), + (0, 1, 0.5), + (0, 0.5, 1), + (0.5, 0.5, 0.5), + (-0.5, 0.5, 0.5), + ] + + self.plane_normals = [ + (0, 0, 1), + (0, 1, 0), + (0, 1, 0), + (0, 0, 1), + (1, 0, 0), + (1, 0, 0), + ] + + for plane, center, normal in zip(self.planes, self.plane_centers, self.plane_normals): + plane.SetCenter(*center) + plane.SetNormal(*normal) + + self.texture_filenames = [negx, negy, negz, posx, posy, posz] + + self.textures = [Texture() for _ in self.texture_filenames] + self.texture_readers = [JPEGReader() for _ in self.texture_filenames] + + for filename, reader, texture in zip(self.texture_filenames, self.texture_readers, self.textures): + reader.SetFileName(filename) + reader.Update() + texture.SetInputConnection(reader.GetOutputPort()) + + self.mappers = [PolyDataMapper() for _ in self.planes] + self.actors = [Actor() for _ in self.planes] + + for mapper, actor, plane, texture in zip(self.mappers, self.actors, self.planes, self.textures): + mapper.SetInputConnection(plane.GetOutputPort()) + actor.SetMapper(mapper) + actor.SetTexture(texture) + + def visualize(self): + """ + Visualizes the textured cube using Fury. + """ + + scene = window.Scene() + for actor in self.actors: + scene.add(actor) + + show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) + show_manager.start() + + +# Example usage +cube = TexturedCube( + "negx.jpg", "negy.jpg", "negz.jpg", "posx.jpg", "posy.jpg", "posz.jpg" +) +cube.visualize() \ No newline at end of file From ed688ca3fc4d64a4d19a027d3dca32515f845e16 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 3 Mar 2024 15:45:48 +0530 Subject: [PATCH 06/21] pep8 fix --- docs/examples/viz_play_cube.py | 38 +++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 3f090772e..4092018b3 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -9,7 +9,8 @@ import vtk from fury import window -from fury.lib import Texture, PolyDataMapper, Actor, JPEGReader #vtkPlaneSource to be added here +from fury.lib import Texture, PolyDataMapper, Actor, JPEGReader +# vtkPlaneSource to be added here class TexturedCube: @@ -17,7 +18,15 @@ class TexturedCube: A class to represent a textured cube. """ - def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: str): + def __init__( + self, + negx: str, + negy: str, + negz: str, + posx: str, + posy: str, + posz: str + ): """ Initializes a TexturedCube object. @@ -35,7 +44,7 @@ def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: self.negz = negz self.posx = posx self.posy = posy - self.posz = posz + self.posz = posz self.planes = [vtk.vtkPlaneSource() for _ in range(6)] @@ -56,8 +65,12 @@ def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: (1, 0, 0), (1, 0, 0), ] - - for plane, center, normal in zip(self.planes, self.plane_centers, self.plane_normals): + + for plane, center, normal in zip( + self.planes, + self.plane_centers, + self.plane_normals + ): plane.SetCenter(*center) plane.SetNormal(*normal) @@ -66,7 +79,11 @@ def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: self.textures = [Texture() for _ in self.texture_filenames] self.texture_readers = [JPEGReader() for _ in self.texture_filenames] - for filename, reader, texture in zip(self.texture_filenames, self.texture_readers, self.textures): + for filename, reader, texture in zip( + self.texture_filenames, + self.texture_readers, + self.textures + ): reader.SetFileName(filename) reader.Update() texture.SetInputConnection(reader.GetOutputPort()) @@ -74,7 +91,12 @@ def __init__(self, negx: str, negy: str, negz: str, posx: str, posy: str, posz: self.mappers = [PolyDataMapper() for _ in self.planes] self.actors = [Actor() for _ in self.planes] - for mapper, actor, plane, texture in zip(self.mappers, self.actors, self.planes, self.textures): + for mapper, actor, plane, texture in zip( + self.mappers, + self.actors, + self.planes, + self.textures + ): mapper.SetInputConnection(plane.GetOutputPort()) actor.SetMapper(mapper) actor.SetTexture(texture) @@ -96,4 +118,4 @@ def visualize(self): cube = TexturedCube( "negx.jpg", "negy.jpg", "negz.jpg", "posx.jpg", "posy.jpg", "posz.jpg" ) -cube.visualize() \ No newline at end of file +cube.visualize() From 1887ccba0912c047e105669c9416645817b95026 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 3 Mar 2024 15:47:02 +0530 Subject: [PATCH 07/21] pep8 --- docs/examples/viz_play_cube.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 4092018b3..9c5fe9d27 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -110,7 +110,11 @@ def visualize(self): for actor in self.actors: scene.add(actor) - show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) + show_manager = window.ShowManager( + scene, + size=(1280, 720), + reset_camera=False + ) show_manager.start() From 5a7c6fc7abf49b5af9bb96ac0c8881607af9c5b5 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 10 Mar 2024 21:36:10 +0530 Subject: [PATCH 08/21] textured cube final version without tests --- fury/actor.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++++- fury/lib.py | 2 + 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/fury/actor.py b/fury/actor.py index 77c370863..0134ed043 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -7,7 +7,7 @@ import numpy as np import fury.primitive as fp -from fury import layout +from fury import layout, window from fury.actors.odf_slicer import OdfSlicerActor from fury.actors.peak import PeakActor from fury.actors.tensor import double_cone, main_dir_uncertainty, tensor_ellipsoid @@ -26,6 +26,7 @@ ConeSource, ContourFilter, CylinderSource, + PlaneSource, DiskSource, FloatArray, Follower, @@ -3954,3 +3955,127 @@ def uncertainty_cone( angles = main_dir_uncertainty(evals, evecs, signal, sigma, b_matrix) return double_cone(centers, evecs, angles, colors, scales, opacity) + +class TexturedCube: + """Class to work with textured cube. + """ + + def __init__(self, negx, negy, negz, posx, posy, posz): + """Initializes a TexturedCube object. + + Parameters + ---------- + negx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + """ + + self.planes = [PlaneSource() for _ in range(6)] + + self.plane_centers = [ + (0, 0.5, 0), + (0, 0, 0.5), + (0, 1, 0.5), + (0, 0.5, 1), + (0.5, 0.5, 0.5), + (-0.5, 0.5, 0.5), + ] + + self.plane_normals = [ + (0, 0, 1), + (0, 1, 0), + (0, 1, 0), + (0, 0, 1), + (1, 0, 0), + (1, 0, 0), + ] + + for plane, center, normal in zip( + self.planes, + self.plane_centers, + self.plane_normals + ): + plane.SetCenter(*center) + plane.SetNormal(*normal) + + self.image_grids = [negx, negy, negz, posx, posy, posz] + self.image_data_objs = [ImageData() for _ in range(6)] + + for grid, image_data_obj in zip(self.image_grids, self.image_data_objs): + image_data_obj.SetDimensions(grid.shape[1], grid.shape[0], 1) + vtkarr = numpy_support.numpy_to_vtk(np.flip(grid.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) + vtkarr.SetName('Image') + image_data_obj.GetPointData().AddArray(vtkarr) + image_data_obj.GetPointData().SetActiveScalars('Image') + + self.texture_objects = [Texture() for _ in range(6)] + for image_data_obj, texture_object in zip(self.image_data_objs, self.texture_objects): + texture_object.SetInputDataObject(image_data_obj) + + self.polyDataMappers = [PolyDataMapper() for _ in range(6)] + for mapper, plane in zip(self.polyDataMappers, self.planes): + mapper.SetInputConnection(plane.GetOutputPort()) + + self.actors = [Actor() for _ in range(6)] + for actor, mapper, texture_object in zip(self.actors, self.polyDataMappers, self.texture_objects): + actor.SetMapper(mapper) + actor.SetTexture(texture_object) + + def get_scene(self): + """Returns + ------- + self.scene : window.Scene""" + + self.scene = window.Scene() + for actor in self.actors: + self.scene.add(actor) + + return self.scene + + def get_actor(self): + """Returns + ------- + assembled_actor : Actor""" + + assembled_actor = Assembly() + for actor_ in self.actors: + assembled_actor.AddPart(actor_) + + return assembled_actor + + def texture_update(self, show_manager, negx, negy, negz, posx, posy, posz): + """Changes the texture of the cube. + + Parameters + ---------- + show_manager : window.ShowManager + Input currently using ShowManager. + negx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + """ + + self.image_grids = [negx, negy, negz, posx, posy, posz] + + for actor_, image in zip(self.actors, self.image_grids): + texture_update(actor_, image) + + show_manager.render() diff --git a/fury/lib.py b/fury/lib.py index b1ba71259..b780bd268 100644 --- a/fury/lib.py +++ b/fury/lib.py @@ -228,6 +228,8 @@ TexturedSphereSource = fsvtk.vtkTexturedSphereSource #: class for RegularPolygonSource RegularPolygonSource = fsvtk.vtkRegularPolygonSource +#: class for PlaneSource +PlaneSource = fsvtk.vtkPlaneSource ############################################################## # vtkCommonDataModel Module From 6fc3dcd91928702b45fcb4f6b6cb3f04b7eecdd6 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 10 Mar 2024 21:37:17 +0530 Subject: [PATCH 09/21] tutorial for viz_play_cube --- docs/examples/viz_play_cube.py | 161 +++++++++------------------------ 1 file changed, 45 insertions(+), 116 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 9c5fe9d27..249121c9e 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -7,119 +7,48 @@ on a cube by updating a texture. """ -import vtk -from fury import window -from fury.lib import Texture, PolyDataMapper, Actor, JPEGReader -# vtkPlaneSource to be added here - - -class TexturedCube: - """ - A class to represent a textured cube. - """ - - def __init__( - self, - negx: str, - negy: str, - negz: str, - posx: str, - posy: str, - posz: str - ): - """ - Initializes a TexturedCube object. - - Args: - negx (str): Path to the negative X-axis texture file. - negy (str): Path to the negative Y-axis texture file. - negz (str): Path to the negative Z-axis texture file. - posx (str): Path to the positive X-axis texture file. - posy (str): Path to the positive Y-axis texture file. - posz (str): Path to the positive Z-axis texture file. - """ - - self.negx = negx - self.negy = negy - self.negz = negz - self.posx = posx - self.posy = posy - self.posz = posz - - self.planes = [vtk.vtkPlaneSource() for _ in range(6)] - - self.plane_centers = [ - (0, 0.5, 0), - (0, 0, 0.5), - (0, 1, 0.5), - (0, 0.5, 1), - (0.5, 0.5, 0.5), - (-0.5, 0.5, 0.5), - ] - - self.plane_normals = [ - (0, 0, 1), - (0, 1, 0), - (0, 1, 0), - (0, 0, 1), - (1, 0, 0), - (1, 0, 0), - ] - - for plane, center, normal in zip( - self.planes, - self.plane_centers, - self.plane_normals - ): - plane.SetCenter(*center) - plane.SetNormal(*normal) - - self.texture_filenames = [negx, negy, negz, posx, posy, posz] - - self.textures = [Texture() for _ in self.texture_filenames] - self.texture_readers = [JPEGReader() for _ in self.texture_filenames] - - for filename, reader, texture in zip( - self.texture_filenames, - self.texture_readers, - self.textures - ): - reader.SetFileName(filename) - reader.Update() - texture.SetInputConnection(reader.GetOutputPort()) - - self.mappers = [PolyDataMapper() for _ in self.planes] - self.actors = [Actor() for _ in self.planes] - - for mapper, actor, plane, texture in zip( - self.mappers, - self.actors, - self.planes, - self.textures - ): - mapper.SetInputConnection(plane.GetOutputPort()) - actor.SetMapper(mapper) - actor.SetTexture(texture) - - def visualize(self): - """ - Visualizes the textured cube using Fury. - """ - - scene = window.Scene() - for actor in self.actors: - scene.add(actor) - - show_manager = window.ShowManager( - scene, - size=(1280, 720), - reset_camera=False - ) - show_manager.start() - - -# Example usage -cube = TexturedCube( - "negx.jpg", "negy.jpg", "negz.jpg", "posx.jpg", "posy.jpg", "posz.jpg" -) -cube.visualize() +from fury import window, actor +import numpy as np +import cv2 + +def timer_callback(_caller, _timer_event): + rgb_images = [] + for video_capture in video_captures: + _, bgr_image = video_capture.read() + + # This condition is used to stop the code when the smallest code is over. + if isinstance(bgr_image, np.ndarray): + rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) + rgb_images.append(rgb_image) + else: + show_manager.exit() + return + + cube.texture_update( + show_manager, + *rgb_images + ) + +# the sources for the video, can be URL or directory links on your machine. +sources = [ + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' +] + +video_captures = [cv2.VideoCapture(source) for source in sources] +rgb_images = [] +for video_capture in video_captures: + _, bgr_image = video_capture.read() + rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) + rgb_images.append(rgb_image) + +# calling the TexturedCube class to create a TexturedCube with different textures on all 6 sides. +cube = actor.TexturedCube(*rgb_images) +scene = cube.get_scene() +show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) +show_manager.add_timer_callback(True, int(1/60), timer_callback) +show_manager.start() From a351499706c31389efecb691b647e2eb37b21306 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 10 Mar 2024 22:03:20 +0530 Subject: [PATCH 10/21] pep8 fix --- docs/examples/viz_play_cube.py | 6 +++-- fury/actor.py | 43 +++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 249121c9e..8ea058dca 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -4,13 +4,14 @@ ======================================================= The goal of this demo is to show how to visualize a video -on a cube by updating a texture. +on a cube by updating its textures. """ from fury import window, actor import numpy as np import cv2 + def timer_callback(_caller, _timer_event): rgb_images = [] for video_capture in video_captures: @@ -29,6 +30,7 @@ def timer_callback(_caller, _timer_event): *rgb_images ) + # the sources for the video, can be URL or directory links on your machine. sources = [ 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', @@ -46,7 +48,7 @@ def timer_callback(_caller, _timer_event): rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) rgb_images.append(rgb_image) -# calling the TexturedCube class to create a TexturedCube with different textures on all 6 sides. +# Creating a TexturedCube with different textures on all 6 sides. cube = actor.TexturedCube(*rgb_images) scene = cube.get_scene() show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) diff --git a/fury/actor.py b/fury/actor.py index 0134ed043..6f069ed3a 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3956,6 +3956,7 @@ def uncertainty_cone( return double_cone(centers, evecs, angles, colors, scales, opacity) + class TexturedCube: """Class to work with textured cube. """ @@ -4009,52 +4010,66 @@ def __init__(self, negx, negy, negz, posx, posy, posz): self.image_grids = [negx, negy, negz, posx, posy, posz] self.image_data_objs = [ImageData() for _ in range(6)] - + for grid, image_data_obj in zip(self.image_grids, self.image_data_objs): image_data_obj.SetDimensions(grid.shape[1], grid.shape[0], 1) - vtkarr = numpy_support.numpy_to_vtk(np.flip(grid.swapaxes(0,1), axis=1).reshape((-1, 3), order='F')) + vtkarr = numpy_support.numpy_to_vtk( + np.flip(grid.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F') + ) vtkarr.SetName('Image') image_data_obj.GetPointData().AddArray(vtkarr) image_data_obj.GetPointData().SetActiveScalars('Image') self.texture_objects = [Texture() for _ in range(6)] - for image_data_obj, texture_object in zip(self.image_data_objs, self.texture_objects): + + for image_data_obj, texture_object in zip( + self.image_data_objs, + self.texture_objects + ): texture_object.SetInputDataObject(image_data_obj) - + self.polyDataMappers = [PolyDataMapper() for _ in range(6)] - for mapper, plane in zip(self.polyDataMappers, self.planes): + + for mapper, plane in zip( + self.polyDataMappers, + self.planes + ): mapper.SetInputConnection(plane.GetOutputPort()) - + self.actors = [Actor() for _ in range(6)] - for actor, mapper, texture_object in zip(self.actors, self.polyDataMappers, self.texture_objects): + for actor, mapper, texture_object in zip( + self.actors, + self.polyDataMappers, + self.texture_objects + ): actor.SetMapper(mapper) actor.SetTexture(texture_object) - + def get_scene(self): """Returns - ------- + ------- self.scene : window.Scene""" self.scene = window.Scene() for actor in self.actors: self.scene.add(actor) - + return self.scene def get_actor(self): """Returns - ------- + ------- assembled_actor : Actor""" assembled_actor = Assembly() for actor_ in self.actors: assembled_actor.AddPart(actor_) - + return assembled_actor def texture_update(self, show_manager, negx, negy, negz, posx, posy, posz): """Changes the texture of the cube. - + Parameters ---------- show_manager : window.ShowManager @@ -4074,7 +4089,7 @@ def texture_update(self, show_manager, negx, negy, negz, posx, posy, posz): """ self.image_grids = [negx, negy, negz, posx, posy, posz] - + for actor_, image in zip(self.actors, self.image_grids): texture_update(actor_, image) From 78f8135902822eef019bbeabb09b53e696275f02 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sun, 10 Mar 2024 22:20:49 +0530 Subject: [PATCH 11/21] pep8 --- docs/examples/viz_play_cube.py | 22 ++++++++++++++-------- fury/actor.py | 12 ++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 8ea058dca..51eb65253 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -17,7 +17,7 @@ def timer_callback(_caller, _timer_event): for video_capture in video_captures: _, bgr_image = video_capture.read() - # This condition is used to stop the code when the smallest code is over. + # Condition used to stop rendering when the smallest video is over. if isinstance(bgr_image, np.ndarray): rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) rgb_images.append(rgb_image) @@ -31,14 +31,20 @@ def timer_callback(_caller, _timer_event): ) -# the sources for the video, can be URL or directory links on your machine. +# the 6 sources for the video, can be URL or directory links on your machine. sources = [ - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4', + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + + 'sample/BigBuckBunny.mp4' ] video_captures = [cv2.VideoCapture(source) for source in sources] diff --git a/fury/actor.py b/fury/actor.py index 6f069ed3a..25e55971e 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -4011,12 +4011,16 @@ def __init__(self, negx, negy, negz, posx, posy, posz): self.image_grids = [negx, negy, negz, posx, posy, posz] self.image_data_objs = [ImageData() for _ in range(6)] - for grid, image_data_obj in zip(self.image_grids, self.image_data_objs): + for grid, image_data_obj in zip( + self.image_grids, + self.image_data_objs + ): image_data_obj.SetDimensions(grid.shape[1], grid.shape[0], 1) - vtkarr = numpy_support.numpy_to_vtk( - np.flip(grid.swapaxes(0, 1), axis=1).reshape((-1, 3), order='F') - ) + numpy_flip = np.flip(grid.swapaxes(0, 1), axis=1) + numpy_flip = numpy_flip.reshape((-1, 3), order='F') + vtkarr = numpy_support.numpy_to_vtk(numpy_flip) vtkarr.SetName('Image') + image_data_obj.GetPointData().AddArray(vtkarr) image_data_obj.GetPointData().SetActiveScalars('Image') From 724ee56aaa2fc08cea035549ef6b4dc7a1a408f9 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Mon, 11 Mar 2024 20:35:47 +0530 Subject: [PATCH 12/21] modified to elininate circular import error, removed get_scene() because it is redundant when get_actor() alreadt exists --- docs/examples/viz_play_cube.py | 4 +++- fury/actor.py | 22 +++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 51eb65253..5f87180f2 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -56,7 +56,9 @@ def timer_callback(_caller, _timer_event): # Creating a TexturedCube with different textures on all 6 sides. cube = actor.TexturedCube(*rgb_images) -scene = cube.get_scene() +scene = window.Scene() +cube_actor = cube.get_actor() +scene.add(cube_actor) show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) show_manager.add_timer_callback(True, int(1/60), timer_callback) show_manager.start() diff --git a/fury/actor.py b/fury/actor.py index 25e55971e..87182378e 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -7,7 +7,7 @@ import numpy as np import fury.primitive as fp -from fury import layout, window +from fury import layout from fury.actors.odf_slicer import OdfSlicerActor from fury.actors.peak import PeakActor from fury.actors.tensor import double_cone, main_dir_uncertainty, tensor_ellipsoid @@ -3958,8 +3958,7 @@ def uncertainty_cone( class TexturedCube: - """Class to work with textured cube. - """ + """Class to work with textured cube.""" def __init__(self, negx, negy, negz, posx, posy, posz): """Initializes a TexturedCube object. @@ -3978,6 +3977,7 @@ def __init__(self, negx, negy, negz, posx, posy, posz): Input 2D RGB or RGBA array. Dtype should be uint8. posz : ndarray Input 2D RGB or RGBA array. Dtype should be uint8. + """ self.planes = [PlaneSource() for _ in range(6)] @@ -4049,21 +4049,12 @@ def __init__(self, negx, negy, negz, posx, posy, posz): actor.SetMapper(mapper) actor.SetTexture(texture_object) - def get_scene(self): - """Returns - ------- - self.scene : window.Scene""" - - self.scene = window.Scene() - for actor in self.actors: - self.scene.add(actor) - - return self.scene - def get_actor(self): """Returns ------- - assembled_actor : Actor""" + assembled_actor : Actor + + """ assembled_actor = Assembly() for actor_ in self.actors: @@ -4090,6 +4081,7 @@ def texture_update(self, show_manager, negx, negy, negz, posx, posy, posz): Input 2D RGB or RGBA array. Dtype should be uint8. posz : ndarray Input 2D RGB or RGBA array. Dtype should be uint8. + """ self.image_grids = [negx, negy, negz, posx, posy, posz] From 6a841762a8a1e99e02db0692895e455d5f67a191 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 12 Mar 2024 23:41:45 +0530 Subject: [PATCH 13/21] added tests and fixed some docstrings, also added to lib.py --- fury/actor.py | 24 ++++++++++++------ fury/lib.py | 2 ++ fury/tests/test_actors.py | 51 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/fury/actor.py b/fury/actor.py index 87182378e..3f6c93623 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3978,26 +3978,34 @@ def __init__(self, negx, negy, negz, posx, posy, posz): posz : ndarray Input 2D RGB or RGBA array. Dtype should be uint8. + |----| + | +Y | + |----|----|----|----| + | -X | +Z | +X | -Z | + |----|----|----|----| + | -Y | + |----| + """ self.planes = [PlaneSource() for _ in range(6)] self.plane_centers = [ - (0, 0.5, 0), + (-0.5, 0.5, 0.5), (0, 0, 0.5), - (0, 1, 0.5), - (0, 0.5, 1), + (0, 0.5, 0), (0.5, 0.5, 0.5), - (-0.5, 0.5, 0.5), + (0, 1, 0.5), + (0, 0.5, 1) ] self.plane_normals = [ - (0, 0, 1), - (0, 1, 0), + (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), - (1, 0, 0), + (0, 1, 0), + (0, 0, 1) ] for plane, center, normal in zip( @@ -4052,7 +4060,7 @@ def __init__(self, negx, negy, negz, posx, posy, posz): def get_actor(self): """Returns ------- - assembled_actor : Actor + assembled_actor : Assembly """ diff --git a/fury/lib.py b/fury/lib.py index b780bd268..1adb93e39 100644 --- a/fury/lib.py +++ b/fury/lib.py @@ -101,6 +101,8 @@ WindowToImageFilter = rcvtk.vtkWindowToImageFilter #: class for InteractorStyle InteractorStyle = rcvtk.vtkInteractorStyle +#: class for PropCollection +PropCollection = rcvtk.vtkPropCollection #: class for PropPicker PropPicker = rcvtk.vtkPropPicker #: class for PointPicker diff --git a/fury/tests/test_actors.py b/fury/tests/test_actors.py index c09862b98..9e9c04066 100644 --- a/fury/tests/test_actors.py +++ b/fury/tests/test_actors.py @@ -13,6 +13,7 @@ from fury.actor import grid from fury.decorators import skip_linux, skip_osx, skip_win from fury.deprecator import ExpiredDeprecationError +from fury.lib import Assembly, PropCollection # Allow import, but disable doctests if we don't have dipy from fury.optpkg import optional_package @@ -1881,3 +1882,53 @@ def test_actors_primitives_count(): primitives_count = test_case[2] act = act_func(**args) npt.assert_equal(primitives_count_from_actor(act), primitives_count) + + +def test_texturedcube(interactive=False): + + arr_255 = np.full((720, 1280), 255, dtype=np.uint8) + arr_0 = np.full((720, 1280), 0, dtype=np.uint8) + + arr_white = np.full((720, 1280, 3), 255, dtype=np.uint8) + arr_red = np.dstack((arr_255, arr_0, arr_0)) + arr_green = np.dstack((arr_0, arr_255, arr_0)) + arr_blue = np.dstack((arr_0, arr_0, arr_255)) + arr_yellow = np.dstack((arr_255, arr_255, arr_0)) + arr_aqua = np.dstack((arr_0, arr_255, arr_255)) + + cube = actor.TexturedCube(arr_white, + arr_red, + arr_green, + arr_blue, + arr_yellow, + arr_aqua) + + cube_actor = cube.get_actor() + + # testing whether the returned is an Assembled Actor Object + assert type(cube_actor) is type(Assembly()) + + # testing whether there are 6 different planes + plane_actors = PropCollection() + cube_actor.GetActors(plane_actors) + + assert plane_actors.GetNumberOfItems() == 6 + + # testing whether the texture is getting updated + def timer_callback(_caller, _timer_event): + rgb_images = [arr_aqua, + arr_yellow, + arr_blue, + arr_green, + arr_red, + arr_white] + cube.texture_update(show_manager, *rgb_images) + + assert cube.image_grids == rgb_images + show_manager.exit() + + scene = window.Scene() + scene.add(cube_actor) + show_manager = window.ShowManager(scene, reset_camera=False) + show_manager.add_timer_callback(True, int(1/60), timer_callback) + show_manager.start() From f735ad931bbe46a9c03cdf5fb1702955fa6db9e5 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Wed, 13 Mar 2024 19:50:39 +0530 Subject: [PATCH 14/21] using isintance for the type comparison --- fury/tests/test_actors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fury/tests/test_actors.py b/fury/tests/test_actors.py index 9e9c04066..c04d0f60b 100644 --- a/fury/tests/test_actors.py +++ b/fury/tests/test_actors.py @@ -1906,7 +1906,7 @@ def test_texturedcube(interactive=False): cube_actor = cube.get_actor() # testing whether the returned is an Assembled Actor Object - assert type(cube_actor) is type(Assembly()) + assert isinstance(cube_actor, Assembly) # testing whether there are 6 different planes plane_actors = PropCollection() From c141f31916bbfc6a7786f99e5f7212eba4a0c3e6 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Sat, 16 Mar 2024 01:25:32 +0530 Subject: [PATCH 15/21] Added center coordinate parameter, used util.py helper function to simplify code, modified the tests for the coordinate change --- fury/actor.py | 47 ++++++++++++++++++++++----------------- fury/tests/test_actors.py | 5 ++++- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/fury/actor.py b/fury/actor.py index 3f6c93623..44402eef3 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -75,6 +75,7 @@ get_actor_from_primitive, lines_to_vtk_polydata, numpy_to_vtk_colors, + numpy_to_vtk_image_data, repeat_sources, rgb_to_vtk, set_input, @@ -3960,7 +3961,17 @@ def uncertainty_cone( class TexturedCube: """Class to work with textured cube.""" - def __init__(self, negx, negy, negz, posx, posy, posz): + def __init__(self, + negx, + negy, + negz, + posx, + posy, + posz, + center_x: int = 0, + center_y: int = 0, + center_z: int = 0, + ): """Initializes a TexturedCube object. Parameters @@ -3977,6 +3988,12 @@ def __init__(self, negx, negy, negz, posx, posy, posz): Input 2D RGB or RGBA array. Dtype should be uint8. posz : ndarray Input 2D RGB or RGBA array. Dtype should be uint8. + center_x : int, optional + X-Coordinate of the cube. + center_y : int, optional + Y-Coordinate of the cube. + center_z : int, optional + Z-Coordinate of the cube. |----| | +Y | @@ -3991,12 +4008,12 @@ def __init__(self, negx, negy, negz, posx, posy, posz): self.planes = [PlaneSource() for _ in range(6)] self.plane_centers = [ - (-0.5, 0.5, 0.5), - (0, 0, 0.5), - (0, 0.5, 0), - (0.5, 0.5, 0.5), - (0, 1, 0.5), - (0, 0.5, 1) + (-0.5 + center_x, 0.5 + center_y, 0.5 + center_z), + (0 + center_x, 0 + center_y, 0.5 + center_z), + (0 + center_x, 0.5 + center_y, 0 + center_z), + (0.5 + center_x, 0.5 + center_y, 0.5 + center_z), + (0 + center_x, 1 + center_y, 0.5 + center_z), + (0 + center_x, 0.5 + center_y, 1 + center_z) ] self.plane_normals = [ @@ -4017,20 +4034,10 @@ def __init__(self, negx, negy, negz, posx, posy, posz): plane.SetNormal(*normal) self.image_grids = [negx, negy, negz, posx, posy, posz] - self.image_data_objs = [ImageData() for _ in range(6)] - for grid, image_data_obj in zip( - self.image_grids, - self.image_data_objs - ): - image_data_obj.SetDimensions(grid.shape[1], grid.shape[0], 1) - numpy_flip = np.flip(grid.swapaxes(0, 1), axis=1) - numpy_flip = numpy_flip.reshape((-1, 3), order='F') - vtkarr = numpy_support.numpy_to_vtk(numpy_flip) - vtkarr.SetName('Image') - - image_data_obj.GetPointData().AddArray(vtkarr) - image_data_obj.GetPointData().SetActiveScalars('Image') + self.image_data_objs = [ + numpy_to_vtk_image_data(grid) for grid in self.image_grids + ] self.texture_objects = [Texture() for _ in range(6)] diff --git a/fury/tests/test_actors.py b/fury/tests/test_actors.py index c04d0f60b..673b1dfad 100644 --- a/fury/tests/test_actors.py +++ b/fury/tests/test_actors.py @@ -1901,7 +1901,10 @@ def test_texturedcube(interactive=False): arr_green, arr_blue, arr_yellow, - arr_aqua) + arr_aqua, + 1, + 2, + 3) cube_actor = cube.get_actor() From 1953851d87fcac21095409b7870a54fcc0280580 Mon Sep 17 00:00:00 2001 From: Robin Roy Date: Tue, 19 Mar 2024 23:23:27 +0530 Subject: [PATCH 16/21] Removed classes, made it functional. Changed the tests accordingly. Made the tutorial more descriptive, and included the changes skoudoro requested during review --- docs/examples/viz_play_cube.py | 82 ++++++++---- fury/actor.py | 222 +++++++++++++-------------------- fury/tests/test_actors.py | 57 +++------ 3 files changed, 161 insertions(+), 200 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 5f87180f2..3307ed004 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -7,31 +7,13 @@ on a cube by updating its textures. """ -from fury import window, actor +from fury import actor, window import numpy as np import cv2 - -def timer_callback(_caller, _timer_event): - rgb_images = [] - for video_capture in video_captures: - _, bgr_image = video_capture.read() - - # Condition used to stop rendering when the smallest video is over. - if isinstance(bgr_image, np.ndarray): - rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) - rgb_images.append(rgb_image) - else: - show_manager.exit() - return - - cube.texture_update( - show_manager, - *rgb_images - ) - - -# the 6 sources for the video, can be URL or directory links on your machine. +# The 6 sources for the video, can be URL or directory paths on your machine. +# There'll be a significant delay if your internet connectivity is poor. +# Use local directory paths for fast rendering. sources = [ 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', @@ -47,18 +29,64 @@ def timer_callback(_caller, _timer_event): + 'sample/BigBuckBunny.mp4' ] + +# We are creating OpenCV videoCapture objects to capture frames from sources video_captures = [cv2.VideoCapture(source) for source in sources] +# rgb_images will store the RGB values of the frames. rgb_images = [] for video_capture in video_captures: _, bgr_image = video_capture.read() + # OpenCV reads in BGR, we are converting it to RGB. rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) rgb_images.append(rgb_image) -# Creating a TexturedCube with different textures on all 6 sides. -cube = actor.TexturedCube(*rgb_images) + +# timer_callback gets called every (1/60) seconds in this particular program. +def timer_callback(_caller, _timer_event): + rgb_images = [] + for video_capture in video_captures: + # Taking the new frames + _, bgr_image = video_capture.read() + + # Condition used to stop rendering when the smallest video is over. + if isinstance(bgr_image, np.ndarray): + rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) + rgb_images.append(rgb_image) + else: + show_manager.exit() + return + + for actor_, image in zip(cube, rgb_images): + # texture_update is a function to update the texture of an actor + actor.texture_update(actor_, image) + + # you've to render the pipeline again to display the results + show_manager.render() + + +# texture_on_cube is the function we use, the images are assigned in +# cubemap order. +# |----| +# | +Y | +# |----|----|----|----| +# | -X | +Z | +X | -Z | +# |----|----|----|----| +# | -Y | +# |----| + +cube = actor.texture_on_cube(*rgb_images, centers=(0, 0, 0)) + +# adding the returned Actors to scene scene = window.Scene() -cube_actor = cube.get_actor() -scene.add(cube_actor) +scene.add(*cube) + +# ShowManager controls the frequency of changing textures +# The video is rendered by changing textures very frequently. show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) show_manager.add_timer_callback(True, int(1/60), timer_callback) -show_manager.start() + + +# Flip it to True for video. +interactive = False +if interactive: + show_manager.start() diff --git a/fury/actor.py b/fury/actor.py index 44402eef3..c9ac34693 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3958,150 +3958,102 @@ def uncertainty_cone( return double_cone(centers, evecs, angles, colors, scales, opacity) -class TexturedCube: - """Class to work with textured cube.""" - - def __init__(self, - negx, - negy, - negz, - posx, - posy, - posz, - center_x: int = 0, - center_y: int = 0, - center_z: int = 0, - ): - """Initializes a TexturedCube object. +def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): + """Map RGB or RGBA textures on a cube - Parameters - ---------- - negx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - negy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - negz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - center_x : int, optional - X-Coordinate of the cube. - center_y : int, optional - Y-Coordinate of the cube. - center_z : int, optional - Z-Coordinate of the cube. - - |----| - | +Y | - |----|----|----|----| - | -X | +Z | +X | -Z | - |----|----|----|----| - | -Y | - |----| + Parameters + ---------- + negx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + negz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posx : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posy : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + posz : ndarray + Input 2D RGB or RGBA array. Dtype should be uint8. + centers : tuple (3,) + The X, Y and Z coordinate of the cube, optional. - """ + |----| + | +Y | + |----|----|----|----| + | -X | +Z | +X | -Z | + |----|----|----|----| + | -Y | + |----| - self.planes = [PlaneSource() for _ in range(6)] - - self.plane_centers = [ - (-0.5 + center_x, 0.5 + center_y, 0.5 + center_z), - (0 + center_x, 0 + center_y, 0.5 + center_z), - (0 + center_x, 0.5 + center_y, 0 + center_z), - (0.5 + center_x, 0.5 + center_y, 0.5 + center_z), - (0 + center_x, 1 + center_y, 0.5 + center_z), - (0 + center_x, 0.5 + center_y, 1 + center_z) - ] - - self.plane_normals = [ - (1, 0, 0), - (0, 1, 0), - (0, 0, 1), - (1, 0, 0), - (0, 1, 0), - (0, 0, 1) - ] - - for plane, center, normal in zip( - self.planes, - self.plane_centers, - self.plane_normals - ): - plane.SetCenter(*center) - plane.SetNormal(*normal) - - self.image_grids = [negx, negy, negz, posx, posy, posz] - - self.image_data_objs = [ - numpy_to_vtk_image_data(grid) for grid in self.image_grids - ] - - self.texture_objects = [Texture() for _ in range(6)] - - for image_data_obj, texture_object in zip( - self.image_data_objs, - self.texture_objects - ): - texture_object.SetInputDataObject(image_data_obj) - - self.polyDataMappers = [PolyDataMapper() for _ in range(6)] - - for mapper, plane in zip( - self.polyDataMappers, - self.planes - ): - mapper.SetInputConnection(plane.GetOutputPort()) - - self.actors = [Actor() for _ in range(6)] - for actor, mapper, texture_object in zip( - self.actors, - self.polyDataMappers, - self.texture_objects - ): - actor.SetMapper(mapper) - actor.SetTexture(texture_object) - - def get_actor(self): - """Returns - ------- - assembled_actor : Assembly + Returns + ------- + actors : list[Actor] + A list of Actor objects, one for each face of the cube, in order. - """ + Implementation + -------------- + Check docs/examples/viz_play_cube.py - assembled_actor = Assembly() - for actor_ in self.actors: - assembled_actor.AddPart(actor_) + """ + planes = [PlaneSource() for _ in range(6)] + center_x, center_y, center_z = centers + + plane_centers = [ + (-0.5 + center_x, 0.5 + center_y, 0.5 + center_z), + (0 + center_x, 0 + center_y, 0.5 + center_z), + (0 + center_x, 0.5 + center_y, 0 + center_z), + (0.5 + center_x, 0.5 + center_y, 0.5 + center_z), + (0 + center_x, 1 + center_y, 0.5 + center_z), + (0 + center_x, 0.5 + center_y, 1 + center_z) + ] + + plane_normals = [ + (1, 0, 0), + (0, 1, 0), + (0, 0, 1), + (1, 0, 0), + (0, 1, 0), + (0, 0, 1) + ] + + for plane, center, normal in zip( + planes, + plane_centers, + plane_normals + ): + plane.SetCenter(*center) + plane.SetNormal(*normal) - return assembled_actor + image_grids = [negx, negy, negz, posx, posy, posz] - def texture_update(self, show_manager, negx, negy, negz, posx, posy, posz): - """Changes the texture of the cube. + image_data_objs = [ + numpy_to_vtk_image_data(grid) for grid in image_grids + ] - Parameters - ---------- - show_manager : window.ShowManager - Input currently using ShowManager. - negx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - negy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - negz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - posz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + texture_objects = [Texture() for _ in range(6)] - """ + for image_data_obj, texture_object in zip( + image_data_objs, + texture_objects + ): + texture_object.SetInputDataObject(image_data_obj) - self.image_grids = [negx, negy, negz, posx, posy, posz] + polyDataMappers = [PolyDataMapper() for _ in range(6)] - for actor_, image in zip(self.actors, self.image_grids): - texture_update(actor_, image) + for mapper, plane in zip( + polyDataMappers, + planes + ): + mapper.SetInputConnection(plane.GetOutputPort()) + + actors = [Actor() for _ in range(6)] + for actor, mapper, texture_object in zip( + actors, + polyDataMappers, + texture_objects + ): + actor.SetMapper(mapper) + actor.SetTexture(texture_object) - show_manager.render() + return actors diff --git a/fury/tests/test_actors.py b/fury/tests/test_actors.py index 673b1dfad..c09584301 100644 --- a/fury/tests/test_actors.py +++ b/fury/tests/test_actors.py @@ -13,7 +13,7 @@ from fury.actor import grid from fury.decorators import skip_linux, skip_osx, skip_win from fury.deprecator import ExpiredDeprecationError -from fury.lib import Assembly, PropCollection +from fury.lib import Actor # Allow import, but disable doctests if we don't have dipy from fury.optpkg import optional_package @@ -1884,8 +1884,7 @@ def test_actors_primitives_count(): npt.assert_equal(primitives_count_from_actor(act), primitives_count) -def test_texturedcube(interactive=False): - +def test_texture_on_cube(interactive=False): arr_255 = np.full((720, 1280), 255, dtype=np.uint8) arr_0 = np.full((720, 1280), 0, dtype=np.uint8) @@ -1896,42 +1895,24 @@ def test_texturedcube(interactive=False): arr_yellow = np.dstack((arr_255, arr_255, arr_0)) arr_aqua = np.dstack((arr_0, arr_255, arr_255)) - cube = actor.TexturedCube(arr_white, - arr_red, - arr_green, - arr_blue, - arr_yellow, - arr_aqua, - 1, - 2, - 3) - - cube_actor = cube.get_actor() - - # testing whether the returned is an Assembled Actor Object - assert isinstance(cube_actor, Assembly) + cube = actor.texture_on_cube(arr_white, + arr_red, + arr_green, + arr_blue, + arr_yellow, + arr_aqua, + (1, 2, 3)) - # testing whether there are 6 different planes - plane_actors = PropCollection() - cube_actor.GetActors(plane_actors) + # testing whether 6 VTK Planes are returned + assert len(cube) == 6 and isinstance(cube[0], Actor) - assert plane_actors.GetNumberOfItems() == 6 - - # testing whether the texture is getting updated - def timer_callback(_caller, _timer_event): - rgb_images = [arr_aqua, - arr_yellow, - arr_blue, - arr_green, - arr_red, - arr_white] - cube.texture_update(show_manager, *rgb_images) + # testing whether the colors render as required (testing only 1) + scene = window.Scene() + scene.add(cube[5]) - assert cube.image_grids == rgb_images - show_manager.exit() + pic1 = window.snapshot(scene) + res1 = window.analyze_snapshot(im=pic1, colors=[ + (0, 255, 255), (255, 255, 255) + ]) - scene = window.Scene() - scene.add(cube_actor) - show_manager = window.ShowManager(scene, reset_camera=False) - show_manager.add_timer_callback(True, int(1/60), timer_callback) - show_manager.start() + npt.assert_equal(res1.colors_found, [True, False]) From dc745327b37eb0a5b851f91c03e3f682bce2d8bf Mon Sep 17 00:00:00 2001 From: robinroy03 Date: Thu, 21 Mar 2024 14:55:45 +0530 Subject: [PATCH 17/21] fixed a coordinate bug, now it is perfectly aligned to the center --- fury/actor.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fury/actor.py b/fury/actor.py index c9ac34693..8b5a50c04 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -4000,12 +4000,12 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): center_x, center_y, center_z = centers plane_centers = [ - (-0.5 + center_x, 0.5 + center_y, 0.5 + center_z), - (0 + center_x, 0 + center_y, 0.5 + center_z), + (-0.5 + center_x, 0 + center_y, 0 + center_z), + (0 + center_x, -0.5 + center_y, 0 + center_z), + (0 + center_x, 0 + center_y, -0.5 + center_z), + (0.5 + center_x, 0 + center_y, 0 + center_z), (0 + center_x, 0.5 + center_y, 0 + center_z), - (0.5 + center_x, 0.5 + center_y, 0.5 + center_z), - (0 + center_x, 1 + center_y, 0.5 + center_z), - (0 + center_x, 0.5 + center_y, 1 + center_z) + (0 + center_x, 0 + center_y, 0.5 + center_z) ] plane_normals = [ From 264721bed6a9cdd781ae8dc1e13d3c7155807923 Mon Sep 17 00:00:00 2001 From: robinroy03 Date: Thu, 21 Mar 2024 23:01:18 +0530 Subject: [PATCH 18/21] fixed docs, made it cleaner. Fixed uneven variable names for texture_on_cube. Updated _valid_examples for doc generation --- docs/examples/_valid_examples.toml | 1 + docs/examples/viz_play_cube.py | 51 +++++++++++++++++++----------- fury/actor.py | 30 +++++++++--------- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/docs/examples/_valid_examples.toml b/docs/examples/_valid_examples.toml index e5ecfb142..5e4e4f6be 100644 --- a/docs/examples/_valid_examples.toml +++ b/docs/examples/_valid_examples.toml @@ -59,6 +59,7 @@ files = [ "viz_emwave_animation.py", "viz_helical_motion.py", "viz_play_video.py", + "viz_play_cube.py", "viz_dt_ellipsoids.py" ] diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 3307ed004..82881c1e3 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -1,6 +1,6 @@ """ ======================================================= -Play a video in the 3D world +Play video on a Cube ======================================================= The goal of this demo is to show how to visualize a video @@ -11,9 +11,10 @@ import numpy as np import cv2 +######################################################################### # The 6 sources for the video, can be URL or directory paths on your machine. -# There'll be a significant delay if your internet connectivity is poor. -# Use local directory paths for fast rendering. +# There'll be a significant delay if your internet connectivity is poor, +# use local directory paths for fast rendering. sources = [ 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', @@ -29,19 +30,24 @@ + 'sample/BigBuckBunny.mp4' ] - -# We are creating OpenCV videoCapture objects to capture frames from sources +######################################################################### +# We are creating ``OpenCV videoCapture`` objects to capture frames from +# sources. video_captures = [cv2.VideoCapture(source) for source in sources] + # rgb_images will store the RGB values of the frames. rgb_images = [] for video_capture in video_captures: _, bgr_image = video_capture.read() + # OpenCV reads in BGR, we are converting it to RGB. rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB) rgb_images.append(rgb_image) -# timer_callback gets called every (1/60) seconds in this particular program. +######################################################################## +# ``timer_callback`` gets called repeatedly to change texture. + def timer_callback(_caller, _timer_event): rgb_images = [] for video_capture in video_captures: @@ -60,19 +66,25 @@ def timer_callback(_caller, _timer_event): # texture_update is a function to update the texture of an actor actor.texture_update(actor_, image) - # you've to render the pipeline again to display the results + # you've to re-render the pipeline again to display the results show_manager.render() - -# texture_on_cube is the function we use, the images are assigned in +####################################################################### +# ``texture_on_cube`` is the function we use, the images are assigned in # cubemap order. -# |----| -# | +Y | -# |----|----|----|----| -# | -X | +Z | +X | -Z | -# |----|----|----|----| -# | -Y | -# |----| + + +""" + |----| + | +Y | +|----|----|----|----| +| -X | +Z | +X | -Z | +|----|----|----|----| + | -Y | + |----| +""" +###################################################################### + cube = actor.texture_on_cube(*rgb_images, centers=(0, 0, 0)) @@ -80,13 +92,16 @@ def timer_callback(_caller, _timer_event): scene = window.Scene() scene.add(*cube) -# ShowManager controls the frequency of changing textures +###################################################################### +# ``ShowManager`` controls the frequency of changing textures. # The video is rendered by changing textures very frequently. show_manager = window.ShowManager(scene, size=(1280, 720), reset_camera=False) show_manager.add_timer_callback(True, int(1/60), timer_callback) -# Flip it to True for video. +# Flip it to ``True`` for video. interactive = False if interactive: show_manager.start() + +window.record(scene, size=(1280, 720), out_path='viz_play_cube.png') diff --git a/fury/actor.py b/fury/actor.py index 8b5a50c04..7268da7c6 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3996,7 +3996,7 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): Check docs/examples/viz_play_cube.py """ - planes = [PlaneSource() for _ in range(6)] + plane_objects = [PlaneSource() for _ in range(6)] center_x, center_y, center_z = centers plane_centers = [ @@ -4018,7 +4018,7 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): ] for plane, center, normal in zip( - planes, + plane_objects, plane_centers, plane_normals ): @@ -4027,33 +4027,33 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): image_grids = [negx, negy, negz, posx, posy, posz] - image_data_objs = [ + image_data_objects = [ numpy_to_vtk_image_data(grid) for grid in image_grids ] texture_objects = [Texture() for _ in range(6)] - for image_data_obj, texture_object in zip( - image_data_objs, + for image_data, texture in zip( + image_data_objects, texture_objects ): - texture_object.SetInputDataObject(image_data_obj) + texture.SetInputDataObject(image_data) - polyDataMappers = [PolyDataMapper() for _ in range(6)] + polydatamapper_objects = [PolyDataMapper() for _ in range(6)] for mapper, plane in zip( - polyDataMappers, - planes + polydatamapper_objects, + plane_objects ): mapper.SetInputConnection(plane.GetOutputPort()) - actors = [Actor() for _ in range(6)] - for actor, mapper, texture_object in zip( - actors, - polyDataMappers, + actor_objects = [Actor() for _ in range(6)] + for actor, mapper, texture in zip( + actor_objects, + polydatamapper_objects, texture_objects ): actor.SetMapper(mapper) - actor.SetTexture(texture_object) + actor.SetTexture(texture) - return actors + return actor_objects From 20d668d08b7a07e9775509b54bcc228056fb50e1 Mon Sep 17 00:00:00 2001 From: robinroy03 Date: Thu, 21 Mar 2024 23:09:49 +0530 Subject: [PATCH 19/21] small typo fix --- docs/examples/viz_play_cube.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 82881c1e3..0cd663c10 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -99,6 +99,7 @@ def timer_callback(_caller, _timer_event): show_manager.add_timer_callback(True, int(1/60), timer_callback) +###################################################################### # Flip it to ``True`` for video. interactive = False if interactive: From 62ac13c956ab60f74c0002602f80bd93aab7dd8b Mon Sep 17 00:00:00 2001 From: robinroy03 Date: Fri, 22 Mar 2024 00:34:45 +0530 Subject: [PATCH 20/21] fixed the normal directions (it now points outwards, earlier it pointed inwards. This might affect if we introduce some optimizations), also some minor QOL changes. Deleted vtkprop because it was unused, it was introduced previously but now it is not needed --- fury/actor.py | 11 ++++------- fury/lib.py | 2 -- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/fury/actor.py b/fury/actor.py index 7268da7c6..68cfbac0a 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3997,8 +3997,8 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): """ plane_objects = [PlaneSource() for _ in range(6)] - center_x, center_y, center_z = centers + center_x, center_y, center_z = centers plane_centers = [ (-0.5 + center_x, 0 + center_y, 0 + center_z), (0 + center_x, -0.5 + center_y, 0 + center_z), @@ -4009,9 +4009,9 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): ] plane_normals = [ - (1, 0, 0), - (0, 1, 0), - (0, 0, 1), + (-1, 0, 0), + (0, -1, 0), + (0, 0, -1), (1, 0, 0), (0, 1, 0), (0, 0, 1) @@ -4026,13 +4026,11 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): plane.SetNormal(*normal) image_grids = [negx, negy, negz, posx, posy, posz] - image_data_objects = [ numpy_to_vtk_image_data(grid) for grid in image_grids ] texture_objects = [Texture() for _ in range(6)] - for image_data, texture in zip( image_data_objects, texture_objects @@ -4040,7 +4038,6 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): texture.SetInputDataObject(image_data) polydatamapper_objects = [PolyDataMapper() for _ in range(6)] - for mapper, plane in zip( polydatamapper_objects, plane_objects diff --git a/fury/lib.py b/fury/lib.py index 1adb93e39..b780bd268 100644 --- a/fury/lib.py +++ b/fury/lib.py @@ -101,8 +101,6 @@ WindowToImageFilter = rcvtk.vtkWindowToImageFilter #: class for InteractorStyle InteractorStyle = rcvtk.vtkInteractorStyle -#: class for PropCollection -PropCollection = rcvtk.vtkPropCollection #: class for PropPicker PropPicker = rcvtk.vtkPropPicker #: class for PointPicker From b26842a5722ef427196e987aba7638f093c30a53 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 1 May 2024 15:56:59 +0530 Subject: [PATCH 21/21] https version of videos, removed implementation note from docstring, tuple optional, uint8 constraint removal, note about 6 actors --- docs/examples/viz_play_cube.py | 12 ++++++------ fury/actor.py | 22 +++++++++------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/docs/examples/viz_play_cube.py b/docs/examples/viz_play_cube.py index 0cd663c10..2d5ef6455 100644 --- a/docs/examples/viz_play_cube.py +++ b/docs/examples/viz_play_cube.py @@ -16,17 +16,17 @@ # There'll be a significant delay if your internet connectivity is poor, # use local directory paths for fast rendering. sources = [ - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4', - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/' + 'sample/BigBuckBunny.mp4' ] diff --git a/fury/actor.py b/fury/actor.py index 54eeced7d..ec2c70bb5 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -3964,19 +3964,19 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): Parameters ---------- negx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB or RGBA array. negy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB or RGBA array. negz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB or RGBA array. posx : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB or RGBA array. posy : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. + Input 2D RGB or RGBA array. posz : ndarray - Input 2D RGB or RGBA array. Dtype should be uint8. - centers : tuple (3,) - The X, Y and Z coordinate of the cube, optional. + Input 2D RGB or RGBA array. + centers : tuple (3,), optional + The X, Y and Z coordinate of the cube. |----| | +Y | @@ -3989,11 +3989,7 @@ def texture_on_cube(negx, negy, negz, posx, posy, posz, centers=(0, 0, 0)): Returns ------- actors : list[Actor] - A list of Actor objects, one for each face of the cube, in order. - - Implementation - -------------- - Check docs/examples/viz_play_cube.py + A list of 6 Actor objects, one for each face of the cube, in order. """ plane_objects = [PlaneSource() for _ in range(6)]