matterport / Mask_RCNN

Mask R-CNN for object detection and instance segmentation on Keras and TensorFlow
Other
24.63k stars 11.7k forks source link

Calculating mAP for multiple classes #2262

Open WillianaLeite opened 4 years ago

WillianaLeite commented 4 years ago

I trained my mask-rcnn model with two classes and now I would like to calculate the average Mean Precision (mAP) of all classes, so I know that I need to calculate the mAP of each class and then make an average to obtain the general mAP . For that, I modified compute_matches as suggested in: #2136 and my code in utils.py was as follows:


def compute_matches(gt_boxes, gt_class_ids, gt_masks,
                    pred_boxes, pred_class_ids, pred_scores, pred_masks,class_id,
                    iou_threshold=0.5, score_threshold=0.0):
    gt_boxes=gt_boxes[np.where(gt_class_ids==class_id])]#comeca aqui
    gt_masks=gt_masks[:,:,gt_class_ids==class_id]
    pred_boxes=pred_boxes[np.where(pred_class_ids==class_id)]
    pred_scores=pred_scores[np.where(pred_class_ids==class_id)]
    pred_masks=pred_masks[:,:,pred_class_ids==class_id]
    pred_class_ids=np.delete(pred_class_ids,np.where(pred_class_ids!=class_id))
    gt_class_ids=np.delete(gt_class_ids,np.where(gt_class_ids!=class_id))#ate aqui
    gt_boxes = trim_zeros(gt_boxes)
    gt_masks = gt_masks[..., :gt_boxes.shape[0]]
    pred_boxes = trim_zeros(pred_boxes)
    indices = np.argsort(pred_scores)[::-1]
    overlaps = compute_overlaps_masks(pred_masks, gt_masks)
    match_count = 0
    pred_match = -1 * np.ones([pred_boxes.shape[0]])
    gt_match = -1 * np.ones([gt_boxes.shape[0]])
    for i in range(len(pred_boxes)):
        sorted_ixs = np.argsort(overlaps[i])[::-1]
        low_score_idx = np.where(overlaps[i, sorted_ixs] < score_threshold)[0]
        if low_score_idx.size > 0:
            sorted_ixs = sorted_ixs[:low_score_idx[0]]
        for j in sorted_ixs:
            if gt_match[j] > -1:
                continue
            iou = overlaps[i, j]
            if iou < iou_threshold:
                break
            if pred_class_ids[i] == gt_class_ids[j]:
                match_count += 1
                gt_match[j] = i
                pred_match[i] = j
                break

    return gt_match, pred_match, overlaps

def compute_ap(gt_boxes, gt_class_ids, gt_masks,
               pred_boxes, pred_class_ids, pred_scores, pred_masks,class_id,
               iou_threshold=0.5):
    gt_match, pred_match, overlaps = compute_matches(
        gt_boxes, gt_class_ids, gt_masks,
        pred_boxes, pred_class_ids, pred_scores, pred_masks,class_id,
        iou_threshold)
    precisions = np.cumsum(pred_match > -1) / (np.arange(len(pred_match)) + 1)
    recalls = np.cumsum(pred_match > -1).astype(np.float32) / len(gt_match)

    precisions = np.concatenate([[0], precisions, [0]])
    recalls = np.concatenate([[0], recalls, [1]])

    for i in range(len(precisions) - 2, -1, -1):
        precisions[i] = np.maximum(precisions[i], precisions[i + 1])

    indices = np.where(recalls[:-1] != recalls[1:])[0] + 1
    mAP = np.sum((recalls[indices] - recalls[indices - 1]) *
                 precisions[indices])

    return mAP, precisions, recalls, overlaps

To use it I did it as follows:

def compute_ap_per_class(name_class, dataset, model, cfg):
  for image_id in dataset.image_ids:
    image, image_meta, gt_class_id, gt_bbox, gt_mask = load_image_gt(dataset, cfg, image_id, use_mini_mask=False)
    scaled_image = mold_image(image, cfg)
    sample = expand_dims(scaled_image, 0)
    yhat = model.detect(sample, verbose=0)
    r = yhat[0]
    AP, _, _, _ = compute_ap(gt_bbox, gt_class_id, gt_mask, r["rois"], r["class_ids"], r["scores"], r['masks'], name_class)
    APs.append(AP)
  mAP = mean(APs)
  return mAP

def evaluate_model(dataset, model, cfg):
    mAP_apple = compute_ap_per_class(train_set.class_names[1], dataset, model, cfg)
    mAP_apple_damaged = compute_ap_per_class(train_set.class_names[2], dataset, model, cfg)
    print('mAP da classe apple ', mAP_apple)
    print('mAP da classe apple damaged ', mAP_apple_damaged) 
    mAP = (mAP_apple + mAP_apple_damaged) / 2
    return mAP

However I am getting the following error, on the line :


-->sorted_ixs = np.argsort(overlaps[i])[::-1]
TypeError: '<' not supported between instances of 'numpy.ndarray' and 'str'

Could someone please help me with this? I would be very, very grateful, this is an important job for my academic life, and unfortunately I can't understand where I'm going wrong. Thank you in advance for your attention.

burhr2 commented 4 years ago

Hi! did you manage to find the solution?