0.29.1

PipedreamHQ/pipedream0.29.1Jun 23, 2026by Borda

AI Summary

A maintenance release for the supervision library, adding NMS for pose estimation and fixing various bugs in metrics, exports, and serialization.

Key Highlights

  • New `KeyPoints.with_nms()` method for pose estimation
  • Fixes for Pascal VOC export mutating bounding boxes
  • Fixes for Precision and F1Score counting background false positives

New Features

  • KeyPoints.with_nms() method for removing duplicate skeletons
  • Pascal VOC export no longer mutates bounding boxes
  • Precision and F1Score correctly count background false positives
  • DetectionsSmoother works with confidence-free detections
  • JSONSink serializes NumPy scalars in custom_data
  • approximate_polygon respects point-count budget
  • COCO export preserves all segments for multi-part masks
  • HaloAnnotator is ~4x faster with CompactMask detections
  • Mask IoU uses less peak memory
  • mask_to_xyxy and KeyPoints.as_detections vectorized

Full Release Notes

## What's new

### 🚀 `KeyPoints.with_nms()` — NMS for pose estimation

```python
import supervision as sv

key_points = model.predict(image)  # sv.KeyPoints
key_points = key_points.with_nms(threshold=0.5)  # removes duplicate skeletons
```

Derives axis-aligned bounding boxes from each skeleton's valid (non-zero and visible) keypoints, then applies standard box NMS. Supports `class_agnostic` mode and any `OverlapMetric` (`IOU`, `IOS`). Raises `ValueError` if `detection_confidence` is not set.


https://github.com/user-attachments/assets/ed7bd310-4868-4275-ae04-c88e7a0c2561

---

## Notable changes

### Bug fixes

- **`sv.DetectionDataset.as_pascal_voc` no longer mutates bounding boxes** (#2341) Previously, every export shifted every bounding box by +1 px in-place. A second call compounded the shift. Fixed by rebinding to a new array; on-disk XML output is unchanged.

- **`sv.Precision` and `sv.F1Score` correctly count background false positives** (#2331) Predictions on images with no ground-truth objects, and predictions of classes absent from any annotation, were previously ignored. Under `MICRO` and `MACRO` averaging they are now counted as false positives. `WEIGHTED` averaging is unchanged. **Users should re-evaluate existing metric results after upgrading.**

- **`sv.DetectionsSmoother` works with confidence-free detections** (#2333) The smoother no longer raises when detections have no confidence scores. Confidence is averaged over the frames that carry it; tracks without any confidence produce `None`.

- **`sv.Detections.from_vlm` is robust to malformed Gemini/Qwen output** (#2342) Valid JSON that is not a list, or whose elements are not dicts, now degrades to empty `Detections` instead of raising `TypeError`. A malformed mask value in Gemini 2.5 responses no longer misaligns the `xyxy`/`confidence`/`masks` arrays.

- **`sv.JSONSink` serializes NumPy scalars in `custom_data`** (#2334) `np.int64` frame indices and other NumPy scalars in `custom_data` no longer raise `TypeError` at flush time. NumPy arrays are serialized as lists. The file handle closes even when serialization fails.

- **`sv.approximate_polygon` respects the point-count budget** (#2332) The function now returns at most `floor(N * (1 - percentage))` points (minimum 3). Previously it could return more points than requested. `epsilon_step` is now validated to be positive.

- **COCO export preserves all segments for multi-part masks** (#2322) Previously, only the first polygon was written when a non-crowd detection had disjoint mask segments. All polygon parts are now written.

### Performance

- **`sv.HaloAnnotator` is ~4× faster with `CompactMask` detections** (#2339) `HaloAnnotator` now uses the same optimized CompactMask paint path as `MaskAnnotator`. Previously it materialized each mask full-frame; now it operates on the bounding-box crop. Annotated output is unchanged.

- **Mask IoU uses less peak memory** (#2323) Mask IoU computation now uses matrix multiplication on flattened masks instead of an explicit `(N, M, H, W)` tensor. For masks larger than 4096×4096 px, computation promotes to float64 automatically. Results are numerically identical.

- **`sv.mask_to_xyxy` and `sv.KeyPoints.as_detections` vectorized** (#2330) Both functions now use batched NumPy operations instead of per-element loops. Outputs are bit-identical.

---

## Contributors

- **Ruben Haisma** ([@RubenHaisma](https://github.com/RubenHaisma), [LinkedIn](https://www.linkedin.com/in/rubenhaisma/)) — VLM robustness, Pascal VOC export fix, DetectionsSmoother, JSONSink, metrics correctness, polygon budgeting, vectorization
- **Agis Kounelis** ([@kounelisagis](https://github.com/kounelisagis), [LinkedIn](https://www.linkedin.com/in/kounelisagis/)) — HaloAnnotator perf, mask IoU matmul, mask_to_xyxy/KeyPoints.as_detections vectorization, OBB cookbook
- **Piotr Skalski** ([@SkalskiP](https://github.com/SkalskiP), [LinkedIn](https://www.linkedin.com/in/skalskip92/)) — `KeyPoints.with_nms()`
- **Abdelrahman Gomaa** ([@abdogomaa201099](https://github.com/abdogomaa201099), [LinkedIn](https://www.linkedin.com/in/abdelrahman-gomaa-96912528b/)) — COCO multi-polygon export

---

**Full Changelog**: https://github.com/roboflow/supervision/compare/0.29.0...0.29.1