So the idea is to write a precision and recall metric for segmentation task. The usual metrics for segmentation tasks calculate this metric by comparing the ground truth and prediction masks pixelwise. The way I want to calculate is that even if some part of the object in ground truth is predicted, then the whole object os considered as true positive.
The way I am currently approaching the problem is I am calculating logical and of the ground truth and predicted masks. Then using skimage.measure.label to assign a unique id to each blob. Then I calculate True Positives, False Negatives etc. by using the number of blobs in both
and_mask = np.logical_and(gt, pred)
labels1 = measure.label(gt, neighbors=8, background=0)
labels2 = measure.label(and_mask, neighbors=8, background=0)
This works for most cases but in the case where my predicted mask for a blob is predicted in two parts, then performing logical_and on it gives me an extra object. This screws up my calculation of metrics.
Is there a way to prevent this and also, is there a simpler way of doing this?
I managed to solve it. I used measure.label to get the individual masks and then computed the iou with the gt masks. That's what I wanted to
labels1 = measure.label(gt, neighbors=8, background=0)
# loop over the unique components
for label in np.unique(labels1):
# if this is the background label, ignore it
if label == 0:
continue
# otherwise, construct the label mask
labelMask1 = np.zeros(pred.shape, dtype="uint8")
labelMask1[labels1 == label] = 255
c, counts1 = np.unique(np.logical_and(labelMask1, pred,
where=255), return_counts=True)
inter = np.sum(np.logical_and(labelMask1, pred, where=255)) /
np.sum(np.logical_or(labelMask1, pred, where=255))
Here's the rough algorithm if anyone's interested.