Skip to content

LazyPipelineExpr

The LazyPipelineExpr class enables composable, lazy pipeline expressions.

Overview

import polars as pl
from polars_cv import Pipeline

# Create lazy expression
expr = pl.col("image").cv.pipe(Pipeline().source("image_bytes"))

# Chain operations
gray = expr.pipe(Pipeline().grayscale())

# Materialize with sink
result = df.with_columns(output=gray.sink("png"))

API Reference

LazyPipelineExpr

Lazy pipeline expression for composed operations.

This class represents a deferred computation that can be composed with other expressions. The entire graph is fused and executed when .sink() is called.

Example

preprocess = Pipeline().source("image_bytes").resize(height=100, width=200) img = pl.col("image").cv.pipe(preprocess) expr = img.sink("numpy")

node_id property

node_id: str

Get the unique node ID for this expression.

column property

column: Expr

Get the underlying column expression.

pipeline property

pipeline: Pipeline

Get the pipeline specification.

alias_name property

alias_name: str | None

Get the user-defined alias for this node, if any.

__init__

__init__(
    column: Expr,
    pipeline: Pipeline,
    node_id: str | None = None,
    upstream: list[LazyPipelineExpr] | None = None,
    alias: str | None = None,
) -> None

Initialize a LazyPipelineExpr.

Parameters:

Name Type Description Default
column Expr

The Polars column expression this pipeline reads from.

required
pipeline Pipeline

The Pipeline instance defining operations.

required
node_id str | None

Unique identifier for this node in the graph.

None
upstream list[LazyPipelineExpr] | None

List of upstream LazyPipelineExpr dependencies.

None
alias str | None

Optional user-defined name for this node (for multi-output).

None

alias

alias(name: str) -> LazyPipelineExpr

Name this checkpoint for multi-output extraction.

Example

base = pl.col("img").cv.pipe(pipe).alias("base") gray = base.pipe(Pipeline().grayscale()).alias("gray") expr = gray.sink({"base": "numpy", "gray": "png"})

pipe

pipe(pipeline: Pipeline) -> LazyPipelineExpr

Chain a Pipeline onto this expression.

Parameters:

Name Type Description Default
pipeline Pipeline

Operations to apply. If no source(), it continues from here.

required

sink

sink(
    format: str | dict[str, str] = "native",
    return_expr: bool = True,
    **kwargs: Any,
) -> pl.Expr | PipelineGraph

Finalize the pipeline graph and return a Polars expression.

Parameters:

Name Type Description Default
format str | dict[str, str]

Output format string (e.g., "numpy", "png") or a dict mapping aliases to formats for multi-output.

'native'
return_expr bool

If True (default), return a pl.Expr. If False, return the PipelineGraph.

True
kwargs Any

Parameters for the sink. quality for jpeg/webp; shape for the array sink; dtype="f16" for the numpy/torch sink to downcast the output tensor to half precision at the encode boundary (halving the tensor bytes and H2D transfer). dtype only accepts "f16" — cast inside the pipeline for other dtypes.

{}

Returns:

Type Description
Expr | PipelineGraph

A Polars expression (or PipelineGraph if return_expr=False).

apply_mask

apply_mask(
    mask: LazyPipelineExpr, *, invert: bool = False
) -> LazyPipelineExpr

Apply a binary mask to this image.

The mask can be from another image pipeline or a contour pipeline (which will be auto-rasterized to match dimensions).

Parameters:

Name Type Description Default
mask LazyPipelineExpr

LazyPipelineExpr producing the mask.

required
invert bool

If True, invert the mask (keep exterior, zero interior).

False

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the mask operation composed.

channel_merge

channel_merge(
    *others: LazyPipelineExpr,
) -> LazyPipelineExpr

Merge single-channel buffers into one multi-channel image.

Stacks this expression's [H, W] buffer with each others buffer along a new channel axis, producing [H, W, C] where C = len(others) + 1. Each operand must be a single-channel [H, W] buffer (e.g. produced by :meth:Pipeline.channel_select) with matching height and width. This is the inverse of channel_select.

Parameters:

Name Type Description Default
others LazyPipelineExpr

One or more single-channel LazyPipelineExpr operands, in channel order after this one.

()

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr producing the merged multi-channel image.

Example
>>> sel = lambda i: pl.col("img").cv.pipe(
...     Pipeline().source("image_bytes").channel_select(index=i)
... )
>>> merged = sel(2).channel_merge(sel(1), sel(0))  # RGB -> BGR

add

