0.30.8
roboflow/supervision0.30.8Oct 6, 2026by Borda
Upgrading?
AI Summary
A patch release improving video quality without OpenCV, fixing YOLO pose label parsing, and correcting mAP calculations for class-agnostic scenarios.
Key Highlights
- `VideoSink` and `process_video` now maintain OpenCV's video bit rate when OpenCV isn't installed.
- YOLO pose labels are now loaded as boxes instead of polygons.
- `MeanAveragePrecision` correctly scores class-agnostic runs when only one side has class IDs.
- Florence-2 detections now return one object per instance, merging split polygons.
- `from_inference` masks no longer drift up and left due to vertex truncation.
Full Release Notes
# v0.30.8 — Sharper video, cleaner labels
Video, YOLO labels, masks, VLM parsing and mAP all get more accurate.
- **`VideoSink`** keeps OpenCV's video quality when OpenCV isn't installed.
- **`from_yolo`** reads pose labels as boxes instead of polygons.
- **`MeanAveragePrecision`** scores class-agnostic runs right when only one side has class IDs.
- **`from_vlm`** returns one Florence-2 detection per object, not one per polygon.
- **`from_inference`** masks no longer drift up to a pixel up and left.
Drop-in upgrade. Without OpenCV, videos get larger; YOLO labels with a negative width or height now raise `ValueError`.
## ✨ Spotlights / highlights
### `sv.VideoSink` and `sv.process_video` keep quality without OpenCV
The PyAV fallback left the encoder bit rate unset, so `mp4v` and `MJPG` files came out at under half of what `cv2.VideoWriter` writes. It now uses OpenCV's rate settings for every codec except H.264. Files get larger and `vp09` may encode more slowly; `codec="avc1"` keeps files small where an H.264 encoder is available. ([#2661](https://github.com/roboflow/supervision/pull/2661))
```python
import supervision as sv
video_info = sv.VideoInfo.from_video_path("in.mp4")
with sv.VideoSink("out.mp4", video_info) as sink: # OpenCV not installed
for frame in sv.get_video_frames_generator("in.mp4"):
sink.write_frame(frame)
# before: mp4v written at under half OpenCV's bit rate, visibly softer
# now: same bit rate OpenCV's writer uses
```
### YOLO pose labels load as boxes
A pose row is a box followed by keypoints. `from_yolo` used to parse the whole row as a polygon, giving wrong boxes and masks nobody asked for. It now reads the box and skips the keypoints that `kpt_shape` declares. ([#2655](https://github.com/roboflow/supervision/pull/2655))
```python
ds = sv.DetectionDataset.from_yolo(
images_directory_path="pose/images",
annotations_directory_path="pose/labels",
data_yaml_path="pose/data.yaml", # kpt_shape: [17, 3]
)
# before: polygon-parsed boxes and masks
# now: one box per row
```
### Class-agnostic mAP with one-sided class IDs
A perfect match scored zero when only one side carried class IDs, such as SAM proposals checked against labeled ground truth. With `class_agnostic=True`, both sides now count as one class.
### One Florence-2 detection per object (#2648)
Florence-2 returns a segmented object as a list of polygons, one per connected region. An object split in two used to come back as two detections; the polygons now merge into one mask with one box around all of them.
### Roboflow masks sit on the right pixels (#2649)
`from_inference` truncated sub-pixel polygon vertices, shifting each mask up and left by up to a pixel. Vertices are now rounded, the way the COCO, YOLO, LabelMe and Pascal VOC loaders already do.
## 🔄 Migration guide
No migration required for this release.
## 📝 Notable changes
### 🌱 Changed
- `sv.DetectionDataset.from_yolo` raises `ValueError` naming the annotation file when a label has a negative width or height; it used to load a box with `x_min` past `x_max`, which made `Detections.area` negative and skewed IoU and NMS. `as_yolo` now orders the corners of a reversed box before measuring, so it no longer writes a file the loader refuses. (#2663)
### 🔧 Fixed
- `sv.VideoSink` and `sv.process_video` write `mp4v`, `MJPG` and other non-H.264 video at OpenCV's bit rate when OpenCV isn't installed. A frame rate of zero or less now raises `RuntimeError` in `sv.VideoSink`, as it does with OpenCV. (#2661)
- `sv.DetectionDataset.from_yolo` reads the box of Ultralytics pose labels and skips their keypoints; a `kpt_shape` other than `[K, 2]` or `[K, 3]` raises `ValueError`. (#2655)
- `sv.DetectionDataset.from_yolo` names a malformed annotation line, one with too few values or, for OBB, not nine, in a `ValueError` instead of failing on an array shape. (#2665)
- `sv.metrics.MeanAveragePrecision(class_agnostic=True)` treats detections without class IDs as the same class as labeled ones, and unsigned class ID arrays no longer raise `OverflowError` on NumPy 2. (#2650)
- `sv.Detections.from_vlm` with `sv.VLM.FLORENCE_2` merges the polygons of one instance into one detection for `<REFERRING_EXPRESSION_SEGMENTATION>` and `<REGION_TO_SEGMENTATION>`, and skips instances with no usable polygon. (#2648)
- `sv.Detections.from_vlm` with `sv.VLM.QWEN_2_5_VL` or `sv.VLM.QWEN_3_VL` recovers complete detections from a response cut off inside a `bbox_2d` array or right after a complete object. (#2666)
- `sv.Detections.from_inference` rounds polygon vertices to the nearest pixel before rasterising masks, and raises `ValueError` for NaN or infinite vertices. (#2649)
- `sv.xyxy_to_mask` returns an empty mask for a box entirely left of or above the image when its maximum coordinate is a negative fraction. (#2646)
- `sv.Detections.get_anchors_coordinates` computes axis-aligned midpoint anchors without integer overflow. (#2660)
- `sv.LineZone.trigger` ages crossing history on frames whose detections lack `tracker_id`, so a reused track ID no longer creates a false crossing after the track expired. (#2644)
- `sv.LineZoneAnnotator(text_orient_to_line=True)` no longer raises `TypeError` without OpenCV for lines drawn right to left. (#2659)
- The Ultralytics, Inference and YOLO-NAS speed estimation examples measure elapsed time from frame indices; a vehicle missed in one frame of three was reported about 44% too fast. (#2654)
- `examples/speed_estimation/rfdetr_example.py` no longer raises `AttributeError`: `supervision._cv2` now provides `getPerspectiveTransform` and `perspectiveTransform`. (#2652)
## 🏆 Contributors
- **Mohammad Hijjawi** (@MohammadHijjawi97, [LinkedIn](https://www.linkedin.com/in/mohammadhijjawi)) — fixed video quality without OpenCV, Florence-2 instance merging and Roboflow mask rounding.
- **Kari Pikkarainen** (@kari-pikkarainen, [LinkedIn](https://www.linkedin.com/in/karipikkarainen/recent-activity/all/)) — fixed speed estimation timing, the NumPy `flip` fallback and the perspective-transform fallbacks.
- **Miral Amin** (@aminmiral) — made YOLO loading reject negative extents and name malformed lines.
- **NIKHIL** (@Nikhi00718) — fixed `LineZone` history expiry and anchor overflow.
- **kevin** (@kevin9327) — made Qwen parsing recover from cut-off responses.
- **A Aswanth Raj** (@aswanth-07, [LinkedIn](https://www.linkedin.com/in/a-aswanth-raj/)) — fixed class-agnostic mAP.
- **Devulapalli Naga Sri Vaishnavi** (@Vaishnavi220506) — fixed masks for off-frame fractional boxes.
- **JANG BYUNGKUN** (@8rulerstar) — fixed YOLO pose label loading.
*Automated contributions: @dependabot*
______________________________________________________________________
**Full changelog**: <https://github.com/roboflow/supervision/compare/0.30.7...0.30.8>
Related Repositories
public-apis/public-apis★ 491,124
A collective list of free APIs
NousResearch/hermes-agent★ 255,892
The agent that grows with you
yt-dlp/yt-dlp★ 199,988
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,477
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,699
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.