11

I have an image of land cover and I segmented it using K-means clustering. Now I want to calculate the accuracy of my segmentation algorithm. I read somewhere that dice co-efficient is the substantive evaluation measure. But I am not sure how to calculate it. I use Python 2.7 Are there any other effective evaluation methods? Please give a summary or a link to a source. Thank You!

Edits: I used the following code for measuring the dice similarity for my original and the segmented image but it seems to take hours to calculate:

for i in xrange(0,7672320):
  for j in xrange(0,3):
    dice = np.sum([seg==gt])*2.0/(np.sum(seg)+np.sum(gt)) #seg is the segmented image and gt is the original image. Both are of same size
RachJain
  • 283
  • 1
  • 5
  • 14

4 Answers4

17

Please refer to Dice similarity coefficient at wiki

A sample code segment here for your reference. Please note that you need to replace k with your desired cluster since you are using k-means.

import numpy as np

k=1

# segmentation
seg = np.zeros((100,100), dtype='int')
seg[30:70, 30:70] = k

# ground truth
gt = np.zeros((100,100), dtype='int')
gt[30:70, 40:80] = k

dice = np.sum(seg[gt==k])*2.0 / (np.sum(seg) + np.sum(gt))

print 'Dice similarity score is {}'.format(dice)
pyan
  • 3,577
  • 4
  • 23
  • 36
  • thank you! your answer helped me get started. Now I tried to use this method for calculating the accuracy of my segmentation. The size of the image is large so iterating over all the rows and columns take a lot of time. Apparently my code took more than an hour to calculate dice coefficient. It would be great if you could help me here. – RachJain Jul 08 '15 at 10:32
  • How big is your image? Can you post your code of how you iterating over all rows and columns? – pyan Jul 08 '15 at 15:16
  • It is 1776*4320*3 RGB image. I rescaled it to size 7672320*3 – RachJain Jul 08 '15 at 16:15
  • It is not big at all. Don't try to iterate through all the pixels. Try to use the selection method shown in my code. That will be much faster than iteration. – pyan Jul 08 '15 at 18:07
  • How do I use selection method when I want to calculate it for whole of my image? Could you please elaborate. – RachJain Jul 09 '15 at 11:44
  • Can you post the code segment that you are currently using? – pyan Jul 10 '15 at 13:47
3

If you are working with opencv you could use the following function:

import cv2
import numpy as np

#load images
y_pred = cv2.imread('predictions/image_001.png')
y_true = cv2.imread('ground_truth/image_001.png') 

# Dice similarity function
def dice(pred, true, k = 1):
    intersection = np.sum(pred[true==k]) * 2.0
    dice = intersection / (np.sum(pred) + np.sum(true))
    return dice

dice_score = dice(y_pred, y_true, k = 255) #255 in my case, can be 1 
print ("Dice Similarity: {}".format(dice_score))

In case you want to evaluate with this metric within a deep learning model using tensorflow you can use the following:

def dice_coef(y_true, y_pred):
    y_true_f = tf.reshape(tf.dtypes.cast(y_true, tf.float32), [-1])
    y_pred_f = tf.reshape(tf.dtypes.cast(y_pred, tf.float32), [-1])
    intersection = tf.reduce_sum(y_true_f * y_pred_f)
    return (2. * intersection + 1.) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + 1.)
2

This is an important clarification if what you're using has more than 2 classes (aka, a mask with 1 and 0).

If you are using multiple classes, make sure to specify that the prediction and ground truth also equal the value which you want. Otherwise you can end up getting DSC values greater than 1.

This is the extra ==k at the end of each [] statement:

import numpy as np

k=1

# segmentation
seg = np.zeros((100,100), dtype='int')
seg[30:70, 30:70] = k

# ground truth
gt = np.zeros((100,100), dtype='int')
gt[30:70, 40:80] = k

dice = np.sum(seg[gt==k]==k)*2.0 / (np.sum(seg[seg==k]==k) + np.sum(gt[gt==k]==k))

print 'Dice similarity score is {}'.format(dice)
0

Here are 3 alternatives for getting the Dice coefficient in Python using raw Numpy, Scipy, and Scikit-Image. Hopefully comparing these can provide some illumination on how the Dice coefficient works and how it is related to other methods...

(1) Using only numpy:

import numpy as np

def dice_coefficient(y_true, y_pred):
    intersection = np.sum(y_true * y_pred)
    return (2. * intersection) / (np.sum(y_true) + np.sum(y_pred))

(2) Using scipy:

Scipy doesn't provide a direct method for Dice similarity coefficient, but you can make use of its spatial distance module to implement it.

from scipy.spatial import distance

def dice_coefficient(y_true, y_pred):
    return 1 - distance.dice(y_true.flatten(), y_pred.flatten())

(3) Using skimage:

Skimage also does not have a direct method for Dice similarity, but it has a method for Jaccard similarity which is related. The Dice coefficient can be calculated from the Jaccard index as follows: Dice = 2 * Jaccard / (1 + Jaccard)

from skimage.metrics import jaccard_score

def dice_coefficient(y_true, y_pred):
    jaccard = jaccard_score(y_true.flatten(), y_pred.flatten())
    return 2*jaccard / (1 + jaccard)
DankMasterDan
  • 1,900
  • 4
  • 23
  • 35