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

  1. Remove the `shift` argument (use default 0) and pass integer pixel coordinates
  2. Pre-divide fixed-point coordinates: `(pt / (1 << shift)).round().astype(int)` before drawing
  3. 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

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


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/9a98c35555320a72. Report an issue: GitHub.