Search code examples
python-3.xopencvobject-detectionyolo

Why NMSboxes is not eliminating multiple bounding boxes?


First of all here is my code :

        image = cv2.imread(filePath)
        height, width, channels = image.shape
        
        # USing blob function of opencv to preprocess image
        blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
        swapRB=True, crop=False)
        #Detecting objects
        net.setInput(blob)
        outs = net.forward(output_layers)
        
        # Showing informations on the screen
        class_ids = []
        confidences = []
        boxes = []

        for out in outs:
            for detection in out:
                scores = detection[5:]
                class_id = np.argmax(scores)
                confidence = scores[class_id]
                if confidence > 0.7:
                    # Object detected
                    center_x = int(detection[0] * width)
                    center_y = int(detection[1] * height)
                    w = int(detection[2] * width)
                    h = int(detection[3] * height)

                    # Rectangle coordinates
                    x = int(center_x - w / 2)
                    y = int(center_y - h / 2)

                    boxes.append([x, y, w, h])
                    confidences.append(float(confidence))
                    class_ids.append(class_id)
                    
                indexes = cv2.dnn.NMSBoxes(boxes, confidences,score_threshold=0.4,nms_threshold=0.8,top_k=1)
                
        font = cv2.FONT_HERSHEY_PLAIN
        colors = np.random.uniform(0, 255, size=(len(classes), 3))
        labels = ['bicycle','car','motorbike','bus','truck']
        for i in range(len(boxes)):
            if i in indexes:
                label = str(classes[class_ids[i]])
                if label in labels:
                    x, y, w, h = boxes[i]
                    color = colors[class_ids[i]]
                    cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
                    cv2.putText(image, label, (x, y + 30), font, 2, color, 3)
        cv2.imshow(fileName,image)

My Question is : Isn't cv2.dnn.NMSBoxes is suppose to eliminate multiple bounding boxes? then why I still get output like sample below :

sample 1 of multiple bounding blocks

sample 2 of multiple bounding blocks

What I expected is something like below :

enter image description here

Did I do something wrong with my code? Is there any better alternative? Thank you very much for your help.


Solution

  • The process of NMS goes something like this
    Input - A list of Proposal boxes (B), corresponding confidence scores (S) and an overlap threshold (N)
    Output - A list of filtered proposals (D)

    Algorithm

    1. Select the proposal with the highest confidence score, remove it from B, and add it to the final proposal list D. (Initially D is empty)
    2. Now compare this with all the proposals — i.e. calculate the IOU (Intersection over Union) of this with every other proposal. If the IOU is greater than the threshold, remove that proposal from B
    3. This process is repeated until there are no more proposals left in B

    The IOU threshold is the nms_threshold. So if you have a larger value for it, you're essentially enforcing two boxes to have a very high overlap (this will vary based on the type of object being detected) and the box will be removed only if it has an IOU more than 0.8 with another box. Since there's usually not this much overlap, the boxes won't be removed. Reducing this value will make it easier to remove redundant detections

    I hope this makes sense.

    You can read more about Non-Maxima Suppression here