0.30.6
minitap-ai/mobile-use0.30.6Sep 29, 2026by Borda
Upgrading?
AI Summary
A patch release fixing 12 correctness bugs in datasets, annotators, and key points, specifically addressing Pillow conversion issues and data integrity problems like silent object dropping.
Key Highlights
- pillow_to_cv2 now correctly converts all Pillow modes (fixing crashes for masks, depth maps, and CMYK)
- LineZone.trigger no longer inflates counts with unconfirmed tracks
- DetectionDataset exporters now export box-only objects instead of silently dropping them
- Dataset splits now raise errors for out-of-range ratios
- DetectionsSmoother no longer crashes on mismatched metadata
New Features
- Correct Pillow mode conversion for all image types
- Accurate LineZone crossing counts
- Complete dataset export functionality
- Input validation for dataset split ratios
Full Release Notes
# 0.30.6: Pillow-conversion, dataset-export, and line-crossing correctness fixes
supervision 0.30.6 is a patch release closing 12 library correctness bugs and landing 2 behavior refinements across datasets, annotators, key points, line-crossing counting, and the Pillow-based fallback backend, plus a new docs guide and a notebook dead-link fix. No new public API, no breaking changes. The broadest-reach fix rewrites `pillow_to_cv2`, the entry point every annotator except `RichLabelAnnotator` and several image helpers use to convert a Pillow image: it used to pass raw mode bytes straight through, so a 1-bit mask, a 16-bit depth map, an `LA`/`PA` image, or a CMYK JPEG all drew wrong or crashed. Two fixes close silent-wrong-data bugs rather than crashes: `LineZone.trigger` let unconfirmed tracks inflate crossing counts, and `DetectionDataset.as_yolo`/`.as_pascal_voc` silently dropped box-only objects from a mixed polygon/box COCO dataset. `DetectionsSmoother` no longer crashes when two tracked objects first seen on different frames carry different metadata (e.g. RF-DETR's `source_image`); its own docstring pipeline was broken. Every library fix ships a regression test.
## β¨ Spotlights / highlights
### `sv.pillow_to_cv2` now converts every Pillow mode the way `cv2.imread` would
Raw mode bytes used to pass straight through: a 1-bit mask came back as `0`/`1` instead of `0`/`255`, a 16-bit depth map wrapped modulo 256 and drew as noise, an `LA`/`PA` image crashed in `cvtColor` on its 2-channel array, and a CMYK JPEG drew its cyan/magenta/yellow ink as red/green/blue. This function is the entry point for every annotator except `RichLabelAnnotator` (which stays on the Pillow path) plus `crop_image`, `resize_image`, `letterbox_image`, `scale_image`, `tint_image`, `grayscale_image`, and `plot_image` whenever handed a Pillow image, so the bug reached the whole drawing surface, not just one call site. A single-channel grayscale image also drew from a read-only buffer view before this fix. Annotating into it silently failed; it now hands back a writable copy.
```python
from PIL import Image
depth_map = Image.open("depth.tif") # mode "I;16"
scene = sv.pillow_to_cv2(depth_map)
# clipped to the 16-bit range and keeps its high byte, instead of wrapping mod 256
```
RGB, RGBA, grayscale, and palette images are unchanged.
### `sv.LineZone.trigger` no longer lets unconfirmed tracks inflate counts
Detections with a negative `tracker_id` (how trackers like `ByteTrackTracker` mark an unconfirmed track) all keyed under one shared id. Two distinct unconfirmed objects crossing on opposite sides in the same frame read as one track oscillating, silently inflating `in_count`/`out_count` with crossings no confirmed track ever made. Confirmed tracks (`tracker_id >= 0`) are counted exactly as before.
### `sv.DetectionDataset.as_yolo` / `.as_pascal_voc` stop dropping box-only objects
`from_coco` gives an all-zero mask to any annotation without its own `segmentation` when a sibling annotation has one, and to every annotation when `force_masks=True`. The exporters only ever wrote the polygon traced from a mask, so a mixed polygon/box COCO dataset silently lost its box-only objects on export, and a box-only COCO dataset loaded with `force_masks=True` wrote empty YOLO label files or object-less Pascal VOC files. A detection with an empty or contour-less mask now exports as its bounding box instead.
### `sv.DetectionsSmoother` no longer crashes on a second tracked object
Each smoothed track was built on the oldest frame in its window, so two objects first seen on different frames carried different frames' `metadata` (exactly what the RF-DETR / `inference` connectors attach), and `Detections.merge` rejected the mismatch. `class_id` and `data` (e.g. `class_name`) now follow the current frame instead of lagging up to `length - 1` frames behind a class change; `xyxy`, `confidence`, and oriented-box corners are still averaged as before.
### Dataset splits reject an out-of-range ratio instead of silently mis-splitting
`sv.DetectionDataset.split`, `sv.ClassificationDataset.split` (both take `split_ratio`), and the internal `train_test_split` helper they call (takes `train_ratio`) never validated the ratio. A finite out-of-range value looked like a successful split: for 10 images, a ratio of `-0.2` returned 8/2 via negative slicing, and `1.2` (or an accidental percentage like `80`) returned 10/0 with no held-out data, no error either way.
```python
train, test = dataset.split(split_ratio=80) # meant 80%
# now raises ValueError naming the problem, instead of silently returning
# every image as train and none as test
```
`0` and `1` keep their existing meanings. Not an API break: no signature changed, only previously-silent input now raises.
## π Migration guide
No breaking changes in this release.
No deprecations or removals landed in 0.30.6 either. All scheduled `remove_in` markers in the codebase target `0.31.0` or `0.32.0` and are untouched by this patch release.
Two entries change *output values* rather than only fixing a crash or a silently-wrong count; not API breaks, but worth checking if your code depends on the old values:
- `sv.KeyPoints.from_ultralytics` / `.from_inference` / `.from_detectron2`: `as_detections().confidence` now carries the model's own detection score, not the mean of the per-keypoint confidences.
- `sv.DetectionsSmoother`: `class_id` and `data` fields on a smoothed track now follow the current frame instead of lagging behind a class change.
## π Notable changes
### π§ Fixed
**Annotators / key points**
- `sv.VertexEllipseHaloAnnotator` now draws the whole halo of a key point whose covariance ellipse is not horizontal. A vertical or diagonal ellipse used to be clipped to a thin band because the fade box was sized as if the major axis always ran along the image x axis. Horizontal ellipses are drawn exactly as before. ([#2634](https://github.com/roboflow/supervision/pull/2634))
- `sv.KeyPoints.from_ultralytics`, `.from_inference` and `.from_detectron2` now keep each object's detection score as `detection_confidence` instead of dropping it, which previously made `sv.KeyPoints.with_nms` raise `ValueError` and `as_detections()` report the mean keypoint confidence instead of the model's own score. ([#2633](https://github.com/roboflow/supervision/pull/2633))
- `sv.LabelAnnotator` now sizes the label background correctly for a label containing a blank line. Text drew each blank line at full height while the background measured it as zero, pushing the last line outside the box. Labels without blank lines are unchanged. ([#2632](https://github.com/roboflow/supervision/pull/2632))
- `sv.IconAnnotator` now draws a palette icon that carries its own alpha channel (Pillow `PA` mode, storable in TIFF) instead of raising `ValueError`. Palettes without alpha, and every read with OpenCV installed, are unchanged. ([#2624](https://github.com/roboflow/supervision/pull/2624))
**Datasets**
- `sv.DetectionDataset.as_yolo` / `.as_pascal_voc` now write a detection whose mask is empty or has no valid contour as its bounding box instead of silently leaving it out of the label file. ([#2631](https://github.com/roboflow/supervision/pull/2631))
- `sv.DetectionDataset.from_yolo` now loads a label row carrying a trailing confidence or tracker id (written by Ultralytics `save_txt` with `save_conf=True` or tracking on) instead of raising `ValueError`, for both box and segmentation rows. The extra token is ignored; box and polygon geometry are unchanged. An odd-length polygon row with no extra field now loses its last value rather than raising, since coordinate parity is the only signal separating the two cases. ([#2619](https://github.com/roboflow/supervision/pull/2619), [#2626](https://github.com/roboflow/supervision/pull/2626), [#2635](https://github.com/roboflow/supervision/pull/2635))
**Tracking**
- `sv.DetectionsSmoother` no longer raises `ValueError: Conflicting metadata` when a second tracked object, first seen on a different frame, enters the smoothing window. ([#2628](https://github.com/roboflow/supervision/pull/2628))
- `sv.LineZone.trigger` now ignores detections with a negative `tracker_id` (the value trackers such as `ByteTrackTracker` report for an unconfirmed track) instead of letting them silently inflate `in_count`/`out_count`. ([#2623](https://github.com/roboflow/supervision/pull/2623))
**Detection utils**
- `sv.polygon_to_mask` now accepts a list/tuple/array-like of `[x, y]` vertices (not just a NumPy array) and returns an all-zero mask for an empty or under-3-vertex polygon instead of crashing inside OpenCV/NumPy with an opaque error. A malformed polygon now raises `ValueError` naming the problem. ([#2622](https://github.com/roboflow/supervision/pull/2622))
- `sv.Detections.from_sam3` now keeps SAM 3 PVS contour fragments with fewer than 3 vertices instead of dropping them. Single points and 2-point edges are rasterized directly into the mask and bounding box. ([#2625](https://github.com/roboflow/supervision/pull/2625))
**Image / IO**
- `sv.pillow_to_cv2` now converts every Pillow mode to the 8-bit array `cv2.imread` would produce, reaching every annotator plus `crop_image`, `resize_image`, `letterbox_image`, `scale_image`, `tint_image`, `grayscale_image`, and `plot_image`. ([#2614](https://github.com/roboflow/supervision/pull/2614))
- `sv.CSVSink` now writes UTF-8 on every platform, preserving non-English detection labels and custom fields on Windows. ([#2615](https://github.com/roboflow/supervision/pull/2615))
**Docs**
- Dead documentation links fixed across the published notebooks (`quickstart.ipynb`, `annotate-video-with-detections.ipynb`, `underestand-visitors-with-yolo-world.ipynb`). ([#2630](https://github.com/roboflow/supervision/pull/2630))
### π± Changed
- `sv.DetectionDataset.split`, `sv.ClassificationDataset.split`, and the internal `train_test_split` helper they call now reject a ratio outside `[0, 1]` (`NaN` and `Β±inf` included) with a `ValueError` naming the problem, instead of silently mis-splitting or dropping the held-out set. ([#2611](https://github.com/roboflow/supervision/pull/2611))
- `sv.tint_image` and `sv.grayscale_image` now accept a single-channel `(H, W)` array or grayscale `Image`, as `sv.letterbox_image` already did. ([#2614](https://github.com/roboflow/supervision/pull/2614))
- New docs guide: "Evaluate targets from a PyTorch DataLoader" in `docs/metrics/mean_average_precision.md`, cross-linked from `docs/how_to/benchmark_a_model.md`. `Detections.from_transformers` gained a docstring note that it expects post-processed predictions, not raw DataLoader targets. ([#2620](https://github.com/roboflow/supervision/pull/2620))
## π Contributors
- **Mohammad Hijjawi** (@MohammadHijjawi97, [LinkedIn](https://www.linkedin.com/in/mohammadhijjawi)) β the `DetectionsSmoother` conflicting-metadata crash, the `KeyPoints` detection-score fix, the YOLO/Pascal VOC empty-mask export fix, the `VertexEllipseHaloAnnotator` rotated-ellipse fix, the `LabelAnnotator` blank-line background fix, and the `polygon_to_mask` crash fix
- **Raghav Rathi** (@raghav-rathi, [LinkedIn](https://www.linkedin.com/in/raghavrathi00/)) β the `pillow_to_cv2` rewrite for every Pillow mode
- **Zachary Alexander** (@zachsplat) β the `LineZone` unconfirmed-track fix
- **NIKHIL** (@Nikhi00718) β the YOLO segmentation-label trailing-value fix
- **Manoj Kumar Thapa** (@iammanoj807, [LinkedIn](https://www.linkedin.com/in/manoj-kumar-thapa-7595a5168)) β the palette-with-alpha `IconAnnotator` fix
- **kevin** (@kevin9327) β the YOLO box-label trailing-value fix
- **Andrew Barnes** (@Bortlesboat, [LinkedIn](https://www.linkedin.com/in/andrew-barnes-705a08195/)) β the CSV Unicode export fix
- **4rch1e** (@archie0732) β the dataset split-ratio validation
- **Salman Ansari** (@salmanwnl44, [LinkedIn](https://www.linkedin.com/in/salmanwnl/)) β the PyTorch DataLoader-targets docs guide
- **Pratik Gandhi** (@pratikgx, [LinkedIn](https://www.linkedin.com/in/pratikgandhix)) β dead-link fixes in the published notebooks
- **Jirka Borovec** (@Borda, [LinkedIn](https://linkedin.com/in/jirka-borovec)) β the `from_sam3` degenerate-fragment fix
______________________________________________________________________
**Full changelog**: https://github.com/roboflow/supervision/compare/0.30.5...0.30.6
Related Repositories
public-apis/public-apisβ
491,135
A collective list of free APIs
NousResearch/hermes-agentβ
255,963
The agent that grows with you
yt-dlp/yt-dlpβ
200,054
A feature-rich command-line audio/video downloader
microsoft/markitdownβ
191,491
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPTβ
187,703
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.