Module simple_3dviz.utils
Expand source code
from .behaviours import Behaviour
from .renderables import Renderable
from .scenes import Scene
try:
import cv2
import numpy as np
def save_frame(path, frame):
channels = frame.shape[-1]
if channels == 1:
cv2.imwrite(path, frame)
# swap channels from rgb to bgr
image_data = [frame[:, :, i] for i in range(channels)]
image_data[0], image_data[2] = image_data[2], image_data[0]
frame = np.stack(image_data, axis=-1)
cv2.imwrite(path, frame[::-1])
def read_image(path):
img = cv2.imread(path, -1)
channels = img.shape[-1]
if channels == 1:
return img
# swap channels from bgr to rgb
image_data = [img[:, :, i] for i in range(channels)]
image_data[0], image_data[2] = image_data[2], image_data[0]
return np.stack(image_data, axis=-1)[::-1]
except ImportError:
from PIL import Image
import numpy as np
def save_frame(path, frame):
Image.fromarray(frame[::-1]).save(path)
def read_image(path):
return np.asarray(Image.open(path))
def render(renderables, behaviours, n_frames, size=(512, 512),
background=(1,)*4, camera_position=(-2, -2, -2),
camera_target=(0, 0, 0), up_vector=(0, 0, 1), light=None,
scene=None):
"""Render a list of primitives for a given number of frames calling the
passed behaviours after every frame.
Arguments
---------
renderables: list[Renderable] the renderables to be displayed in the
scene
behaviours: list[Behaviour] a list of behaviours to animate the scene
and save the results
n_frames: int the number of frames to render
size: (w, h) the size of the window
background: (r, g, b, a) the rgba tuple for the background
camera_position: (x, y, z) the position of the camera
camera_target: (x, y, z) the point that the camera looks at
up_vector: (x, y, z) defines the floor and sky
light: (x, y, z) defines the position of the light source
scene: An optional scene to reuse
"""
# Create the scene or clear it if it is provided
if scene is None:
scene = Scene(size=size)
else:
scene.clear()
# Set up the scene
scene.background = background
scene.camera_position = camera_position
scene.camera_target = camera_target
scene.up_vector = up_vector
scene.light = light if light is not None else camera_position
# Add the primitives
if not isinstance(renderables, (list, tuple)):
renderables = [renderables]
if not all(isinstance(r, Renderable) for r in renderables):
raise ValueError(("render() expects one or more renderables as "
"parameters not {}").format(renderables))
for r in renderables:
scene.add(r)
# Render the frames and run the behaviours
# TODO: The following code duplicates some logic that can be found also in
# the implementations of BaseWindow. Investigate whether this could
# be refactored out.
for frame in range(n_frames):
# render
scene.render()
# run the behaviours
params = Behaviour.Params(
None, # we have no window
scene, # the scene
lambda: scene.frame, # return the frame if needed
None, # no mouse
None, # no keyboard
frame == n_frames-1 # is this the last frame?
)
remove = []
for i, b in enumerate(behaviours):
b.behave(params)
if params.done:
remove.append(i)
params.done = False
if params.stop_propagation:
break
for i in reversed(remove):
behaviours.pop(i)
Functions
def read_image(path)
-
Expand source code
def read_image(path): img = cv2.imread(path, -1) channels = img.shape[-1] if channels == 1: return img # swap channels from bgr to rgb image_data = [img[:, :, i] for i in range(channels)] image_data[0], image_data[2] = image_data[2], image_data[0] return np.stack(image_data, axis=-1)[::-1]
def render(renderables, behaviours, n_frames, size=(512, 512), background=(1, 1, 1, 1), camera_position=(-2, -2, -2), camera_target=(0, 0, 0), up_vector=(0, 0, 1), light=None, scene=None)
-
Render a list of primitives for a given number of frames calling the passed behaviours after every frame.
Arguments
renderables: list[Renderable] the renderables to be displayed in the scene behaviours: list[Behaviour] a list of behaviours to animate the scene and save the results n_frames: int the number of frames to render size: (w, h) the size of the window background: (r, g, b, a) the rgba tuple for the background camera_position: (x, y, z) the position of the camera camera_target: (x, y, z) the point that the camera looks at up_vector: (x, y, z) defines the floor and sky light: (x, y, z) defines the position of the light source scene: An optional scene to reuse
Expand source code
def render(renderables, behaviours, n_frames, size=(512, 512), background=(1,)*4, camera_position=(-2, -2, -2), camera_target=(0, 0, 0), up_vector=(0, 0, 1), light=None, scene=None): """Render a list of primitives for a given number of frames calling the passed behaviours after every frame. Arguments --------- renderables: list[Renderable] the renderables to be displayed in the scene behaviours: list[Behaviour] a list of behaviours to animate the scene and save the results n_frames: int the number of frames to render size: (w, h) the size of the window background: (r, g, b, a) the rgba tuple for the background camera_position: (x, y, z) the position of the camera camera_target: (x, y, z) the point that the camera looks at up_vector: (x, y, z) defines the floor and sky light: (x, y, z) defines the position of the light source scene: An optional scene to reuse """ # Create the scene or clear it if it is provided if scene is None: scene = Scene(size=size) else: scene.clear() # Set up the scene scene.background = background scene.camera_position = camera_position scene.camera_target = camera_target scene.up_vector = up_vector scene.light = light if light is not None else camera_position # Add the primitives if not isinstance(renderables, (list, tuple)): renderables = [renderables] if not all(isinstance(r, Renderable) for r in renderables): raise ValueError(("render() expects one or more renderables as " "parameters not {}").format(renderables)) for r in renderables: scene.add(r) # Render the frames and run the behaviours # TODO: The following code duplicates some logic that can be found also in # the implementations of BaseWindow. Investigate whether this could # be refactored out. for frame in range(n_frames): # render scene.render() # run the behaviours params = Behaviour.Params( None, # we have no window scene, # the scene lambda: scene.frame, # return the frame if needed None, # no mouse None, # no keyboard frame == n_frames-1 # is this the last frame? ) remove = [] for i, b in enumerate(behaviours): b.behave(params) if params.done: remove.append(i) params.done = False if params.stop_propagation: break for i in reversed(remove): behaviours.pop(i)
def save_frame(path, frame)
-
Expand source code
def save_frame(path, frame): channels = frame.shape[-1] if channels == 1: cv2.imwrite(path, frame) # swap channels from rgb to bgr image_data = [frame[:, :, i] for i in range(channels)] image_data[0], image_data[2] = image_data[2], image_data[0] frame = np.stack(image_data, axis=-1) cv2.imwrite(path, frame[::-1])