Framework Integration
Every selection object exposes named properties that map straight onto the shape each framework expects — no manual format conversion.
A note on shapes: most properties return a list or array you pass as a single argument (region=, box=). Two return a dict meant for ** unpacking — Point.sam / MultiPoint.sam, and Polygon.supervision. The examples below show which is which.
Ultralytics YOLO
Inference on a region — yolo_region gives the region outline as a list of corner points, which is what the Ultralytics solutions take for region=.
from ultralytics import solutions
zone = pixpick.polygon("image.jpg")
counter = solutions.RegionCounter(
region=zone.yolo_region, # [(x0,y0), (x1,y1), ...]
model="yolo26n.pt",
)
Box.yolo_region returns the box's four corners in the same shape, so a box and a polygon are interchangeable here:
region = pixpick.box("image.jpg")
region.yolo_region # [(x1,y1), (x2,y1), (x2,y2), (x1,y2)]
Visual prompt for YOLOE — yolo_prompt returns an (N, 4) array of [x1, y1, x2, y2] rows, one per box.
region = pixpick.box("image.jpg")
visual_prompts = dict(
bboxes=region.yolo_prompt, # (N, 4) array
cls=np.zeros(len(region.yolo_prompt)),
)
results = model.predict("image.jpg", visual_prompts=visual_prompts)
Check
visual_promptsagainst your installed Ultralytics version — YOLOE's prompt API has changed between releases, and some versions also want an explicitpredictor=.region.yolo_promptis the array either way.
SAM / SAM2 / SAM3
Box prompt — sam returns [x1, y1, x2, y2].
region = pixpick.box("image.jpg")
predictor.set_image(image)
masks, scores, _ = predictor.predict(box=region.sam)
For a Multibox, sam returns one row per box — [[x1,y1,x2,y2], ...].
Point prompt
Click the object to segment, Shift+click anything you want excluded.
picks = pixpick.point("image.jpg")
predictor.set_image(image)
masks, scores, _ = predictor.predict(**picks.sam)
# expands to: predictor.predict(point_coords=(N,2) float32, point_labels=(N,) int32)
One click returns a Point, several return a MultiPoint. Both expose the same .sam, so the call above works either way.
.sam returns a dict here rather than a bare array — point prompts need two parallel arrays. Combine it with a box prompt by unpacking both:
masks, scores, _ = predictor.predict(box=region.sam, **picks.sam)
The individual arrays are available too, if you would rather pass them yourself:
picks.sam_coords # (N, 2) float32
picks.sam_labels # (N,) int32 — 1 = foreground, 0 = background
Supervision
PolygonZone — supervision returns {"polygon": np.array}, ready to unpack.
import supervision as sv
zone = pixpick.polygon("image.jpg")
polygon_zone = sv.PolygonZone(**zone.supervision)
For a MultiPolygon you get one dict per polygon:
zones = pixpick.polygon("image.jpg")
polygon_zones = [sv.PolygonZone(**z) for z in zones.supervision]
KeyPoints — supervision on a point selection returns {"xy": (1, N, 2) float32}.
picks = pixpick.point("image.jpg")
keypoints = sv.KeyPoints(**picks.supervision)
Verify these constructor signatures against your installed
supervisionversion.
Line crossing
Line gives you the two endpoints plus the geometry helpers most counting setups need.
line = pixpick.line("image.jpg")
line.start # (x1, y1)
line.end # (x2, y2)
line.center # (cx, cy)
line.length # float, pixels
line.horizontal # the same line re-drawn horizontally through its centre
horizontal and vertical return coordinates, not booleans — useful for snapping a hand-drawn counting line to an axis.
Raw formats
When you need a format that isn't covered by a named property. raw is a property, not a method — no parentheses.
region = pixpick.box("image.jpg")
raw = region.raw
raw["xyxy"] # [x1, y1, x2, y2] absolute pixels
raw["xywh"] # [x, y, w, h] absolute pixels
raw["cxcywh"] # [cx, cy, w, h] absolute pixels
raw["normalized"] # [x1, y1, x2, y2] 0.0 – 1.0
raw["normalized_xywh"] # [x, y, w, h] 0.0 – 1.0
raw["numpy"] # [x1, y1, x2, y2] as list (JSON serialisable)
Every selection type has raw, with keys suited to its geometry:
| Type | raw keys |
|---|---|
Box / Multibox |
xyxy, xywh, cxcywh, normalized, normalized_xywh, numpy |
Polygon |
points, numpy, normalized, normalized_numpy, bbox_xyxy |
MultiPolygon |
points*, numpy, normalized, normalized_numpy, bbox_xyxy |
Line / MultiLine |
points, numpy, normalized, normalized_numpy, center, length, start, end, vector |
Point |
xy, label, numpy, normalized, normalized_numpy |
MultiPoint |
xy, labels, numpy, normalized, normalized_numpy, centroid, foreground, background |
* MultiPolygon.raw["points"] currently holds the vertex count of each polygon, not the vertices. Use zones.yolo_region for the vertex lists until that is fixed.