PixPick
Draw on the frame. Get the coordinates back in Python.
Boxes, polygons, lines and points — picked interactively, returned as objects that drop straight into YOLO, SAM and Supervision.
The problem
Every CV pipeline starts with coordinates you don't have yet.
# YOLO
counter = RegionCounter(region=[(120, 80), (640, 80), (640, 480), (120, 480)]) # where do these come from?
# SAM2 / SAM3
masks = predictor.predict(box=np.array([120, 80, 640, 480])) # same question
So you do one of three things:
- Guess and rerun. Type some numbers, run, squint at the output, nudge, run again.
- Write the throwaway script.
cv2.setMouseCallback,print(x, y), copy from the terminal, paste into the real code, delete the script. Next project — write it again. - Open an annotation tool just to read pixel values off the cursor.
None of that is the work. It's the step everyone hates and nobody automated.
The fix
import pixpick
region = pixpick.box("video.mp4", frame=10) # drag a box on a specific video frame
zone = pixpick.polygon("image.jpg") # click polygon vertices
# coordinates are ready — unpack directly into any framework
# YOLO:
regioncounter = RegionCounter(
region=zone.yolo_region, # pass region points
model="yolo26n.pt",
)
# same for YOLOE
model.predict("image.jpg", visual_prompts=dict(bboxes=region.yolo_prompt, cls=classes))
# SAM/SAM2/SAM3:
predictor.predict(box=region.sam)
A window opens on your image or video frame. You draw. The coordinates come back as Python objects, already in the shape each framework wants. No terminal copy-paste, no throwaway scripts.
All selectors accept a frame= argument when the source is a video file.
Install
pip install pixpick
Selectors
| Selector | How to use | Returns |
|---|---|---|
pixpick.box() |
Left-click + drag | Box |
pixpick.polygon() |
Click vertices | Polygon |
pixpick.line() |
Click start → click end | Line |
pixpick.point() |
Click points (fg / bg) | Point / MultiPoint |
Make several selections in one pass and you get the matching wrapper — Multibox, MultiPolygon, MultiLine or MultiPoint — each holding a list of the singular objects.
For more information on controls, see Getting Started.
Output formats
Every selection object carries all the formats you'll ever need.
# ── Box ──────────────────────────────────────────────────────
region = pixpick.box("frame.jpg")
region.xyxy # [x1, y1, x2, y2] absolute pixels
region.xywh # [x, y, w, h] absolute pixels
region.cxcywh # [cx, cy, w, h] absolute pixels (YOLO format)
region.center # (cx, cy)
region.area # pixels²
# ── Polygon ───────────────────────────────────────────────────
zone = pixpick.polygon("frame.jpg")
zone.points # [(x0,y0), (x1,y1), ...] absolute pixels
zone.as_numpy # np.array shape (N, 2)
zone.norm # [(x0n,y0n), ...] 0.0 – 1.0
zone.bbox # [x1, y1, x2, y2] tight bounds around the polygon
zone.npoints # int
## ── Line ─────────────────────────────────────────────────────
line = pixpick.line("frame.jpg")
line.points # [(x0,y0), (x1,y1)] absolute pixels
line.as_numpy # np.array shape (2, 2)
line.norm # [(x0n,y0n), (x1n,y1n)] 0.0 – 1.0
line.center # (cx, cy)
line.length # pixels
line.vertical # [(x,y), (x,y)] same line re-drawn vertically
## ── Point ────────────────────────────────────────────────────
pick = pixpick.point("frame.jpg") # one click → Point
pick.xy # (x, y) absolute pixels
pick.label # 1 = foreground, 0 = background
pick.norm # (xn, yn) 0.0 – 1.0
pick.is_foreground # bool
pick.rescale(640, 640) # → Point remapped to another resolution
For more details, see Selectors.
Framework integration
| Framework | Selector | Properties |
|---|---|---|
| Ultralytics YOLOE — visual prompt | Box |
region.yolo_prompt |
| Ultralytics YOLO — region | Box/Polygon |
region.yolo_region |
| SAM / SAM2 / SAM3 — box prompt | Box |
region.sam |
| SAM / SAM2 / SAM3 — point prompt | Point / MultiPoint |
picks.sam |
| Supervision PolygonZone — polygon | Polygon |
zone.supervision |
| Supervision KeyPoints — points | Point / MultiPoint |
picks.supervision |
| Any other format | all selectors | region.raw |
Persistence
Pick once, reuse forever.
region.save("zone.json")
region = pixpick.load("zone.json") # Box and Polygon both work
Production pattern — pick interactively the first time, load on every subsequent run:
from pathlib import Path
import pixpick
ZONE = "config/count_zone.json"
zone = pixpick.load(ZONE) if Path(ZONE).exists() else pixpick.polygon("frame.jpg")
zone.save(ZONE)
Docs
| 🚀 Getting Started | Installation, first selection, controls |
| 🎯 Selectors | All properties and methods for Box and Polygon |
| 🔌 Framework Integration | YOLO, SAM2/SAM3 and more |
| 💾 Persistence | Save, load, JSON schema |
| 🏗️ Architecture | How it's built and how to extend it |
| 🗺️ Roadmap | What's coming next |
Contributing
We welcome contributions! Please open a GitHub issue or submit a pull request. For more information, see Contribution Guidelines.
Metadata
Release files for pixpick 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pixpick-0.2.5.tar.gz | 28.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pixpick-0.2.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.4 kB
Release files / pixpick-0.2.5.tar.gz
| Download URL | pixpick-0.2.5.tar.gz |
|---|---|
| Size | 28.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e7293f2996450c3cde59d9018bfa265f23b3b56d2fb6b68454c3469e2c6afcd
|
|
BLAKE2b-256 checksum How to use checksums |
9713af91c400ad46c47f09013e60fd4dbfff1cb276037ec12f73dac29cc88d9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.18
|
Release files / pixpick-0.2.5-py3-none-any.whl
| Download URL | pixpick-0.2.5-py3-none-any.whl |
|---|---|
| Size | 27.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f1d161c9edd4b0dddd20d71aa68d97eb40f565c45623d29bd5b9341b33308db2
|
|
BLAKE2b-256 checksum How to use checksums |
2c2e70b7c4f66c2603ae31ba1a15b8b9587c2e29ba1e58a8b5fa0232d0328557
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.18
|