{"record":{"id":"17a37f067c549577","repo":"roboflow/supervision","slug":"only-border-constant-is-supported-by-the-fallback","errorCode":null,"errorMessage":"Only BORDER_CONSTANT is supported by the fallback","messagePattern":"Only BORDER_CONSTANT is supported by the fallback","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/_cv2/_image.py","lineNumber":45,"sourceCode":"    elif flip_code == -1:\n        axes = (0, 1)\n    else:\n        raise ValueError(f\"Unsupported flip code: {flip_code}\")\n    return np.ascontiguousarray(np.flip(image, axis=axes))\n\n\ndef _copy_make_border(\n    image: npt.NDArray[Any],\n    top: int,\n    bottom: int,\n    left: int,\n    right: int,\n    border_type: int,\n    value: int | float | Sequence[int | float] = 0,\n) -> npt.NDArray[Any]:\n    \"\"\"Add a constant border around an image.\"\"\"\n    if border_type != _BORDER_CONSTANT:\n        raise ValueError(\"Only BORDER_CONSTANT is supported by the fallback\")\n    if min(top, bottom, left, right) < 0:\n        raise ValueError(\"Border sizes must be non-negative\")\n\n    height, width = image.shape[:2]\n    shape = (height + top + bottom, width + left + right, *image.shape[2:])\n\n    # OpenCV's Scalar(v) fills only channel 0 and zero-pads the rest for\n    # multichannel images — a bare scalar is treated the same as a\n    # length-1 sequence, not broadcast to every channel.\n    sequence_value = value if isinstance(value, Sequence) else (value,)\n    values = np.asarray(sequence_value, dtype=image.dtype).reshape(-1)\n    if image.ndim == 2:\n        fill_value: Any = values[0] if values.size else 0\n    else:\n        fill = np.zeros(image.shape[2], dtype=image.dtype)\n        fill[: min(values.size, image.shape[2])] = values[: image.shape[2]]\n        fill_value = fill.reshape((1, 1, -1))\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/_cv2/_image.py#L27-L63","documentation":"The fallback `cv2.copyMakeBorder` at src/supervision/_cv2/_image.py:45 implements only BORDER_CONSTANT (padding with a fixed value) because that is all supervision uses. Border modes like BORDER_REFLECT, BORDER_REPLICATE, or BORDER_WRAP require edge-mirroring logic the fallback does not provide, so they are rejected up front.","triggerScenarios":"Calling `cv2.copyMakeBorder(img, t, b, l, r, cv2.BORDER_REFLECT)` (or any non-constant border type) while running without opencv-python, e.g. in data-augmentation or letterboxing code.","commonSituations":"Augmentation pipelines ported from training code that use reflective padding; letterbox resize helpers using BORDER_REFLECT_101 (the OpenCV default is BORDER_CONSTANT|BORDER_ISOLATED variants differ by call).","solutions":["Use `cv2.BORDER_CONSTANT` with an explicit fill `value`","Implement reflect/replicate padding yourself with `np.pad` mode equivalents (`mode='reflect'`, `'edge'`)","Install `opencv-python` for the full set of border modes"],"exampleFix":"// before\npadded = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_REFLECT)\n\n// after\npadded = np.pad(img, ((10, 10), (10, 10)) + ((0, 0),) * (img.ndim - 2), mode='reflect')","handlingStrategy":"fallback","validationCode":"import numpy as np\n\nBORDER_MODES = {\"constant\": None, \"reflect\": \"reflect\", \"reflect_101\": \"reflect\", \"replicate\": \"edge\", \"wrap\": \"wrap\"}\n\ndef pad_image(image, top, bottom, left, right, mode: str = \"constant\", value=0):\n    \"\"\"Portable padding: BORDER_CONSTANT via fallback, others via np.pad.\"\"\"\n    if mode == \"constant\":\n        return cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=value)\n    np_mode = BORDER_MODES[mode]\n    pad_width = ((top, bottom), (left, right)) + ((0, 0),) * (np.asarray(image).ndim - 2)\n    return np.pad(image, pad_width, mode=np_mode)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer BORDER_CONSTANT with an explicit value for portable supervision code","Use np.pad directly when you need reflect/replicate semantics and cv2 may be absent"],"tags":["cv2-fallback","padding","border","unsupported-operation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}