Pytorch-yolov3: True positive count may be wrong

Created on 19 Jul 2019  路  9Comments  路  Source: eriklindernoren/PyTorch-YOLOv3

In get_batch_statistics(), it counts true_positives like this:

for pred_i, (pred_box, pred_label) in enumerate(zip(pred_boxes, pred_labels)):

 # If targets are found break
    if len(detected_boxes) == len(annotations):
        break

    # Ignore if label is not one of the target labels
    if pred_label not in target_labels:
        continue

    iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)
    if iou >= iou_threshold and box_index not in detected_boxes:
        true_positives[pred_i] = 1
        detected_boxes += [box_index]

So it is possible that target_labels is [1, 2], and the iou of pred_boxes[0] and target_boxes[0] is over iou_threshold while pred_labels[0] is 2 (which should be 1 to make it a TP), but still here true_positives[0] will be 1.

I suggest you modify the third "if" to
if iou >= iou_thresh and box_index not in detected_boxes and pred_label == target_labels[box_index]:

Most helpful comment

Here's the link to the code.
https://github.com/eriklindernoren/PyTorch-YOLOv3/blob/1c5a58f47c9904a9fe9903b46c73bf93a230d8e7/utils/utils.py#L166

And, @youzunzhi 's suggestion is the following.

            for pred_i, (pred_box, pred_label) in enumerate(zip(pred_boxes, pred_labels)):

                # If targets are found break
                if len(detected_boxes) == len(annotations):
                    break

                # Ignore if label is not one of the target labels
                if pred_label not in target_labels:
                    continue

                iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)
-                if iou >= iou_threshold and box_index not in detected_boxes:
+                if iou >= iou_thresh and box_index not in detected_boxes and pred_label == target_labels[box_index]:
                    true_positives[pred_i] = 1
                    detected_boxes += [box_index]

All 9 comments

Here's the link to the code.
https://github.com/eriklindernoren/PyTorch-YOLOv3/blob/1c5a58f47c9904a9fe9903b46c73bf93a230d8e7/utils/utils.py#L166

And, @youzunzhi 's suggestion is the following.

            for pred_i, (pred_box, pred_label) in enumerate(zip(pred_boxes, pred_labels)):

                # If targets are found break
                if len(detected_boxes) == len(annotations):
                    break

                # Ignore if label is not one of the target labels
                if pred_label not in target_labels:
                    continue

                iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)
-                if iou >= iou_threshold and box_index not in detected_boxes:
+                if iou >= iou_thresh and box_index not in detected_boxes and pred_label == target_labels[box_index]:
                    true_positives[pred_i] = 1
                    detected_boxes += [box_index]

@youzunzhi
@peaceiris
How much does this change affect the mAP?

@H-YunHui It is hard to say.

@youzunzhi @peaceiris
Another problem with calculating TP,
iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)

The code just calculates max matched IOU, However, predict box may have the IOU(> iou_thresh) with another gt box, and also predict right.

@ujsyehao Hello, have you solved this problem? I have another question. For one ground-truth, we have found a matched predict box. In the next iteration, another predict box has a higher IOU than the already matched box. However, as this ground-truth already finds its matched box, we will ignore the second box, as in the code:
if iou >= iou_threshold and box_index not in detected_boxes:

In summary, for one ground-truth, the pred_box having the highest IOU is regarded as TP. So, I think we should iterate the target_boxes instead of pred_boxes.

@youzunzhi @peaceiris
Another problem with calculating TP,
iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)

The code just calculates max matched IOU, However, predict box may have the IOU(> iou_thresh) with another gt box, and also predict right.

here's my solution.
`

             ...
            # Ignore if label is not one of the target labels
            if pred_label not in target_labels:
                continue    

            iou = bbox_iou(pred_box.unsqueeze(0), target_boxes)
        mask_matched = (target_labels == pred_label) & (iou >= iou_threshold)

        iou_matched = torch.where(mask_matched, iou, torch.zeros_like(iou))
        iou_max, box_index = iou_matched.max(0)

        if iou_max >= iou_threshold and box_index not in detected_boxes:
            true_positives[pred_i] = 1
            detected_boxes += [box_index]

`

I have another question. Suppose there are two target_box, when pred_box[0] matches target_box[0]銆乼arget_box[1], will a pred_box match two target box?

I have another question. Suppose there are two target_box, when pred_box[0] matches target_box[0]銆乼arget_box[1], will a pred_box match two target box?

@zxj11838 In this implementation, pred_box[0] will be added to detected_boxes and it won't be count as another true positive any more.

i think this is correct

            iou_sort, box_index_sort = bbox_iou(pred_box.unsqueeze(0), target_boxes).sort(descending=True) 
            for iou,box_index in zip(iou_sort,box_index_sort):
                if iou >= iou_threshold and box_index not in detected_boxes and pred_label == target_labels[box_index]:
                    true_positives[pred_i] = 1
                    detected_boxes += [box_index]
Was this page helpful?
0 / 5 - 0 ratings

Related issues

qilong-zhang picture qilong-zhang  路  5Comments

andohuman picture andohuman  路  3Comments

MAP
nationalflag picture nationalflag  路  5Comments

hezhangubc picture hezhangubc  路  4Comments

ghimiredhikura picture ghimiredhikura  路  4Comments