{"record":{"id":"99544dab3ef0c848","repo":"roboflow/supervision","slug":"detections-confidence-must-be-given-for-nmm-to-be","errorCode":null,"errorMessage":"Detections confidence must be given for NMM to be executed.","messagePattern":"Detections confidence must be given for NMM to be executed\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/core.py","lineNumber":3189,"sourceCode":"            is the tightest rectangle at the winner's orientation enclosing all\n            corners contributed by every detection in the group. The winner is\n            the highest-confidence detection in the group. The axis-aligned\n            ``xyxy`` field is updated to the tight bounding box of that rect.\n            For zero-rotation OBBs this equals the axis-aligned union exactly;\n            for rotated OBBs the merged rect inherits the winner's rotation angle.\n            Groups of size 1 keep the original OBB unchanged.\n\n        Raises:\n            ValueError: If `confidence` is None or `class_id` is None and\n                class_agnostic is False.\n\n        ![non-max-merging](https://media.roboflow.com/supervision-docs/non-max-merging.png){ align=center width=\"800\" }\n        \"\"\"  # noqa: E501 // docs\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 NMM to be executed.\"\n            )\n\n        predictions = self._build_nms_predictions(class_agnostic, \"NMM\")\n\n        if self.mask is not None:\n            merge_groups = mask_non_max_merge(\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            merge_groups = oriented_box_non_max_merge(\n                predictions=predictions,\n                oriented_boxes=np.asarray(\n                    self.data[ORIENTED_BOX_COORDINATES], dtype=np.float32\n                ),","sourceCodeStart":3171,"sourceCodeEnd":3207,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/core.py#L3171-L3207","documentation":"Detections.with_non_max_merge (with_nmm) merges overlapping boxes and computes a confidence-weighted merge; the weighting requires per-box scores. If self.confidence is None the method raises this ValueError before dispatching to the merge routine.","triggerScenarios":"Calling detections.with_nmm(threshold=...) on a Detections created without confidence — e.g. from_sam output, VLM connectors (PaliGemma, DeepSeek-VL2, Moondream) that populate only class_name, or manual cls(xyxy=...) construction.","commonSituations":"Merging duplicate SAM/VLM boxes that have no scores; constructing Detections from external detectors (HTTP APIs, ONNX custom pipelines) that don't expose scores; post-processing steps that drop the confidence field.","solutions":["Provide confidence at construction time from whatever scoring source exists.","Use uniform scores np.ones(len(detections)) if you only need geometric merging and accept unweighted behavior.","If no scores are meaningful, replace NMM with your own IoU-grouping + box averaging loop."],"exampleFix":"# before\ndetections = sv.Detections(xyxy=boxes)  # no confidence\nmerged = detections.with_nmm(threshold=0.5)  # ValueError\n\n# after\ndetections = sv.Detections(xyxy=boxes, confidence=np.ones(len(boxes)))\nmerged = detections.with_nmm(threshold=0.5)","handlingStrategy":"validation","validationCode":"if detections.confidence is None:\n    detections = sv.Detections(\n        xyxy=detections.xyxy,\n        class_id=detections.class_id,\n        confidence=np.ones(len(detections), dtype=float),\n    )\nmerged = detections.with_nmm(threshold=0.5)","typeGuard":"def has_confidence(dets: sv.Detections) -> bool:\n    return dets.confidence is not None","tryCatchPattern":"try:\n    merged = detections.with_nmm(threshold=0.5)\nexcept ValueError as e:\n    if 'confidence must be given' in str(e):\n        raise ValueError('cannot weight NMM merge without scores') from e\n    raise","preventionTips":["Feed detector scores into Detections even when you don't visualize them","Guard confidence before NMS/NMM/Soft-NMS in one shared helper","Know which connectors produce confidence=None (SAM, several VLMs)"],"tags":["nmm","merge","confidence","detections"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}