Geometry Operations¶
polars-cv provides two expression namespaces for geometry: .contour for polygon operations and .point for point operations.
Schemas¶
Geometry data uses Polars Struct columns:
from polars_cv import CONTOUR_SCHEMA, POINT_SCHEMA, BBOX_SCHEMA
# POINT_SCHEMA: Struct({x: f64, y: f64})
# BBOX_SCHEMA: Struct({x: f64, y: f64, width: f64, height: f64})
# CONTOUR_SCHEMA: Struct({exterior: List(POINT), holes: List(List(POINT)), is_closed: bool})
Contours¶
The .contour namespace operates on polygon columns.
Measurements¶
df.with_columns(
area=pl.col("contour").contour.area(),
perimeter=pl.col("contour").contour.perimeter(),
centroid=pl.col("contour").contour.centroid(),
bbox=pl.col("contour").contour.bounding_box(),
)
Transforms¶
df.with_columns(
moved=pl.col("contour").contour.translate(dx=10, dy=20),
scaled=pl.col("contour").contour.scale(sx=2.0, sy=2.0),
simplified=pl.col("contour").contour.simplify(tolerance=1.0),
hull=pl.col("contour").contour.convex_hull(),
)
Rasterization¶
Convert contours to binary masks:
pipe = Pipeline().source("contour", width=200, height=200)
result = df.with_columns(
mask=pl.col("contour").cv.pipe(pipe).sink("numpy")
)
Infer dimensions from an existing image:
img = pl.col("image").cv.pipe(Pipeline().source("image_bytes").resize(height=200, width=200))
mask = pl.col("contour").cv.pipe(Pipeline().source("contour", shape=img))
Points¶
The .point namespace operates on point columns.
Transforms¶
df.with_columns(
normalized=pl.col("point").point.normalize(ref_width=100, ref_height=100),
absolute=pl.col("point").point.to_absolute(ref_width=100, ref_height=100),
moved=pl.col("point").point.translate(dx=10, dy=20),
scaled=pl.col("point").point.scale(sx=2.0, sy=2.0),
rotated=pl.col("point").point.rotate(math.pi / 2),
)
Distances¶
df.with_columns(
euclidean=pl.col("p1").point.distance(pl.col("p2")),
manhattan=pl.col("p1").point.manhattan_distance(pl.col("p2")),
to_boundary=pl.col("point").point.distance_to_contour(pl.col("contour")),
signed=pl.col("point").point.signed_distance_to_contour(pl.col("contour")),
)
Geometric Operations¶
df.with_columns(
angle=pl.col("p1").point.angle_to(pl.col("p2")),
mid=pl.col("p1").point.midpoint(pl.col("p2")),
interp=pl.col("p1").point.interpolate(pl.col("p2"), t=0.25),
nearest=pl.col("point").point.nearest_point_on_contour(pl.col("contour")),
inside=pl.col("point").point.within_bbox(pl.col("bbox")),
)
Bounding Boxes¶
The .bbox namespace operates on List[BBOX_SCHEMA] columns for detection tasks.
Pairwise IoU¶
Compute IoU between two sets of bounding boxes:
Detection Matching¶
Greedy one-to-one matching between predicted and ground-truth bounding boxes:
df.with_columns(
match_result=pl.col("pred_bboxes").bbox.match_detections(
pl.col("gt_bboxes"),
threshold=0.5,
scores=pl.col("pred_scores"),
),
)
Mask Metrics¶
Pixel-based metrics for binary masks: