Exemple #1
0
def IoU_per_score(gt_mask, gt_class_id, pred_mask):
    IoU_general = []
    IoU_names = ["IoU", "IoU_ring", "IoU_crack", "IoU_resin", "IoU_pith"]
    # if no mask is detected
    if pred_mask.shape[-1] == 0:
        IoU_general = [0]*5
    else:
        IoU= utils.compute_overlaps_masks(gt_mask, pred_mask)
        IoU = np.nan_to_num(np.mean(IoU)) #change nans to 0
        IoU_general = [IoU]
        for i in range(1,5):
            IoU= utils.compute_overlaps_masks(gt_mask[:,:,gt_class_id==i], pred_mask[:,:,pred_class_id==i])
            IoU = np.nan_to_num(np.mean(IoU)) #change nans to 0
            IoU_general.append(IoU)

    return IoU_general, IoU_names
Exemple #2
0
def compute_mean_iou_per_image(num_classes, pred_masks, gt_masks,
                               matched_classes):
    '''
    This function computes the average IoU per image.
    each image can contain different amount and kind of mask's classes,
    the average is taken among each class separately.
    :param num_classes: ndarray (1,num_images): how many classes exist in each image? (background doesn't count)
    :param pred_masks: the image's predicted masks
    :param gt_masks: the image's ground truth masks
    :param matched_classes: ndarray it's indices has correspondence between the prediction to the GT.
    :return IoU_per_class: mean IoU over all instances from the same class. ndarray with shape[num_classes + 1, 1]
    :return class_exist: ndarray with shape[num_classes + 1, 1], which contain 1 at indces where the class has at least
                        one instance in the image
    '''
    # IoU: mat. IoU score of each possible pair of masks gt Vs preds
    IoU = utils.compute_overlaps_masks(pred_masks, gt_masks)
    diag_indices = np.arange(IoU.shape[0])  # ndarray. IoU of matched masks
    IoU_diag = IoU[diag_indices, diag_indices]
    IoU_per_class = np.zeros((num_classes + 1, 1))
    cnt_classes = np.zeros((num_classes + 1, 1))
    for i in np.arange(IoU_diag.shape[0]):
        IoU_per_class[matched_classes[i]] += IoU_diag[i]
        cnt_classes[matched_classes[i]] += 1
    select_nonzero = cnt_classes != 0
    IoU_per_class[select_nonzero] = IoU_per_class[
        select_nonzero] / cnt_classes[select_nonzero]
    class_exist = cnt_classes > 0
    return IoU_per_class, class_exist.astype(np.uint8)
Exemple #3
0
def TP_FP_FN_per_score_mask(gt_mask, pred_mask, scores, IoU_treshold):

    #loop scores
    score_range = np.arange(0.5, 1.0, 0.05)

    #print(gt_r)
    #print(pred_r)
    gt_rings = []
    pred_rings = []
    TPs = []
    FPs = []
    FNs = []

    for SR in score_range:
        #print(SR)
        score_ids = np.where(
            scores > SR)[0]  #Ids for predictions above certain score threshold
        #print(score_ids)
        mask_SR = np.take(pred_mask, score_ids, axis=2)
        #print('mask_SR.shape:', mask_SR.shape)

        mask_matrix = utils.compute_overlaps_masks(gt_mask, mask_SR)
        #print("mask_matrix", mask_matrix)
        #for every score range callculate TP, ...append by the socre ranges
        # making binary numpy array with IoU treshold
        mask_matrix_binary = np.where(mask_matrix > IoU_treshold, 1, 0)
        #print (mask_matrix_binary)

        #GT rings and predicted rigs
        #print(mask_matrix.shape)
        if mask_matrix.shape[0] == 0:
            TPs.append(0)
            FPs.append(0)
            FNs.append(0)
        else:
            gt_r = len(mask_matrix)
            pred_r = len(mask_matrix[0])

            #TP
            sum_truth = np.sum(mask_matrix_binary, axis=1)
            sum_truth_binary = np.where(sum_truth > 0, 1, 0)
            TP = np.sum(sum_truth_binary)
            TPs.append(TP)
            #print('TPs:', TPs)
            #FP
            sum_pred = np.sum(mask_matrix_binary, axis=0)
            sum_pred_binary = np.where(sum_pred > 0, 1, 0)
            FP = pred_r - np.sum(sum_pred_binary)
            FPs.append(FP)
            #print('FP:', FP)
            #FN
            FN = gt_r - TP
            FNs.append(FN)
        #print('FN:', FN)
    #put together and sum up TP...per range

    return TPs, FPs, FNs, score_range
Exemple #4
0
        gt_mask_flat = gt_mask_flat + gt_mask[:,:,m]


    #print('combined_mask_shape:', combined_mask_binary.shape)
    gt_mask_flat_binary = np.where(gt_mask_flat > 0, 1, 0)
    #print(gt_mask_flat_binary.shape)
    gt_mask_flat_binary = np.reshape(gt_mask_flat_binary, (1024,1024,1))
    print('gt_mask_shape:', gt_mask_flat_binary.shape)
    #### THIS SHOULD BE DONE ON INDIVIDUAL MASKS AND NOT ON FLATENED
    IoU_combined_mask.append(utils.compute_overlaps_masks(gt_mask_flat_binary, combined_mask_binary_wrong))

    #IoU_combined_mask = np.mean(IoU_combined_mask)
    #print('IoU_combined:', IoU_combined_mask)
    """

    mask_matrix = utils.compute_overlaps_masks(gt_mask, combined_mask_binary)
    print("mask_matrix.shape", mask_matrix.shape)
    print("mask_matrix", mask_matrix)
    # making binary numpy array with IoU treshold
    ## HERE YOU CAN CALCULATE FOR ALL IoU
    IoU_treshold = 0.5  # i set it less because combined mask is bigger and it does not matter i think
    mask_matrix_binary = np.where(mask_matrix > IoU_treshold, 1, 0)
    #print (mask_matrix_binary)

    #GT rings and predicted rigs
    gt_r = len(mask_matrix)
    pred_r = len(mask_matrix[0])

    #TP
    sum_truth = np.sum(mask_matrix_binary, axis=1)
    sum_truth_binary = np.where(sum_truth > 0, 1, 0)
def compute_matches(gt_boxes,
                    gt_class_ids,
                    gt_masks,
                    pred_boxes,
                    pred_class_ids,
                    pred_scores,
                    pred_masks,
                    iou_threshold=0.5,
                    score_threshold=0.0):
    """Finds matches between prediction and ground truth instances.

    Returns:
        gt_match: 1-D array. For each GT box it has the index of the matched
                  predicted box.
        pred_match: 1-D array. For each predicted box, it has the index of
                    the matched ground truth box.
        overlaps: [pred_boxes, gt_boxes] IoU overlaps.
    """
    # Trim zero padding
    # TODO: cleaner to do zero unpadding upstream
    gt_boxes = utils.trim_zeros(gt_boxes)
    gt_masks = gt_masks[..., :gt_boxes.shape[0]]
    pred_boxes = utils.trim_zeros(pred_boxes)
    pred_scores = pred_scores[:pred_boxes.shape[0]]
    # Sort predictions by score from high to low
    indices = np.argsort(pred_scores)[::-1]
    pred_boxes = pred_boxes[indices]
    pred_class_ids = pred_class_ids[indices]
    pred_scores = pred_scores[indices]
    pred_masks = pred_masks[..., indices]

    # Compute IoU overlaps [pred_masks, gt_masks]
    overlaps = utils.compute_overlaps_masks(pred_masks, gt_masks)
    masks1 = pred_masks
    masks2 = gt_masks
    masks1 = np.reshape(masks1 > .5, (-1, masks1.shape[-1])).astype(np.float32)
    masks2 = np.reshape(masks2 > .5, (-1, masks2.shape[-1])).astype(np.float32)
    area1 = np.sum(masks1, axis=0)
    area2 = np.sum(masks2, axis=0)

    # intersections and union
    intersections = np.dot(masks1.T, masks2)

    gt_class_area = np.zeros(3)
    for i, ids in enumerate(gt_class_ids):
        gt_class_area[ids] += area2[i]

    # Loop through predictions and find matching ground truth boxes
    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)):
        # Find best matching ground truth box
        # 1. Sort matches by score
        sorted_ixs = np.argsort(overlaps[i])[::-1]
        # 2. Remove low scores
        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]]
        # 3. Find the match
        for j in sorted_ixs:
            # If ground truth box is already matched, go to next one
            if gt_match[j] > 0:
                continue
            # If we reach IoU smaller than the threshold, end the loop
            iou = overlaps[i, j]
            if iou < iou_threshold:
                break
            # Do we have a match?
            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, gt_class_area, area1, intersections
Exemple #6
0
def TP_FP_FN_IoU_per_score_mask(gt_mask, pred_mask, scores, IoU_threshold, score_range=None):

    #loop scores
    if score_range is None:
        score_range = np.arange(0.5, 1.0, 0.05)
        #print(gt_r)
        #print(pred_r)

    TPs = []
    FPs = []
    FNs = []
    IoUs = []
    #print("GT_MASK_SHAPE", gt_mask.shape)
    for SR in score_range:
        #print("SR",SR)
        #print("scores", scores)
        score_ids = np.where(scores > SR)[0] #Ids for predictions above certain score threshold
        #print("score_ids", score_ids)
        #print("pred_mask.shape", pred_mask.shape)
        mask_SR = np.take(pred_mask, score_ids, axis=2)
        #print('mask_SR.shape:', mask_SR.shape)

        mask_matrix = utils.compute_overlaps_masks(gt_mask, mask_SR)
        print("mask_matrix", mask_matrix)
        # calculate average IoU
        IoU_clean = mask_matrix[np.where(mask_matrix>0)]
        #print("IoU_clean", IoU_clean)
        IoU = np.nan_to_num(np.mean(IoU_clean))
        IoUs.append(IoU)
        #for every score range callculate TP, ...append by the socre ranges
        # making binary numpy array with IoU threshold
        mask_matrix_binary = np.where(mask_matrix > IoU_threshold, 1, 0)
        #print("mask_matrix_binary", mask_matrix_binary)

        #GT rings and predicted rigs
        #print("MASK MATRIX SHAPE", mask_matrix.shape)

        if mask_matrix.shape[0]==0:
            TPs.append(0)
            FPs.append(mask_SR.shape[-1]) # All predicted are false in this case
            FNs.append(0)
        else:
            gt_r = len(mask_matrix)
            pred_r = len(mask_matrix[0])
            #TP
            sum_truth = np.sum(mask_matrix_binary, axis=1)
            sum_truth_binary = np.where(sum_truth > 0, 1, 0)
            TP = np.sum(sum_truth_binary)
            TPs.append(TP)
            #print('TP:', TP)
            #FP
            sum_pred = np.sum(mask_matrix_binary, axis=0)
            sum_pred_binary = np.where(sum_pred > 0, 1, 0)
            FP = pred_r - np.sum(sum_pred_binary)
            FPs.append(FP)
            #print('FP:', FP)
            #FN
            FN = gt_r - TP
            FNs.append(FN)

        print('TPs:', TPs)
        print('FPs:', FPs)
        print('FNs:', FNs)
    #put together and sum up TP...per range

    return TPs, FPs, FNs, IoUs
Exemple #7
0
def TP_FP_FN_IoU_comb(gt_mask, pred_mask, IoU_thresholds=None):

    #loop scores
    if IoU_thresholds is None:
        IoU_thresholds = np.arange(0, 1.0, 0.05)
        #print(gt_r)
        #print(pred_r)

    TPs = []
    FPs = []
    FNs = []
    IoUs = []
    #print("GT_MASK_SHAPE", gt_mask.shape)
    for iou_threshold in IoU_thresholds:

        mask_matrix = utils.compute_overlaps_masks(gt_mask, pred_mask)
        print("combined_mask_matrix", mask_matrix)

        if iou_threshold == min(IoU_thresholds):
            # calculate average IoU
            IoU_clean = mask_matrix[np.where(mask_matrix>0)]
            #print("IoU_clean", IoU_clean)
            IoU = np.nan_to_num(np.mean(IoU_clean))
            IoUs.append(IoU)
        #for every score range callculate TP, ...append by the socre ranges
        # making binary numpy array with IoU threshold
        mask_matrix_binary = np.where(mask_matrix > iou_threshold, 1, 0)
        #print ("comb_mask_matrix_binary", mask_matrix_binary)

        #GT rings and predicted rigs
        #print("MASK MATRIX SHAPE", mask_matrix.shape)

        if mask_matrix.shape[0]==0:
            TPs.append(0)
            FPs.append(pred_mask.shape[-1]) # All predicted are false in this case
            FNs.append(0)
        else:
            gt_r = len(mask_matrix)
            pred_r = len(mask_matrix[0])
            #TP
            sum_truth = np.sum(mask_matrix_binary, axis=1)
            sum_truth_binary = np.where(sum_truth > 0, 1, 0)
            TP = np.sum(sum_truth_binary)
            TPs.append(TP)
            #print('TP:', TP)
            #FP
            sum_pred = np.sum(mask_matrix_binary, axis=0)
            sum_pred_binary = np.where(sum_pred > 0, 1, 0)
            FP = pred_r - np.sum(sum_pred_binary)
            FPs.append(FP)
            #print('FP:', FP)
            #FN
            FN = gt_r - TP
            FNs.append(FN)

        print('TPs:', TPs)
        print('FPs:', FPs)
        print('FNs:', FNs)
    #put together and sum up TP...per range

    return TPs, FPs, FNs, IoUs
Exemple #8
0
model.load_weights(custom_WEIGHTS_PATH, by_name=True)

from importlib import reload  # was constantly changin the visualization, so I decided to reload it instead of notebook
reload(visualize)

image_id = int(sys.argv[1])
image, image_meta, gt_class_id, gt_bbox, gt_mask =\
    modellib.load_image_gt(dataset, config, image_id, use_mini_mask=False)
info = dataset.image_info[image_id]
#print("image ID: {}.{} ({}) {}".format(info["source"], info["id"], image_id,
#                                       dataset.image_reference(image_id)))

# Run object detection
results = model.detect([image], verbose=1)

# Display results
ax = get_ax(1)
r = results[0]

visualize.display_differences
visualize.display_instances(image,
                            r['rois'],
                            r['masks'],
                            r['class_ids'],
                            dataset.class_names,
                            r['scores'],
                            ax=ax,
                            title="Predictions")
iou = utils.compute_overlaps_masks(gt_mask, r['masks'])
print("IOU:" + str(iou))
Exemple #9
0
    gt_mask = gt_mask[:, :, gt_class_id == 1]
    nmasks = gt_mask.shape[2]
    for m in range(0, nmasks):
        gt_mask_flat = gt_mask_flat + gt_mask[:, :, m]
    #calcumate IoU
    combined_mask_binary = np.where(combined_mask > 0, 1, 0)
    #print("combined_mask_binary",combined_mask_binary.shape)
    combined_mask_binary = np.reshape(combined_mask_binary, (1024, 1024, 1))

    #print('combined_mask_shape:', combined_mask_binary.shape)
    gt_mask_flat_binary = np.where(gt_mask_flat > 0, 1, 0)
    #print(gt_mask_flat_binary.shape)
    gt_mask_flat_binary = np.reshape(gt_mask_flat_binary, (1024, 1024, 1))
    print('gt_mask_shape:', gt_mask_flat_binary.shape)
    IoU_combined_mask.append(
        utils.compute_overlaps_masks(gt_mask_flat_binary,
                                     combined_mask_binary))

    #IoU_combined_mask = np.mean(IoU_combined_mask)
    #print('IoU_combined:', IoU_combined_mask)

    ####### Try to separate combined masks into layers
    separated_mask = modify_flat_mask(combined_mask)
    #print('separated_mask_shape', separated_mask.shape)

    #print(IoU_m)
    #plt.imshow(gt_mask[:,:,3])
    #plt.show()
    #plt.imshow(separated_mask[:,:,0])
    #plt.show()
    mask_matrix = utils.compute_overlaps_masks(gt_mask, separated_mask)
    #print("mask_matrix.shape", mask_matrix.shape)
        ###calculate all the stuff
        mask_normal = r['masks']  # for the combined mask at the end
        ap = utils.compute_ap_range(gt_bbox,
                                    gt_class_id,
                                    gt_mask,
                                    r['rois'],
                                    r['class_ids'],
                                    r['scores'],
                                    r['masks'],
                                    verbose=0)
        #print(r['scores'])
        #print(r['masks'].shape)
        mAP.append(ap)

        #compute mask IoU
        IoU_m = utils.compute_overlaps_masks(gt_mask, r['masks'])
        IoU_m = np.nan_to_num(np.mean(IoU_m))  #change nans to 0
        mask_IoU.append(IoU_m)

        #compute bbox IoU
        IoU_bbox = utils.compute_overlaps(gt_bbox, r['rois'])
        IoU_bbox = np.nan_to_num(np.mean(IoU_bbox))
        bbox_IoU.append(IoU_bbox)

        #compute TP, FP, FN for mask
        TP, FP, FN, score_range = TP_FP_NF_per_score_mask(gt_mask,
                                                          r['masks'],
                                                          r['scores'],
                                                          IoU_treshold=0.3)
        #print(TP)
        #print(FP)
Exemple #11
0
def display_instances(image,
                      boxes,
                      masks,
                      mask1,
                      class_ids,
                      class_names,
                      scores=None,
                      title="",
                      figsize=(16, 16),
                      ax=None):
    """
    boxes: [num_instance, (y1, x1, y2, x2, class_id)] in image coordinates.
    masks: [height, width, num_instances]
    class_ids: [num_instances]
    class_names: list of class names of the dataset
    scores: (optional) confidence scores for each box
    figsize: (optional) the size of the image.
    """
    # Number of instances
    N = boxes.shape[0]
    mask_iou_bf = []
    mask_iou_plaque = []
    if not N:
        print("\n*** No instances to display *** \n")
    else:
        assert boxes.shape[0] == masks.shape[-1] == class_ids.shape[0]

    if not ax:
        _, ax = plt.subplots(1, figsize=figsize)

    # Generate random colors
    colors = random_colors(N)

    # Show area outside image boundaries.
    height, width = image.shape[:2]
    ax.set_ylim(height + 10, -10)
    ax.set_xlim(-10, width + 10)
    ax.axis('off')
    ax.set_title(title)

    masked_image = image.astype(np.uint32).copy()
    for i in range(N):
        color = colors[i]

        # Bounding box
        if not np.any(boxes[i]):
            # Skip this instance. Has no bbox. Likely lost in image cropping.
            continue
        y1, x1, y2, x2 = boxes[i]
        p = patches.Rectangle((x1, y1),
                              x2 - x1,
                              y2 - y1,
                              linewidth=2,
                              alpha=0.7,
                              linestyle="-",
                              edgecolor=color,
                              facecolor='none')
        ax.add_patch(p)

        # Label
        class_id = class_ids[i]
        score = scores[i] if scores is not None else None
        label = class_names[class_id]
        x = random.randint(x1, (x1 + x2) // 2)
        caption = "{} {:.3f}".format(label, score) if score else label
        ax.text(x1,
                y1 - 10,
                caption,
                color=color,
                size=11,
                backgroundcolor="none")

        # Mask
        iou_acc = compute_overlaps_masks(masks, mask1)
        ax.text(x1 - 7, y1 - 86 + (38 * i),
                "mask_iou for {} :{}".format(label, max(np.array(iou_acc[i]))))
        if label == 'leaf':
            mask_iou_bf.append(max(np.array(iou_acc[i])))
        elif label == 'root':
            mask_iou_plaque.append(max(np.array(iou_acc[i])))
        mask = masks[:, :, i]
        #mask1 = mask1[:,:,i]
        masked_image = apply_mask(masked_image, mask, color)
        #masks_img = apply_mask(masking_image,mask1,color)
        # Mask Polygon
        # Pad to ensure proper polygons for masks that touch image edges.
        padded_mask = np.zeros((mask.shape[0] + 2, mask.shape[1] + 2),
                               dtype=np.uint8)
        #padding_mask = np.zeros((mask1.shape[0]+2,mask1.shape[1]+2),dtype=np.uint8)
        padded_mask[1:-1, 1:-1] = mask
        #padding_mask[1:-1,1:-1] = mask1
        contours = find_contours(padded_mask, 0.5)
        #contouring = find_contours(padding_mask,0.5)
        for verts in contours:
            # Subtract the padding and flip (y, x) to (x, y)
            verts = np.fliplr(verts) - 1
            p = Polygon(verts, facecolor="none", edgecolor=color)
            ax.add_patch(p)
            #parr = np.array(parr)
            '''ax.text(x1, y1-2, "Area:{}".format(math.ceil(area(verts))),
                    color='w', size=11, backgroundcolor="none")'''
    #ax.text(x1-7, y1-56,"mask_iou:{}".format(compute_overlaps_masks(masks, mask1), color='w', size=11, backgroundcolor='none'))
    #print(np.array(verts).shape)
    ax.imshow(masked_image.astype(np.uint8))
    plt.show()
    return [np.mean(np.array(mask_iou_bf)), np.mean(np.array(mask_iou_plaque))]