{"record":{"id":"68a7cb4720f43292","repo":"roboflow/supervision","slug":"detections-confidence-must-be-given-for-nms-to-be","errorCode":null,"errorMessage":"Detections confidence must be given for NMS to be executed.","messagePattern":"Detections confidence must be given for NMS to be executed\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/core.py","lineNumber":3039,"sourceCode":"            class_agnostic: Whether to perform class-agnostic\n                non-maximum suppression. If True, the class_id of each detection\n                will be ignored. Defaults to False.\n            overlap_metric: Metric used to compute the degree of\n                overlap between pairs of masks or boxes (e.g., IoU, IoS).\n\n        Returns:\n            A new Detections object containing the subset of detections\n                after non-maximum suppression.\n\n        Raises:\n            ValueError: If `confidence` is None and class_agnostic is False.\n                If `class_id` is None and class_agnostic is False.\n        \"\"\"\n        if len(self) == 0:\n            return self\n\n        if self.confidence is None:\n            raise ValueError(\n                \"Detections confidence must be given for NMS to be executed.\"\n            )\n\n        predictions = self._build_nms_predictions(class_agnostic, \"NMS\")\n\n        if self.mask is not None:\n            indices = mask_non_max_suppression(\n                predictions=predictions,\n                masks=self.mask,\n                iou_threshold=threshold,\n                overlap_metric=overlap_metric,\n            )\n        elif ORIENTED_BOX_COORDINATES in self.data:\n            indices = oriented_box_non_max_suppression(\n                predictions=predictions,\n                oriented_boxes=np.asarray(\n                    self.data[ORIENTED_BOX_COORDINATES], dtype=np.float32\n                ),","sourceCodeStart":3021,"sourceCodeEnd":3057,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/core.py#L3021-L3057","documentation":"Detections.with_nms performs non-maximum suppression, which ranks boxes by confidence. Without a confidence array there is no way to decide which box in an overlap group survives, so the method raises this ValueError when self.confidence is None.","triggerScenarios":"Calling detections.with_nms(threshold=...) on a Detections created without confidence — e.g. from connectors that don't produce scores (from_sam, some VLM paths like PaliGemma/DeepSeek/Moondream), or manual cls(xyxy=..., class_id=...) construction.","commonSituations":"SAM/SAM2 segmentation masks have no scores; VLM connectors return class names without probabilities; filtering tracker output that dropped the confidence column.","solutions":["If scores exist upstream, attach them: cls(xyxy=..., confidence=scores, ...).","If you want to suppress purely on IoU without scores, implement selection manually (e.g. sv.utils.iou_and_nms or cv2.dnn.NMSBoxes with a dummy uniform score) — uniform scores make NMS keep first-of-group.","For VLM results that genuinely have no confidence, skip with_nms or deduplicate by class_name text."],"exampleFix":"# before\ndetections = sv.Detections(xyxy=boxes, mask=masks)  # from SAM, no confidence\nclean = detections.with_nms(threshold=0.5)  # ValueError\n\n# after\ndetections = sv.Detections(\n    xyxy=boxes,\n    mask=masks,\n    confidence=np.ones(len(boxes), dtype=float),  # uniform scores for IoU-only NMS\n)\nclean = detections.with_nms(threshold=0.5)","handlingStrategy":"validation","validationCode":"def with_confidence_or_default(dets: sv.Detections):\n    if dets.confidence is None:\n        dets = dets.__class__(\n            xyxy=dets.xyxy,\n            mask=dets.mask,\n            class_id=dets.class_id,\n            confidence=np.ones(len(dets), dtype=float),\n        )\n    return dets\n\nclean = with_confidence_or_default(detections).with_nms(threshold=0.5)","typeGuard":"def has_confidence(dets: sv.Detections) -> bool:\n    return dets.confidence is not None","tryCatchPattern":"try:\n    clean = detections.with_nms(threshold=0.5)\nexcept ValueError as e:\n    if 'confidence must be given' in str(e):\n        raise ValueError('source produced no scores; NMS undefined') from e\n    raise","preventionTips":["Propagate model scores into Detections.confidence","Treat uniform-confidence NMS as first-of-group tie-breaking, not ranking","Skip NMS for score-less connectors like from_sam"],"tags":["nms","confidence","detections","suppression"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}