Skip to content

Expressions (.cv)

The .cv accessor is registered on every Polars expression once polars_cv is imported. It is the entry point for pipelines, for raw byte access, and for the header-only metadata readers.

import polars as pl
import polars_cv  # registers .cv (and .point / .contour / .bbox)

Overview

Method Input column Returns Purpose
pipe() image bytes, paths, lists/arrays, contour structs LazyPipelineExpr Apply a Pipeline; finish with .sink(...)
read_bytes() String paths Binary Read the bytes a path names, without decoding
width() Binary encoded images UInt32 Image width from the header only
height() Binary encoded images UInt32 Image height from the header only
channels() Binary encoded images UInt32 Channel count from the header only
image_dtype() Binary encoded images String Sample dtype from the header only

Only pipe() builds a graph and runs through the vb_graph expression. The others are standalone plugin expressions: they take a column and return a column, with no pipeline to build.

Pipelines

pipe = Pipeline().source("image_bytes").resize(height=224, width=224)

df.with_columns(out=pl.col("image").cv.pipe(pipe).sink("numpy"))

See Pipeline for the operations and LazyPipelineExpr for composition and sinks.

Everything that configures a pipeline lives on the Pipeline (or on the LazyPipelineExpr it produces), not on the accessor — including the per-row error and null-parameter policies, .on_error() and .on_null_param(). Unlike the geometry namespaces, .cv has no on_null().

Byte access

read_bytes() is the fetch half of the "file_path" source — that source fetches a path's bytes and then decodes them as an image, and this stops after the fetch. Bytes are returned verbatim, so an encoded file survives the round trip byte-for-byte.

# Read originals, filter on header metadata, decode only the survivors.
lf = (
    pl.scan_parquet("images.parquet")
    .with_columns(raw=pl.col("path").cv.read_bytes())
    .filter(pl.col("raw").cv.width() > 512)
    .with_columns(thumb=pl.col("raw").cv.pipe(pipe).sink("png"))
)

It takes the same cloud_options and on_error values as Pipeline.source("file_path"). See Reading Bytes Without Decoding for the memory and streaming behaviour, and for the path-sandboxing caveat.

Metadata

The metadata readers parse only the image header, so they do not decode pixels. They take a Binary column of encoded images or a String column of paths (a local file is read only as far as its header needs):

df.with_columns(w=pl.col("path").cv.width(), info=pl.col("path").cv.image_info())

See Metadata & Display for details.

API Reference

CvNamespace

Bases: _PluginNamespace

Namespace for computer vision operations on Polars expressions.

Example

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

Metadata methods (header-only, no full decode): >>> df.with_columns(w=pl.col("image").cv.width()) >>> df.filter(pl.col("image").cv.height() > 1024)

pipe

pipe(pipe: 'Pipeline') -> 'LazyPipelineExpr'

Apply a vision pipeline to this column.

Returns a LazyPipelineExpr that can be composed with other operations. Call .sink(format) to finalize and get a Polars expression.

read_bytes

read_bytes(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str = "raise",
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Read the bytes each path names, without decoding them.

This is the first half of the "file_path" source: that source fetches a path's bytes and then decodes them as an image, and this stops after the fetch. Bytes are returned verbatim, so an encoded file survives the round trip unchanged and can be written back byte-for-byte — something a decode cannot offer, since re-encoding a decoded JPEG never reproduces the original file and the image sinks carry no EXIF/ICC metadata.

The header-only metadata methods below take a path column directly (a local file read only as far as its header needs), so they do not need this first.

Local paths (bare or file://) and remote URIs (s3://, gs://, az://, http://) are both supported, with the same credential handling as source("file_path"). Within one call the distinct remote paths are fetched concurrently; local files are read per row.

Under engine="streaming" a bytes column produced here is morsel-bounded, so it only becomes corpus-resident if you select it in the final projection — which is the point when you want the originals.

Note

Without allowed_roots paths are not sandboxed: whatever the column names is read in full, including any local file and any http:// address (link-local metadata endpoints among them). That is the right default for your own paths and the wrong one for paths that came from somewhere else. File size is not capped either way.

Parameters:

Name Type Description Default
cloud_options 'CloudOptions | dict[str, Any] | None'

Credentials/settings for remote reads, as CloudOptions or a dict (see Pipeline.source).

None
on_error str

"raise" (default) fails the query on the first unreadable path; "null" yields null for that row only.

'raise'
allowed_roots 'Sequence[str] | None'

Restrict which locations may be read, exactly as Pipeline.source(allowed_roots=...) does — one list covering local directories and remote URI prefixes, canonicalized and matched component-wise, denying anything that matches no entry. A refusal follows on_error, so on_error="null" nulls the offending rows rather than failing the query.

None

Returns:

Type Description
Expr

Binary expression with each path's raw file contents.

width

width(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str | None = None,
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Get image width from its header, without a full decode.

The column holds image bytes (Binary) or paths (String). A local path's file is read only as far as its header needs; a remote path's object is fetched whole, as .cv.read_bytes() does. Supports encoded images (PNG, JPEG, WebP, TIFF, BMP, GIF) and VIEW protocol blobs; null for an unrecognised format or a null input. For more than one field, .cv.image_info() reads each header once.

Parameters:

Name Type Description Default
cloud_options 'CloudOptions | dict[str, Any] | None'

Path columns only: credentials for remote reads, as for .cv.read_bytes().

None
on_error str | None

Path columns only: "raise" (default) or "null" for an unreadable path.

None
allowed_roots 'Sequence[str] | None'

Path columns only: the locations that may be read, as for .cv.read_bytes().

None

Returns:

Type Description
Expr

UInt32 expression with the width of each image.

height

height(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str | None = None,
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Get image height from its header, without a full decode.

Takes bytes or paths, as :meth:width does (see it for the options).

Returns:

Type Description
Expr

UInt32 expression with the height of each image.

channels

channels(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str | None = None,
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Get the number of channels from its header, without a full decode.

Takes bytes or paths, as :meth:width does (see it for the options).

Returns:

Type Description
Expr

UInt32 expression with the channel count of each image.

image_dtype

image_dtype(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str | None = None,
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Get the element dtype from its header, without a full decode.

Returns dtype names like "uint8", "uint16", "float32". Takes bytes or paths, as :meth:width does (see it for the options).

Returns:

Type Description
Expr

String expression with the dtype name of each image.

image_info

image_info(
    *,
    cloud_options: "CloudOptions | dict[str, Any] | None" = None,
    on_error: str | None = None,
    allowed_roots: "Sequence[str] | None" = None,
) -> pl.Expr

Width, height, channels and dtype from one header read per row.

Takes bytes or paths, as :meth:width does (see it for the options).

Returns:

Name Type Description
Expr

``Struct{width: UInt32, height: UInt32, channels: UInt32,

dtype Expr

String}``; null for a null input or an unrecognised format.