roboflow/supervision · error · ValueError
Only unshifted drawing coordinates are supported
Error message
Only unshifted drawing coordinates are supported
What it means
OpenCV drawing functions accept a `shift` parameter meaning coordinates are fixed-point with `shift` fractional bits. The Pillow-based fallback cannot reproduce sub-pixel fixed-point rasterization, so `_validate_shift` at src/supervision/_cv2/_drawing.py:65 rejects any non-zero shift rather than silently drawing at wrong positions.
Source
Thrown at src/supervision/_cv2/_drawing.py:65
return round(point[0]), round(point[1])
def _points(points: npt.NDArray[Any], offset: tuple[int, int] = (0, 0)) -> list[_Point]:
"""Normalize OpenCV polygon shapes to integer Pillow coordinates."""
values = np.asarray(points)
if values.size == 0:
return []
if values.ndim not in (2, 3) or values.shape[-1] != 2:
raise ValueError("Drawing points must have shape (N, 2) or (N, 1, 2)")
normalized = np.rint(values.reshape(-1, 2)).astype(np.int64)
normalized += np.asarray(offset, dtype=np.int64)
return [(int(x), int(y)) for x, y in normalized]
def _validate_shift(shift: int) -> None:
"""Reject fixed-point coordinates not supported by the fallback."""
if shift != 0:
raise ValueError("Only unshifted drawing coordinates are supported")
def _line(
img: _ImageArray,
pt1: Sequence[int | float],
pt2: Sequence[int | float],
color: Any,
thickness: int = 1,
lineType: int = 8,
shift: int = 0,
) -> _ImageArray:
"""Draw a line in place using Pillow's integer rasterization."""
del lineType
_validate_shift(shift)
width = max(1, thickness)
mask = _drawing_mask(
img,
lambda draw: draw.line([_point(pt1), _point(pt2)], fill=1, width=width),View on GitHub (pinned to 7f254d9784)
Solutions
- Remove the `shift` argument (use default 0) and pass integer pixel coordinates
- Pre-divide fixed-point coordinates: `(pt / (1 << shift)).round().astype(int)` before drawing
- Install `opencv-python` if sub-pixel fixed-point drawing is a hard requirement
Example fix
// before cv2.line(img, (160, 320), (480, 640), color, 2, cv2.LINE_8, shift=1) // after start = (160 >> 1, 320 >> 1) end = (480 >> 1, 640 >> 1) cv2.line(img, start, end, color, 2, cv2.LINE_8, shift=0)
Defensive patterns
Strategy: validation
Validate before calling
def unshift_points(points, shift: int):
"""Convert fixed-point coordinates to pixel coordinates before drawing."""
if shift == 0:
return points
return [(int(x) >> shift, int(y) >> shift) for x, y in points] Prevention
- Avoid the shift parameter entirely in supervision-based drawing code
- When porting OpenCV snippets, strip shift and pre-scale coordinates yourself
When it happens
Trigger: Calling `cv2.line`/`rectangle`/`circle`/`polylines`/`fillPoly` fallback equivalents with `shift > 0` (e.g. `cv2.line(img, pt1, pt2, color, 1, 8, shift=4)`), typically when porting OpenCV sample code that uses fixed-point coordinates for anti-aliased sub-pixel precision.
Common situations: Environments without opencv-python where copied OpenCV snippets keep the `shift` argument; high-precision overlay code that multiplies coordinates by 2^shift.
Related errors
- Drawing points must have shape (N, 2) or (N, 1, 2)
- Only None hierarchy is supported by the fallback
- `image` must be a numpy.ndarray or PIL.Image.Image. Received
- `image` must be a numpy.ndarray or PIL.Image.Image. Received
- Expected shape (H,W), (H,W,3), or (H,W,4), got {image.shape}
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/9a98c35555320a72.
Report an issue: GitHub.