add(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise addition with another array.

For u8/u16: Saturating addition (clamps to max value, e.g., 255 for u8). For f32/f64: Standard addition.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to add.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the add operation composed.

Example
>>> img1 = pl.col("image1").cv.pipe(pipe1)
>>> img2 = pl.col("image2").cv.pipe(pipe2)
>>> result = img1.add(img2).sink("numpy")  # 200 + 100 = 255 (saturated)

subtract

subtract(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise subtraction.

For u8/u16: Saturating subtraction (clamps to 0). For f32/f64: Standard subtraction.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to subtract.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the subtract operation composed.

Example
>>> img1 = pl.col("image1").cv.pipe(pipe1)
>>> img2 = pl.col("image2").cv.pipe(pipe2)
>>> result = img1.subtract(img2).sink("numpy")  # 50 - 100 = 0 (saturated)

multiply

multiply(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise multiplication.

For u8/u16: Saturating multiplication (clamps to max value). For f32/f64: Standard multiplication.

For normalized image blending (treating values as [0,1] range), use blend() instead.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to multiply by.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the multiply operation composed.

Example
>>> img1 = pl.col("image1").cv.pipe(pipe1)
>>> img2 = pl.col("image2").cv.pipe(pipe2)
>>> result = img1.multiply(img2).sink("numpy")  # 16 * 16 = 255 (saturated)
See Also

blend: For normalized multiplication ((a/255) * (b/255) * 255)

divide

divide(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise division.

For u8/u16: Integer division with zero protection (returns 0 for divide by 0). For f32/f64: Standard division.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to divide by.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the divide operation composed.

blend

blend(other: LazyPipelineExpr) -> LazyPipelineExpr

Normalized blend (element-wise).

Performs normalized multiplication useful for image blending/compositing.

For u8: (a/255) * (b/255) * 255 For u16: (a/65535) * (b/65535) * 65535 For f32/f64: Standard multiplication.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to blend with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the blend operation composed.

Example

Blend two images together with proper normalization:

img1 = pl.col("image1").cv.pipe(pipe1) img2 = pl.col("image2").cv.pipe(pipe2) blended = img1.blend(img2).sink("numpy")

ratio

ratio(other: LazyPipelineExpr) -> LazyPipelineExpr

Scaled ratio division.

Computes a/b scaled to the full range of the data type.

For u8: (a/b) * 255, clamped to [0, 255] For u16: (a/b) * 65535, clamped to [0, 65535] For f32/f64: Standard division.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to divide by.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the ratio operation composed.

Example

Compute normalized ratio between two images:

img1 = pl.col("image1").cv.pipe(pipe1) img2 = pl.col("image2").cv.pipe(pipe2) result = img1.ratio(img2).sink("numpy")

bitwise_and

bitwise_and(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise bitwise AND.

For binary masks (0/255 values), this computes the intersection.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to AND with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the bitwise AND operation composed.

Example

Compute intersection of two binary masks:

mask1 = pl.col("pred_mask").cv.pipe(mask_pipe) mask2 = pl.col("gt_mask").cv.pipe(mask_pipe) intersection = mask1.bitwise_and(mask2).sink("list")

bitwise_or

bitwise_or(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise bitwise OR.

For binary masks (0/255 values), this computes the union.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to OR with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the bitwise OR operation composed.

Example

Compute union of two binary masks:

mask1 = pl.col("pred_mask").cv.pipe(mask_pipe) mask2 = pl.col("gt_mask").cv.pipe(mask_pipe) union = mask1.bitwise_or(mask2).sink("list")

bitwise_xor

bitwise_xor(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise bitwise XOR.

For binary masks (0/255 values), this computes the symmetric difference.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to XOR with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the bitwise XOR operation composed.

Example

Compute symmetric difference of two binary masks:

mask1 = pl.col("pred_mask").cv.pipe(mask_pipe) mask2 = pl.col("gt_mask").cv.pipe(mask_pipe) diff = mask1.bitwise_xor(mask2).sink("list")

maximum

maximum(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise maximum of two arrays.

Returns the maximum value at each position between this and another array. Useful for operations like image compositing, clamping, and non-linear image processing.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to compare with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the maximum operation composed.

Example

Compute element-wise maximum of two images:

img1 = pl.col("image1").cv.pipe(pipe1) img2 = pl.col("image2").cv.pipe(pipe2) result = img1.maximum(img2).sink("numpy")

minimum

minimum(other: LazyPipelineExpr) -> LazyPipelineExpr

Element-wise minimum of two arrays.

Returns the minimum value at each position between this and another array. Useful for operations like image compositing, clamping, and non-linear image processing.

Parameters:

Name Type Description Default
other LazyPipelineExpr

LazyPipelineExpr to compare with.

required

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the minimum operation composed.

Example

Compute element-wise minimum of two images:

img1 = pl.col("image1").cv.pipe(pipe1) img2 = pl.col("image2").cv.pipe(pipe2) result = img1.minimum(img2).sink("numpy")

apply_contour_mask

apply_contour_mask(
    contour: LazyPipelineExpr, *, invert: bool = False
) -> LazyPipelineExpr

Apply a contour as a mask to this image.

The contour will be auto-rasterized to match the current image dimensions. This is a convenience for: mask_pipe = Pipeline().source("contour", shape=img_expr) mask = pl.col("contour").cv.pipe(mask_pipe) img.apply_mask(mask)

Parameters:

Name Type Description Default
contour LazyPipelineExpr

LazyPipelineExpr from a contour source (dimensions will be inferred from this image's output shape).

required
invert bool

If True, mask exterior instead of interior.

False

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with the contour mask applied.

merge_pipe

merge_pipe(*others: LazyPipelineExpr) -> LazyPipelineExpr

Merge multiple pipeline branches into a single terminal node.

This creates a node that depends on self and all others, making them all reachable for multi-output sinking. The merged node outputs the same as self (the first/primary branch).

Use this when you have branching pipelines that share a backbone and want to sink multiple branches in a single expression.

Parameters:

Name Type Description Default
others LazyPipelineExpr

Other LazyPipelineExpr nodes to include in the graph.

()

Returns:

Type Description
LazyPipelineExpr

New LazyPipelineExpr with all branches as upstream dependencies.

Example
>>> gray = pl.col("image").cv.pipe(gray_pipe).alias("gray")
>>> contours = gray.extract_contours().alias("contours")
>>> blurred = gray.blur(5).alias("blurred")
>>>
>>> # Merge branches for multi-output
>>> result = contours.merge_pipe(blurred)
>>> expr = result.sink({
...     "gray": "png",
...     "contours": "native",
...     "blurred": "numpy"
... })

Note: - Safe to merge nodes that are already upstream (deduplication handled) - Can merge pipelines from different source columns (multi-source graph) - The merged node's output is the same as self (first argument)

statistics

statistics(include: list[str] | None = None) -> pl.Expr

Compute multiple statistics from the buffer in a single pass.

Returns a Struct column with named fields for each statistic. By default includes: mean, std, min, max.

This is a convenience method that creates branching reduction pipelines and merges them into a single multi-output expression.

Parameters:

Name Type Description Default
include list[str] | None

List of statistics to compute. Valid options: - "mean": Arithmetic mean - "std": Standard deviation - "min": Minimum value - "max": Maximum value - "sum": Sum of all values If None, defaults to ["mean", "std", "min", "max"].

None

Returns:

Type Description
Expr

A Polars expression that returns a Struct column with the

Expr

requested statistics as fields.

Example
>>> # Get statistics for processed images
>>> pipe = Pipeline().source("image_bytes").grayscale()
>>> img = pl.col("image").cv.pipe(pipe)
>>> stats_expr = img.statistics()
>>> df.with_columns(stats=stats_expr)
>>> # Access: df["stats"].struct.field("mean")
>>>
>>> # Only compute specific stats
>>> stats_expr = img.statistics(include=["min", "max"])

statistics_lazy

statistics_lazy(
    include: list[str] | None = None,
) -> LazyPipelineExpr

Create a lazy pipeline for computing multiple statistics.

Unlike statistics() which returns a finalized pl.Expr, this method returns a LazyPipelineExpr that can be merged with other pipelines for multi-output composition.

When sunk, each statistic becomes a separate field in the output struct. The stat nodes are aliased with prefixed names: "stat_mean", "stat_std", etc.

Parameters:

Name Type Description Default
include list[str] | None

List of statistics to compute. Valid options: - "mean": Arithmetic mean - "std": Standard deviation - "min": Minimum value - "max": Maximum value - "sum": Sum of all values If None, defaults to ["mean", "std", "min", "max"].

None

Returns:

Type Description
LazyPipelineExpr

A LazyPipelineExpr representing the merged statistics pipelines.

LazyPipelineExpr

Can be composed with other pipelines using merge_pipe().

Example
>>> # Compose stats with other outputs
>>> pipe = Pipeline().source("image_bytes")
>>> img = pl.col("image").cv.pipe(pipe).alias("img")
>>> gray = img.pipe(Pipeline().grayscale()).alias("gray")
>>> stats = gray.statistics_lazy()  # Creates stat_mean, stat_std, etc.
>>>
>>> # Merge and sink together
>>> result = img.merge_pipe(gray, stats)
>>> expr = result.sink({
...     "img": "numpy",
...     "gray": "numpy",
...     "stat_mean": "native",
...     "stat_std": "native",
...     "stat_min": "native",
...     "stat_max": "native",
... })

__repr__

__repr__() -> str

Return string representation with guidance.

__str__

__str__() -> str

Return string representation.