Ask Your Question
1

NMSBoxes output with top_k parameter

asked 2020-07-23 08:49:37 -0600

LauLauThom gravatar image

updated 2020-07-27 04:11:27 -0600

Hi all, the top_K parameter in the cv2.dnn.NMSBoxes correspond to the maximum number of bounding-boxes to return right ? Like if we know how many object we expect in the image.

If that's the case, I have an unexpected output when setting top_k to a value >0.
With the default value (<0), I have a sensible set of bounding-boxes (on the left below).
However with the same parameters, except setting top_k to an actual value, here 4, I get only the 2 top detections and not the top 4. Why is that ?

The bounding boxes with index 4, 100, 72 and 17 are indeed the one I want, so I can use top_k<0 and select the top_4 afterwards but I though setting top_K in the NMS could stop the NMS earlier and thus save time.

I am using
- opencv-python-headless 4.3.0.36 (installed via pip)
- python 3.7.4
on a win10 machine

Thanks !

image description

EDIT: Test code

import cv2
listBoxes = [
 (946, 784, 414, 400),
 (1525, 968, 414, 400),
 (1533, 960, 414, 400),
 (947, 784, 400, 414),
 (1173, 1354, 414, 400),
 (1459, 474, 400, 414),
 (1021, 888, 414, 400),
 (1450, 492, 400, 414),
 (1398, 889, 414, 400),
 (1005, 872, 400, 414),
 (686, 1367, 414, 400),
 (697, 1371, 414, 400),
 (694, 1371, 414, 400),
 (1128, 1377, 414, 400),
 (950, 787, 414, 400),
 (1438, 481, 414, 400),
 (1064, 1238, 414, 400),
 (1455, 485, 414, 400),
 (111, 787, 414, 400),
 (109, 782, 414, 400)]

listScores = [
 1.0,
 0.5919371843338013,
 0.5894666314125061,
 0.5689446926116943,
 0.5510676503181458,
 0.5381054282188416,
 0.5311822891235352,
 0.5298448204994202,
 0.5123124122619629,
 0.511840283870697,
 0.5080571174621582,
 0.5080069303512573,
 0.5079731941223145,
 0.5000045895576477,
 0.49151238799095154,
 0.4728872776031494,
 0.4612887501716614,
 0.4540329873561859,
 0.4483684003353119,
 0.44806933403015137]

'''
# Cast boxes to float (optional)
convertBox = lambda box : list(map(float, box)) 
listBoxes = list(map(convertBox, listBoxes))
print (listBoxes)
'''

indexes1 = cv2.dnn.NMSBoxes(listBoxes, listScores, score_threshold=0.4, nms_threshold=0.3, top_k=5)
print(indexes1)

print("-------")

indexes2 = cv2.dnn.NMSBoxes(listBoxes, listScores, score_threshold=0.4, nms_threshold=0.3)
print(indexes2)
edit retag flag offensive close merge delete

Comments

can you try to come up with a small, reproducable example ?

berak gravatar imageberak ( 2020-07-24 01:31:47 -0600 )edit
1

I added a test code, with 2 calls to NMSBoxes: with and without the top_k parameters. With top_k=5, it returns only 3 detections.

I'm wondering if it could be related to this PR https://github.com/opencv/opencv/pull..., but it should be fixed in 4.3.0 isn't it ?

LauLauThom gravatar imageLauLauThom ( 2020-07-27 04:16:03 -0600 )edit

nice example !

using latest master, i get:

[[0]
 [1]
 [4]]
-------
[[ 0]
 [ 1]
 [ 4]
 [ 5]
 [10]
 [18]]
berak gravatar imageberak ( 2020-07-27 04:39:45 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2020-07-27 04:56:28 -0600

berak gravatar image

naa, no bug here ;)

if you look at the src, the algorithm is like this:

  1. sort by score
  2. cut off top_k elems
  3. compute overlaps (cluster)

so, step 3 will reduce the list of boxes even further, since several boxes will collapse to a single one.

again, you get at most top_k items (and only if it does not find any significant overlaps)

edit flag offensive delete link more

Comments

1

Alright ! Thanks for spotting it !!
I though it was ordered as 1, 3, 2 (loop to compute pairwise overlap, until top_k are collected).
I had written my own NMS implementation initially and that's how I was using it, but fair enough !

Maybe that could be mentioned in the function docstring, it was not really obvious :P
I could eventually submit a short PR for that ;)

LauLauThom gravatar imageLauLauThom ( 2020-07-27 07:48:16 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-07-23 08:49:37 -0600

Seen: 1,707 times

Last updated: Jul 27 '20