From a3fb5baf95906f88e017c8788943e715bd91fcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Thu, 18 Jun 2026 13:05:39 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20NMS=20identical=20area=20tie=E2=80=91bre?= =?UTF-8?q?aker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In cases when both input bounding boxes have the same score and area, operation leaves them both. This causes duplicates in output mask. It should leave only single bounding box while discarding all the other duplicates. --- src/cvcuda/priv/OpNonMaximumSuppression.cu | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/cvcuda/priv/OpNonMaximumSuppression.cu b/src/cvcuda/priv/OpNonMaximumSuppression.cu index 7d1ae495e..ccedef743 100644 --- a/src/cvcuda/priv/OpNonMaximumSuppression.cu +++ b/src/cvcuda/priv/OpNonMaximumSuppression.cu @@ -99,11 +99,24 @@ __global__ void NonMaximumSuppression(cuda::Tensor2DWrap i const int2 coordY{bboxY, batchIdx}; const T srcY = inBBoxes[coordY]; - if (ComputeIoU(srcX, srcY) > iouThreshold) + if (ComputeIoU(srcX, srcY) <= iouThreshold) { - const float scoreY = inScores[coordY]; + continue; + } + + const float scoreY = inScores[coordY]; + + if (scoreX < scoreY) + { + discard = true; + break; + } + else if (scoreX == scoreY) + { + const float areaX = ComputeArea(srcX); + const float areaY = ComputeArea(srcY); - if (scoreX < scoreY || (scoreX == scoreY && ComputeArea(srcX) < ComputeArea(srcY))) + if (areaX < areaY || (areaX == areaY && bboxX > bboxY)) { discard = true; break;