# Calculate True Positive, False Positive, True Negative and False negative and colourize output

Objective : Calculate True Positive, False Positive, True Negative and False negative and colourize the image accordignly, based on ground-truth and prediction from my classifier model.

Problem : Very Slow

Description:

The prediction is a gray-level image that comes from my classifier.

The truth_image is also a gray-level image, but its the correct image that prediction should try to approximate.

The mask_image segmentates the ROI ( region of interest), when its pixel value is 1, means its inside the region of interest, if its 0, then we should ignore and move on to the next pixel.

The output is the array where I want to keep the colourized image.

def coloured_prediction_truth(prediction, truth_image, mask_image,output_image):
prediction = prediction.astype(np.uint8)
truth_image = truth_image.astype(np.uint8)
#output_image = np.empty(shape=(submission_image.shape[0], submission_image.shape[1], 4), dtype=np.uint8)

#binarize values , values > 127 becomes 1. Else -> 0
for i in xrange(0, prediction.shape[0]):
for j in xrange(0, prediction.shape[1]):
if prediction[i, j] > 127:
prediction[i, j] = 1
else:
prediction[i, j] = 0

for i in xrange(0, truth_image.shape[0]):
for j in xrange(0, truth_image.shape[1]):
if truth_image[i, j] > 127:
truth_image[i, j] = 1
else:
truth_image[i, j] = 0

else:

# B-G-R-A
blue = [255, 0, 0, 255]
green = [0, 255, 0, 255]
red = [0, 0, 255, 255]
orange = [0, 128, 255, 255]
black = [0, 0, 0, 255]

TruePositive = 0.00
TrueNegative = 0.00
FalsePositive = 0.00
FalseNegative = 0.00

#Count pixel by pixel
for i in xrange(0, output_image.shape[0]):
for j in xrange(0, output_image.shape[1]):

pred = prediction[i, j]
truth = truth_image[i, j]

if pred == 1 and truth == 1:
output_image[i, j] = blue
TruePositive = TruePositive + 1
else:
if pred == 0 and truth == 0:
output_image[i, j] = green
TrueNegative = TrueNegative + 1
else:
if pred == 0 and truth == 1:
output_image[i, j] = red
FalseNegative = FalseNegative + 1
else:
if pred == 1 and truth == 0:
output_image[i, j] = orange
FalsePositive = FalsePositive + 1
else:
output_image[i, j] = black
else:
output_image[i, j] = black

accuracy = float((TruePositive + TrueNegative)) / float((TruePositive + FalsePositive + FalseNegative + TrueNegative))
sensitivity = float((TruePositive)) / float((TruePositive + FalseNegative))
specificity = float((TrueNegative)) / float((TrueNegative + FalsePositive))
try:
positivePredictiveValue = float((TruePositive)) / float((TruePositive + FalsePositive))
except Exception:
positivePredictiveValue = 0

return output_image, TruePositive, TrueNegative, FalsePositive, FalseNegative, accuracy, sensitivity, specificity, positivePredictiveValue


Example :

From these 3 images, the coloured image, would be:

For instance, you can create a true positives mask like this:

true_positive_mask = np.logical_and(prediction > 127, truth_image > 127)

After that, you can use this mask to index the output image:

output_image[true_positive_mask] = green # or whatever color you want

and to compute the total number of true positives:

true_positives = np.sum(true_positive_mask)

You can use the same idea to compute other values or for input binarization.

• Is this faster? – KenobiShan Oct 14 '17 at 17:04
• @KenobiShan Yes. – kraskevich Oct 14 '17 at 17:18
• Thank you so much! I made a little test and it saved me from 6sec for 1 image, to 0.06 – KenobiShan Oct 14 '17 at 23:23

Thanks to @kraskevich, I came up with the following code, which Im posting here in case anyone needs it.

def coloured_prediction_truth_2(prediction, truth_image, submission_image, mask_image):
prediction = prediction.astype(np.uint8)
truth_image = truth_image.astype(np.uint8)

output_image = np.empty(shape=(submission_image.shape[0], submission_image.shape[1], 4), dtype=np.uint8)

true_positive_mask = np.logical_and(prediction > 127, truth_image > 127)

true_negative_mask = np.logical_and(prediction <= 127, truth_image <= 127)

false_negative_mask = np.logical_and(prediction <= 127, truth_image > 127)

false_positive_mask = np.logical_and(prediction > 127, truth_image <= 127)

# B-G-R-A
blue = [255, 0, 0, 255]
green = [0, 255, 0, 255]
red = [0, 0, 255, 255]
orange = [0, 128, 255, 255]
black = [0, 0, 0, 255]

output_image[background_mask] = black  # or whatever color you want
output_image[true_positive_mask] = blue  # or whatever color you want
output_image[true_negative_mask] = green  # or whatever color you want
output_image[false_positive_mask] = orange  # or whatever color you want
output_image[false_negative_mask] = red  # or whatever color you want


• You don't need a second logical_and for each mask if you apply the color of the background_mask after all other colors. You may also cache the values of truth_image > 127 and so on to avoid recomputing them, and use np.logical_not over this value instead of recomputing truth_image <= 127. – Mathias Ettinger Jul 19 '18 at 14:05