{"record":{"id":"a42c18538ce09df3","repo":"roboflow/supervision","slug":"areas-must-be-shaped-n","errorCode":null,"errorMessage":"Areas must be shaped (N,)","messagePattern":"Areas must be shaped \\(N,\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/metrics/utils/object_size.py","lineNumber":156,"sourceCode":"\n    Returns:\n        The size category of each area, matching the enum values of\n        `ObjectSizeCategory`. Shaped (N,).\n\n    Raises:\n        ValueError: If `areas` is not one-dimensional.\n\n    Example:\n        ```pycon\n        >>> import numpy as np\n        >>> from supervision.metrics.utils.object_size import get_area_size_category\n        >>> get_area_size_category(np.array([100, 2500, 10000]))\n        array([1, 2, 3])\n\n        ```\n    \"\"\"\n    if len(areas.shape) != 1:\n        raise ValueError(\"Areas must be shaped (N,)\")\n\n    result = np.full(areas.shape, ObjectSizeCategory.ANY.value)\n    sm, lg = SIZE_THRESHOLDS\n    result[areas < sm] = ObjectSizeCategory.SMALL.value\n    result[(areas >= sm) & (areas < lg)] = ObjectSizeCategory.MEDIUM.value\n    result[areas >= lg] = ObjectSizeCategory.LARGE.value\n    return result\n\n\ndef get_mask_size_category(\n    mask: npt.NDArray[np.bool_] | CompactMask,\n) -> npt.NDArray[np.int_]:\n    \"\"\"\n    Get the size category of detection masks.\n\n    Args:\n        mask: The mask array shaped (N, H, W), or a\n            :class:`~supervision.detection.compact_mask.CompactMask`.","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/metrics/utils/object_size.py#L138-L174","documentation":"Raised by get_area_size_category() when the areas array is not one-dimensional. The function maps each scalar area to a size bucket via boolean masks, so a 2-D input (e.g. an (N,1) column) breaks the elementwise bucketing. Validation happens before the thresholds are applied.","triggerScenarios":"Calling get_area_size_category with areas shaped (N, 1) (common after np.sum(..., keepdims=True) or df[['area']].values), or with a scalar 0-D array.","commonSituations":"Areas extracted from a pandas DataFrame with double brackets producing (N,1); results of reductions with keepdims=True; nested lists passed directly instead of flattened.","solutions":["Flatten before calling: np.asarray(areas).reshape(-1) or .ravel()","Use single brackets when extracting from DataFrames: df['area'].values","Avoid keepdims=True on the reduction that produces the areas"],"exampleFix":"# before\nareas = df[['area']].to_numpy()        # (N, 1)\nget_area_size_category(areas)          # ValueError\n\n# after\nareas = df['area'].to_numpy()          # (N,)\nget_area_size_category(areas)","handlingStrategy":"validation","validationCode":"areas = np.asarray(areas).reshape(-1)\nif areas.ndim != 1:\n    raise ValueError('areas must be 1-D')\ncats = get_area_size_category(areas)","typeGuard":"import numpy as np\n\ndef is_flat_vector(arr: np.ndarray) -> bool:\n    \"\"\"True when arr is one-dimensional.\"\"\"\n    return arr.ndim == 1","tryCatchPattern":"try:\n    cats = get_area_size_category(areas)\nexcept ValueError as e:\n    if 'shaped (N,)' in str(e):\n        cats = get_area_size_category(np.asarray(areas).ravel())\n    else:\n        raise","preventionTips":["Use df['col'].to_numpy() (single brackets) rather than df[['col']].to_numpy()","Avoid keepdims=True on reductions that feed per-item arrays into metrics"],"tags":["metrics","object-size","shape-validation","numpy"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}