deadleaves#

Submodules#

Classes#

LeafGeometryGenerator

Set up the geometrical dead leaves model.

LeafAppearanceSampler

Setup color and texture model for a dead leaves partition.

ImageRenderer

Setup leaf geometry and appearance for rendering.

LeafTopology

Topology-level operations on leaf tables to

Package Contents#

class deadleaves.LeafGeometryGenerator(leaf_shape: Literal['circular', 'ellipsoid', 'rectangular', 'polygon'], shape_param_distributions: dict[str, dict[str, dict[str, float | dict]]], image_shape: tuple[int, int], position_mask: torch.Tensor | numpy.ndarray | dict | None = None, n_sample: int | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None)#

Set up the geometrical dead leaves model.

Args:
leaf_shape (Literal[“circular”, “ellipsoid”, “rectangular”, “polygon”]):

Shape of leaves.

shape_param_distributions (dict[str, dict[str, [dict[str, float | dict]]]):

Leaf shape parameters and their distributions and hyperparameter values.

image_shape (tuple[int, int]):

Height (y, M) and width (x, N) of the canvas.

position_mask (torch.Tensor | np.ndarray | dict | None, optional):

Boolean tensor containing allowed leaf positions to create images with different shapes. If None all positions on the canvas are allowed. Defaults to None.

n_sample (int | None, optional):

Number of leaves to sample. If None, the sampling will stop when the full area is partitioned. Default is None.

device (Literal[“cuda”, “mps”, “cpu”] | None, optional):

Torch device to use, either ‘cuda’ or ‘cpu’. If None, device will be chosen automatically. Defaults to None.

device: torch.device#

Chosen compute backend.

image_shape: tuple[int, int]#

Height (y, M) and width (x, N) of the canvas.

n_sample: int | None = None#

Number of leaves to sample.

leaf_shape: Literal['circular'] | Literal['ellipsoid'] | Literal['rectangular'] | Literal['polygon']#

Shape of the leaves.

shape_param_distributions#

Shape parameters and their distributions and hyperparameter values.

generate_leaf_mask: Callable#

Method to generate mask of leaf on canvas.

position_mask: torch.Tensor#

Positions on canvas masked for sampling leaf positions.

_resolve_dependencies() list[str]#

Resolve model parameter dependencies.

Raises:
ValueError:

Error on circular or unresolvable dependencies.

Returns:
list[str]:

Sorted list of parameters.

_unpack_parameters() None#

Generate list of model parameters and distribution instances to sample from.

Raises:
ValueError:

Provided parameters don’t match provided leaf shape.

_sample_parameters() dict[str, torch.Tensor]#

Draw a sample from the model distributions.

Returns:
dict[str, torch.Tensor]:

Sample for each model parameter.

_resolve_position_mask(position_mask: torch.Tensor | numpy.ndarray | dict) None#

Resolve position mask from tensor or geometric specification.

Args:
position_mask (torch.Tensor | np.ndarray | dict):

Boolean tensor or array with allowed sampling positions or dictionary specifying a leaf shape and its parameters.

Raises:
ValueError:

Position mask dict must contain ‘shape’ and ‘params’.

ValueError:

Check for unsupported leaf shapes in dict.

TypeError:

Check argument type.

ValueError:

Check that position mask has same size as canvas.

ValueError:

Check that there are allowed positions.

generate_segmentation() tuple[pandas.DataFrame, torch.Tensor]#

Generate a dead leaves segmentation from the model.

Uses a quadtree to track which canvas regions still contain uncovered pixels. Fully covered subtrees are pruned from future queries, so mask evaluation is restricted to the sparse frontier of remaining gaps.

Returns:
tuple[pd.DataFrame, torch.Tensor]:

Dataframe listing the parameters of all generated leaves, along with an segmentation map assigning each image location to a leaf.

class deadleaves.LeafAppearanceSampler(leaf_table: pandas.DataFrame, device: Literal['cuda', 'mps', 'cpu'] | None = None)#

Setup color and texture model for a dead leaves partition.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

device (Literal[“cuda”, “mps”, “cpu”] | None, optional):

Torch device to use, either ‘cuda’ or ‘cpu’. If None, device will be chosen automatically. Defaults to None.

device: torch.device#

Chosen compute backend.

leaf_table: pandas.DataFrame#

Dataframe of leaves and their parameters.

n_leaves: int#

Number of leaves.

_unpack_color() None#

Generate color distribution instances to sample from.

_sample_grayscale_colors() torch.Tensor#

Sample a grayscale color for each leaf.

Returns:
torch.Tensor:

Color values.

_sample_3d_colors() torch.Tensor#

Sample a 3d color for each leaf.

Returns:
torch.Tensor:

Color values.

_sample_colors_from_images() torch.Tensor#

Sample a pixel value for each leaf from a random image in folder.

Returns:
torch.Tensor:

Color values.

sample_color(color_param_distributions: dict[str, dict[str, dict[str, float]]] | dict[str, dict[str, dict[str, dict]]] | dict[str, dict[str, dict[str, str]]]) pandas.DataFrame#

Sample leaf colors according to the configured color space.

Args:
color_param_distributions (dict[str, dict[str, dict[str, float | dict | str]]]):

Color parameters and their distribution setup.

Returns:
pd.DataFrame:

Updated DataFrame with color parameters added to each leaf

_unpack_texture() None#

Generate texture distribution instances to sample from.

_sample_texture_parameters() pandas.DataFrame#

Materialize per-leaf texture parameters and distribution metadata.

Returns:
pd.DataFrame

One row per leaf with resolved texture parameters for all channels.

sample_texture(texture_param_distributions: dict[str, dict[str, dict[str, float | str | dict[str, dict[str, float]]]]]) pandas.DataFrame#

Sample leaf textures according to the configured color space.

Args:
texture_param_distribution (dict[str, dict[str, dict[str, float | dict[str, dict[str, float]]]]]):

Texture parameters and their distribution setup.

Raises:
ValueError:

Chosen texture space is not supported.

Return:
pd.DataFrame:

Updated DataFrame with texture parameters added to each leaf

class deadleaves.ImageRenderer(leaf_table: pandas.DataFrame, segmentation_map: torch.Tensor | None = None, image_shape: tuple[int, int] | None = None, background_color: torch.Tensor | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None)#

Setup leaf geometry and appearance for rendering.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

segmentation_map (torch.Tensor | None, optional):

Partition which assigns image locations to a leaf. If None the segmentation map will be generated from the leaf table. Defaults to None.

image_shape (tuple[int,int] | None, optional):

Height (y, M) and width (x, N) of the canvas. If None the image_shape will be set based on the segmentation map. Defaults to None. Either image_shape or segmentation_map need to be given.

background_color (torch.Tensor | None, optional):

For images which are not fully covered (due to a position mask or sparse sampling) one can set a RGB background color. If None the background will be black. Defaults to None.

device (Literal[“cuda”, “mps”, “cpu”] | None, optional):

Torch device to use, either ‘cuda’ or ‘cpu’. If None, device will be chosen automatically. Defaults to None.

device: torch.device#

Chosen compute backend.

background_color: torch.Tensor | None = None#

Color for pixels not belonging to any leaf.

leaf_table: pandas.DataFrame#

Dataframe of leaves and their parameters.

segmentation_map: torch.Tensor | None = None#

Partition of the image area.

image_shape: tuple[int, int]#

Height (y, M) and width (x, N) of the canvas.

_resolve_image_shape(image_shape: tuple[int, int] | None, segmentation_map: torch.Tensor | None) tuple[int, int]#

Resolve image shape from segmentation_map or explicit image_shape.

Raises:
ValueError:

Shape of segmentation map and provided image shape don’t match.

ValueError:

Neither image_shape nor segmentation map are given.

_generate_segmentation_map() None#

Generate segmentation map if None is provided.

_infer_texture_space() None#

Infer which color space the texture parameters are defined in.

_infer_color_space() None#

Infer which color space the color parameters are defined in.

_get_texture_param_columns(channel: str) list[str]#

Get all columns which contain texture parameters from leaf_table.

Args:
channel (str):

Color channel to extract parameters for.

Returns:
list[str]:

Columns with parameters for channel texture.

_get_leaf_texture_params(leaf_row: pandas.Series, channel: str) dict#

Get values from columns with texture parameters in leaf_table.

Args:
leaf_row (pd.Series):

Single row from leaf table.

channel (str):

Channel name.

Returns:
dict:

Parameters for leaf texture as dictionary.

_generate_leafwise_texture_1d(channel: str) torch.Tensor#

Generate grayscale texture from sampled distributions.

Args:
channel (str):

Color channel name.

Returns:
torch.Tensor

Texture image of shape (H, W).

_generate_leafwise_texture_from_source() torch.Tensor#

Generate grayscale texture from image sources stored in leaf_table.

Returns:
torch.Tensor

Texture image of shape (H, W).

_generate_leafwise_texture() torch.Tensor#

Generate a per-pixel texture image from leafwise texture parameters.

Raises:
ValueError:

Fallback for unknown specifications.

Returns:
torch.Tensor

Texture RBG image of shape (H, W, 3).

render_image() torch.Tensor#

Generate a dead leaves image.

Returns:
torch.Tensor:

Dead leaves image tensor.

apply_image_noise(noise: dict[str, dict | torch.Tensor], image: torch.Tensor | None = None) torch.Tensor#

Apply global noise to an image.

Args:
image (torch.Tensor):

Input image tensor of shape (H, W, C), values in [0,1].

noise (dict):

Dictionary or tensor/array specifying noise per channel. Examples: - Distribution-based: {“gray”: {“normal”: {“loc”: 0, “scale”: 0.1}}} - Array-based: {“R”: torch.randn(H, W) * 0.05}

Returns:
torch.Tensor:

Image with noise applied, clipped to [0,1].

show(image: torch.Tensor | None = None, figsize: tuple[int, int] | None = None) None#

Show selected image.

Args:
image (torch.Tensor, optional):

Image to show. If None the self.image will be used.

figsize (tuple[int,int], optional):

Figure size in inches (width, height). If None size is inferred from image size. Defaults to None.

save(save_to: pathlib.Path | str, image: torch.Tensor | None = None) None#

Save image to path.

Args:
save_to (Path):

Path to file to save image to.

image (torch.Tensor, optional):

Image to save. If None the self.image will be used.

animate(fps: int = 10, save_to: pathlib.Path | None = None) matplotlib.animation.FuncAnimation#

Generate animation of dead leaves partition generation.

Args:
fps (int, optional):

Frames per second of animation. In each frame a new leaf is sampled. Defaults to 10.

save_to (Path, optional):

Path to file to save animation to. If None the animation will not be saved. Defaults to None.

Returns:
animation.FuncAnimation:

Animation of partition generation.

class deadleaves.LeafTopology(image_shape: tuple[int, int] | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None)#

Topology-level operations on leaf tables to - Construct segmentation maps - Merge and relabel leaf tables - Manage leaf identities (leaf_idx)

Args:
image_shape (tuple[int, int] | None, optional):

Height (y, M) and width (x, N) of the area to be partitioned.

device (Literal[“cuda”, “mps”, “cpu”] | None, optional):

Torch device to use, either ‘cuda’ or ‘cpu’. If None, device will be chosen automatically. Defaults to None.

image_shape: tuple[int, int] | None = None#

Height (y, M) and width (x, N) of the canvas.

device: torch.device#

Chosen compute backend.

static _validate_geometry(leaf_table: pandas.DataFrame) None#

Check if leaf table contains parameters necessary for constructing the geometry.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

Raises:
ValueError:

If required columns are missing, unknown shapes are present, or required parameters contain NaNs.

_cull_outside_canvas(leaf_table: pandas.DataFrame) pandas.DataFrame#

Remove leaves whose centers are outside the canvas.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

Returns:
pd.DataFrame:

Reduced table.

segmentation_map_from_table(leaf_table: pandas.DataFrame) torch.Tensor#

Construct a segmentation map from a leaf table.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

Returns:
torch.Tensor:

Segmentation map which assigns each image location to a leaf.

static merge_leaf_tables(*leaf_tables: pandas.DataFrame) pandas.DataFrame#

Merge multiple leaf tables and assign fresh leaf_idx.

Args:
leaf_tables (pd.DataFrame):

List of tables to be merged.

Returns:
pd.DataFrame:

Merged table.

static reindex_by_group(leaf_table: pandas.DataFrame, groupby: str, shuffle: bool = True, group_order: str | None = None, seed: int | None = None) pandas.DataFrame#

Reassign leaf_idx within groups.

Args:
leaf_table (pd.DataFrame):

Dataframe of leaves and their parameters.

groupby (str):

Column containing the groups.

shuffle (bool):

If true shuffle leaf index within group. Defaults to true.

group_order (str | None):

Order of groups: “ascending”, or “descending”, or random (None). Defaults to None.

seed (int | None):

Set value for generating a random seed for reproducibility. If None a different random seed will be set at each execution. Defaults to None.

Returns:
pd.DataFrame:

Reindexed (and shuffled) table.

static randomize_index(leaf_table: pandas.DataFrame, seed: int | None = None) pandas.DataFrame#

Randomly reassign a global index while preserving all row attributes.

This shuffles depth ordering across all leaves, including across semantic groups (e.g. target vs background), while keeping group labels intact.

Args:
table (pd.DataFrame):

Input leaf table.

seed (int, optional):

Random seed for reproducibility. Default to None.

Returns:
pd.DataFrame:

Table with randomized index_col.