def eval(): print('\nEval') net.eval() global dice_score global ite global count global num_sym target_boxes = testset.boxes # print('target_boxes',target_boxes) target_img = create_binaryImage(target_boxes, False) # for i in range(2): # img = Image.fromarray(target_img[i]) # img.show() # pdb.set_trace() for batch_idx, (images, loc_targets, conf_targets) in enumerate(testloader): if use_cuda: images = images.cuda() loc_targets = loc_targets.cuda() conf_targets = conf_targets.cuda() images = Variable(images, volatile=True) # loc_targets = Variable(loc_targets) # conf_targets = Variable(conf_targets) loc_preds, conf_preds = net(images) data_encoder = DataEncoder() # pdb.set_trace() conf_preds_list = [] for i in range(batch_size): s_conf = F.softmax(conf_preds[i]).data conf_preds_list.append(s_conf) # pdb.set_trace() try: boxes, labels, scores = data_encoder.decodeforbatch( loc_preds.data, conf_preds_list) # print('eloc', loc_preds.data) # print('esoftmax', conf_preds_list) predicted_img = create_binaryImage(boxes) for i in range(batch_size): dice_score += binary.dc(predicted_img[i], target_img[batch_idx * batch_size + i]) ite += 1 print('[I %d]: %.5f' % (ite, binary.dc(predicted_img[i], target_img[batch_idx * batch_size + i]))) # print(binary.dc(predicted_img[i],target_img[batch_idx + i])) # img = Image.fromarray(target_img[batch_idx + i]) # img.show('target') # imgg = Image.fromarray(predicted_img[batch_idx + i]) # imgg.show('predict') except: print('err')
def do(argv): segResults_path = argv[0] references_path = argv[1] num_classes = argv[2] results = listdir(segResults_path) results.sort(key=lambda f: int(filter(str.isdigit, f))) references = listdir(references_path) references.sort(key=lambda f: int(filter(str.isdigit, f))) pack = zip(results, references) res = 1 for resultname, referencename in pack: result = nib.load(join(segResults_path, resultname)).get_data() print('result name: ', resultname) print('reference name: ', referencename) reference = nib.load(join(references_path, referencename)).get_data() reference = reference.reshape(result.shape) print("ASSD: ", mmb.assd(result, reference, voxelspacing=res)) Assd_array = [] Dice_array = [] print(num_classes) for res_c, ref_c in zip( range(num_classes), range(num_classes) ): #or some specific class labels, e.g., zip([2,3,4], [2,3,4]) dc = mmb.dc(result == res_c, reference == ref_c) assd = mmb.assd(result == res_c, reference == ref_c, voxelspacing=res) Assd_array.append(assd) Dice_array.append(dc) for i in xrange(0, len(Dice_array)): print('Dice score of class_{}'.format(i + 1), Dice_array[i]) for i in xrange(0, len(Assd_array)): print('ASSD score of class_{}'.format(i + 1), Assd_array[i]) #print("obj_assd: ",obj_assd(result,reference)) #print("ASD: ", asd(result,reference)) #print("ASD: ", asd(reference,result)) #print("HD: ", hd(result,reference)) print("Dice: ", mmb.dc(result, reference))
def get_outputs(seg, seg_truth): print seg.shape, seg_truth.shape seg_thresh = utility.threshold(seg,THRESHOLD) print seg_thresh.shape contour = utility.listSegToContours(seg_thresh, meta_test[1,:], meta_test[0,:], ISOVALUE) errs = utility.listAreaOverlapError(contour, contours_test) thresh,ts = utility.cum_error_dist(errs,DX) roc = roc_curve(np.ravel(seg_truth),np.ravel(seg), pos_label=1) pr = precision_recall_curve(np.ravel(seg_truth),np.ravel(seg), pos_label=1) dorf = [] emd = [] asdl = [] dice = [] prec = [] for i in range(len(seg_truth)): if np.sum(seg_thresh[i,:,:]) > 0.1 and np.sum(seg_truth[i,:,:,0]) > 0.1: e= hd(seg_thresh[i,:,:],seg_truth[i,:,:,0],meta_test[0,i][0]) dorf.append(e) e_asd= assd(seg_thresh[i,:,:],seg_truth[i,:,:,0],meta_test[0,i][0]) asdl.append(e_asd) # if np.sum(seg_thresh[i,:,:]) < 600 and np.sum(seg_truth[i,:,:,0]) < 600: # print i,np.sum(seg_thresh[i,:,:]),np.sum(seg_truth[i,:,:,0]) # e_emd = utility.EMDSeg(seg_truth[i,:,:,0],seg_thresh[i,:,:], meta_test[0,i][0]) # emd.append(e_emd) edc = dc(seg_thresh[i,:,:],seg_truth[i,:,:,0]) dice.append(edc) prec.append(precision(seg_thresh[i,:,:],seg_truth[i,:,:,0])) acc,mean_acc = calc_accuracy(seg, seg_truth) return (contour,errs,thresh,roc,pr,acc,mean_acc,dorf,dice, prec,asdl)
def update_eval_metrics(preds, labels, eval_metrics): if len(labels.shape) == 2: preds = np.expand_dims(preds, axis=0) labels = np.expand_dims(labels, axis=0) N = labels.shape[0] for i in range(N): pred = preds[i, :, :] label = labels[i, :, :] eval_metrics['dice score'].append(dc(pred, label)) eval_metrics['precision'].append(precision(pred, label)) eval_metrics['recall'].append(recall(pred, label)) eval_metrics['sensitivity'].append(sensitivity(pred, label)) eval_metrics['specificity'].append(specificity(pred, label)) if np.sum(pred) > 0 and np.sum(label) > 0: eval_metrics['hausdorff'].append(hd(pred, label)) eval_metrics['hausdorff 95%'].append(hd95(pred, label)) eval_metrics['asd'].append(asd(pred, label)) eval_metrics['assd'].append(assd(pred, label)) eval_metrics['jaccard'].append(jc(pred, label)) else: eval_metrics['hausdorff'].append('nan') eval_metrics['hausdorff 95%'].append('nan') eval_metrics['asd'].append('nan') eval_metrics['assd'].append('nan') eval_metrics['jaccard'].append('nan') return eval_metrics
def metrics2(img_gt, img_pred, apply_hd=False, apply_asd=False): """ evaluate the models on mmwhs data in batches :param img_gt: the ground truth :param img_pred: the prediction :param apply_hd: whether to evaluate Hausdorff Distance :param apply_asd: whether to evaluate Average Surface Distance :return: """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res = {} class_name = ["myo", "la", "lv", "aa"] # Loop on each classes of the input images for c, cls_name in zip([1, 2, 3, 4], class_name) : gt_c_i = np.where(img_gt == c, 1, 0) pred_c_i = np.where(img_pred == c, 1, 0) # Compute the Dice dice = dc(gt_c_i, pred_c_i) h_d, a_sd = 0, 0 if apply_hd: h_d = hd(gt_c_i, pred_c_i) if apply_asd: a_sd = asd (gt_c_i, pred_c_i) res[cls_name] = [dice, h_d, a_sd] return res
def metrics(img_gt, img_pred, ifhd=True, ifasd=True): from medpy.metric.binary import hd, dc, asd if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format( img_gt.ndim, img_pred.ndim)) res = [] cat = {'Myo', 'LA-blood', 'LV-blood', 'AA'} for c in range(len(cat)): # Copy the gt image to not alterate the input gt_c_i = np.where(img_gt == c + 1, 1, 0) # Copy the pred image to not alterate the input pred_c_i = np.where(img_pred == c + 1, 1, 0) # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) try: h_d = hd(gt_c_i, pred_c_i) if ifhd else -1 except: h_d = -1 try: a_sd = asd(gt_c_i, pred_c_i) if ifasd else -1 except: a_sd = -1 res += [dice, h_d, a_sd] return res
def metrics(self, img_gt, img_pred, voxel_size): if img_gt.ndim != img_pred.ndim: raise ValueError( "The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res = [] # Loop on each classes of the input images for c in [3, 1, 2]: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) # Compute volume volpred = pred_c_i.sum() * np.prod(voxel_size) / 1000. volgt = gt_c_i.sum() * np.prod(voxel_size) / 1000. res += [dice, volpred, volpred - volgt] return res
def get_results(prediction, reference): results = {} for c, key in enumerate(["", "RV_", "MYO_", "LV_"]): ref = np.copy(reference) pred = np.copy(prediction) ref = ref if c == 0 else np.where(ref != c, 0, ref) pred = pred if c == 0 else np.where(np.rint(pred) != c, 0, pred) results[key + "SED"] = np.sum((ref - pred)**2) results[key + "SED_rint"] = np.sum((ref - np.rint(pred))**2) results[key + "maxSED"] = np.sum( ((ref - pred)**2).reshape(ref.shape[0], -1), axis=1).max() results[key + "maxSED_rint"] = np.sum( ((ref - np.rint(pred))**2).reshape(ref.shape[0], -1), axis=1).max() results[key + "Dice"] = 2 * np.sum(pred * np.where(ref != 0, 1, 0)) / np.sum( pred + np.where(ref != 0, 1, 0)) if np.sum( pred + np.where(ref != 0, 1, 0)) != 0 else 0 results[key + "Dice_rint"] = binary.dc( np.where(ref != 0, 1, 0), np.where(np.rint(pred) != 0, 1, 0)) try: results[key + "HD_rint"] = binary.hd( np.where(ref != 0, 1, 0), np.where(np.rint(pred) != 0, 1, 0)) except Exception: results[key + "HD_rint"] = np.nan return results
def eval_seg_metric(pred, gt): dice = metric.dc(pred, gt) #hd = metric.hd(pred,gt) #assd = metric.assd(pred,gt) sens = metric.recall(pred, gt) return dice, sens
def CalDice(SegRes, Ref, seg_labels, ref_labels): Dice_array = [] for res_c, ref_c in zip(seg_labels, ref_labels): dc = mmb.dc(SegRes == res_c, Ref == ref_c) Dice_array.append(dc) return Dice_array
def dice(result, reference): d = 0 res = np.squeeze(result) ref = np.squeeze(reference) for layer in range(1, 3): d += dc(res == layer, ref == layer) return d / 3
def metrics_slice(img_gt, img_pred, voxel_size): """ Function to compute the metrics between two segmentation maps given as input. Parameters ---------- img_gt: np.array Array of the ground truth segmentation map. img_pred: np.array Array of the predicted segmentation map. voxel_size: list, tuple or np.array The size of a voxel of the images used to compute the volumes. Return ------ A list of metrics in this order, [Dice LV, Volume LV, Err LV(ml), Dice RV, Volume RV, Err RV(ml), Dice MYO, Volume MYO, Err MYO(ml)] """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res_zs = [] for zz in range(img_gt.shape[2]): res_z = [] # Loop on each classes of the input images for c in [3, 1, 2]: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt[..., zz]) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred[..., zz]) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Modified dice accuracy xent = mod_dc(gt_c_i, pred_c_i) # Compute the Dice dice = dc(gt_c_i, pred_c_i) # Compute volume volpred = pred_c_i.sum() * np.prod(voxel_size) / 1000. volgt = gt_c_i.sum() * np.prod(voxel_size) / 1000. res_z += [dice, xent, volpred, volpred - volgt] res_zs += [res_z] return metrics(img_gt, img_pred, voxel_size), res_zs
def do(argv): segResults_path = argv[0] references_path = argv[1] num_classes = argv[2] results = listdir(segResults_path) results.sort(key=lambda f: int(filter(str.isdigit, f))) references = listdir(references_path) references.sort(key=lambda f: int(filter(str.isdigit, f))) res = 1 # image-specific variable for resultname, referencename in zip(results,references): result = nib.load(join(segResults_path,resultname)).get_data() reference = nib.load(join(references_path,referencename)).get_data() # Please adjust this for your own data reference = numpy.expand_dims(reference,axis=3) reference = numpy.expand_dims(reference,axis=4) print("ASSD: ", mmb.assd(result,reference,voxelspacing=res)) Assd_array = [] Dice_array = [] print(num_classes) for c_i in xrange(0,int(num_classes)): dc = mmb.dc(result == c_i, reference == c_i) assd = mmb.assd(result == c_i, reference == c_i,voxelspacing=res) Assd_array.append(assd) Dice_array.append(dc) for i in xrange(0, len(Dice_array)): print('Dice score of class_{}'.format(i), Dice_array[i]) for i in xrange(0,len(Assd_array)): print('ASSD score of class_{}'.format(i), Assd_array[i]) #print("obj_assd: ",obj_assd(result,reference)) #print("ASD: ", asd(result,reference)) #print("ASD: ", asd(reference,result)) #print("HD: ", hd(result,reference)) print("Dice: ", mmb.dc(result,reference))
def metrics(img_gt, img_pred, voxel_size): """ Function to compute the metrics between two segmentation maps given as input. Parameters ---------- img_gt: np.array Array of the ground truth segmentation map. img_pred: np.array Array of the predicted segmentation map. voxel_size: list, tuple or np.array The size of a voxel of the images used to compute the volumes. Return ------ A list of metrics in this order, [Dice LV, Volume LV, Err LV(ml), Dice RV, Volume RV, Err RV(ml), Dice MYO, Volume MYO, Err MYO(ml)] """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format( img_gt.ndim, img_pred.ndim)) res = [] # Loop on each classes of the input images for c in [3, 1, 2]: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) try: hausdorff = hd(pred_c_i, gt_c_i) except Exception as e: hausdorff = np.NaN #hausdorff = img_gt.shape[0]/4 # mark this hausdorff as a really huge error print(str(e)) # Compute volume volpred = pred_c_i.sum() * np.prod(voxel_size) / 1000. volgt = gt_c_i.sum() * np.prod(voxel_size) / 1000. res += [dice, volpred, volpred - volgt, hausdorff] return res
def metrics(img_gt, img_pred, voxel_size): global VOXEL_SPACING """ Function to compute the metrics between two segmentation maps given as input. Parameters ---------- img_gt: np.array Array of the ground truth segmentation map. img_pred: np.array Array of the predicted segmentation map. voxel_size: list, tuple or np.array The size of a voxel of the images used to compute the volumes. Return ------ A list of metrics in this order, [Dice LV, Volume LV, Err LV(ml), Dice RV, Volume RV, Err RV(ml), Dice MYO, Volume MYO, Err MYO(ml)] """ print (img_gt.shape) print (img_pred.shape) if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res = [] # Loop on each classes of the input images for c in [255]: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) hd_value=hd(gt_c_i,pred_c_i,voxelspacing=VOXEL_SPACING,connectivity=1) assd_value = assd(gt_c_i, pred_c_i, voxelspacing=VOXEL_SPACING,connectivity=1) jd=jc(gt_c_i,pred_c_i) # Compute volume # volpred = pred_c_i.sum() * np.prod(voxel_size) / 1000. # volgt = gt_c_i.sum() * np.prod(voxel_size) / 1000. # res+=[dice,jd] res += [dice,jd,hd_value,assd_value]#,volpred, volpred-volgt] return res
def DiceCoeff(pred, gt): pred = pred.to('cpu').numpy() gt = gt.to('cpu').numpy() # if gt is all zero (use inverse to count) if np.count_nonzero(gt) == 0: gt = gt + 1 pred = 1 - pred return dc(pred, gt)
def inferencee(network, x_train, y_train, imageNames, epoch, folder_save, number_modalities): a = 64 b = 64 '''root_dir = './Data/MRBrainS/DataNii/' model_dir = 'model' moda_1 = root_dir + 'Training/T1' moda_2 = root_dir + 'Training/T1_IR' moda_3 = root_dir + 'Training/T2_FLAIR' moda_g = root_dir + 'Training/GT''' network.eval() softMax = nn.Sigmoid() numClasses = 1 if torch.cuda.is_available(): softMax.cuda() network.cuda() patchSize = a patchSize_gt = b pred_numpy = np.zeros((0, patchSize_gt, patchSize_gt, patchSize_gt)) pred_numpy = np.vstack( (pred_numpy, np.zeros( (x_train.shape[0], patchSize_gt, patchSize_gt, patchSize_gt)))) # pred = network(numpy_to_var(x[0,:,:,:,:]).view(1,number_modalities,patchSize,patchSize,patchSize)) for i_p in range(x_train.shape[0]): pred = network( numpy_to_var(x_train[i_p, :, :, :, :].reshape( 1, number_modalities, patchSize, patchSize, patchSize))) pred_y = softMax(pred.reshape(patchSize_gt, patchSize_gt, patchSize_gt)) pred_numpy[i_p, :, :, :] = pred_y.cpu().data.numpy() printProgressBar(i_p + 1, x_train.shape[0], prefix="[Training_eval] ", length=15) # To reconstruct the predicted volume extraction_step_value = b pred_classes = np.round(pred_numpy) pred_classes = pred_classes.reshape( (x_train.shape[0], patchSize_gt, patchSize_gt, patchSize_gt)) # bin_seg = reconstruct_volume(pred_classes, (img_shape[1], img_shape[2], img_shape[3])) # bin_seg = bin_seg[:,:,extraction_step_value:img_shape[3]-extraction_step_value] dsc = dc(y_train, pred_classes) acc = accuracy_score(y_train.flatten(), pred_classes.flatten()) return dsc, acc
def getbest_dice(preds_train_func,pred_mask): dice=np.zeros(256,dtype=np.float32) for i in range(0,255): hello=preds_train_func[...,axis].squeeze() hello = (hello>i).astype(np.bool) #ihere+=i dcval= dc(hello,pred_mask)*100 #print('here',dcval) #dice= [] dice[i]=dcval #dice= int(dice) #data= [dice,i] return dice
def CalDice(SegRes, Ref, seg_labels, ref_labels): Dice_array = [] ASSD_array = [] print(len(np.unique(SegRes))) if len(np.unique(SegRes)) > 3: print('Subnuclei!') seg_labels = [1,2,3,4,5,6,7,8,9,10] ref_labels = [1,2,3,4,5,6,7,8,9,10] for res_c,ref_c in zip(seg_labels,ref_labels): if (res_c != 1) & (res_c != 6) & (ref_c != 1) & (res_c != 6): dc = mmb.dc(SegRes == res_c, Ref == ref_c) Dice_array.append(dc) else: print('Amygdala!') ref_labels = [1,2] seg_labels = [1,2] for res_c,ref_c in zip(seg_labels,ref_labels): dc = mmb.dc(SegRes == res_c, Ref == ref_c) Dice_array.append(dc) return Dice_array
def evaluateSegmentation(gt, pred): pred = pred.astype(dtype='int') numClasses = np.unique(gt) dsc = np.zeros((1, len(numClasses) - 1)) for i_n in range(1, len(numClasses)): gt_c = np.zeros(gt.shape) y_c = np.zeros(gt.shape) gt_c[np.where(gt == i_n)] = 1 y_c[np.where(pred == i_n)] = 1 dsc[0, i_n - 1] = dc(gt_c, y_c) return dsc
def get_score(truth, prediction, masking_functions): score = list() dice_score = [dc(func(truth), func(prediction)) for func in masking_functions] # hd_score = [hd(func(truth), func(prediction)) # for func in masking_functions] sensitivity_score = [sensitivity(func(truth), func(prediction)) for func in masking_functions] specificity_score = [specificity(func(truth), func(prediction)) for func in masking_functions] score.extend(dice_score) # score.extend(sensitivity_score) # score.extend(specificity_score) return score
def binary_measures_numpy(result, target, binary_threshold=0.5): result_binary = (result > binary_threshold).astype(numpy.uint8) target_binary = (target > binary_threshold).astype(numpy.uint8) result = BinaryMeasuresDto(mpm.dc(result_binary, target_binary), numpy.Inf, numpy.Inf, mpm.precision(result_binary, target_binary), mpm.sensitivity(result_binary, target_binary), mpm.specificity(result_binary, target_binary)) if result_binary.any() and target_binary.any(): result.hd = mpm.hd(result_binary, target_binary) result.assd = mpm.assd(result_binary, target_binary) return result
def metrics(img_gt, img_pred, classes): """ author: Clément Zotti ([email protected]) date: April 2017 - without the volume part Function to compute the metrics between two segmentation maps given as input. Parameters ---------- img_gt: np.array Array of the ground truth segmentation map. img_pred: np.array Array of the predicted segmentation map. Return ------ A list of metrics in this order, [Dice LV, Dice RV, Dice MYO] """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format( img_gt.ndim, img_pred.ndim)) res = [] # Loop on each classes of the input images for c in classes: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) res += [dice] return np.array(res)
def process_model(c,files,mhas): errs = [] dorf = [] asd = [] ravd_arr = [] dc_arr = [] vols = [] for f in files: mod = f.replace('truth',c) img_name = f.split('.')[0] img_file = [i for i in mhas if img_name in i][0] print f, mod, img_file ref_img = sitk.ReadImage(img_file) p1 = utility.readVTKPD(vtk_dir+f) p2 = utility.readVTKPD(vtk_dir+mod) e = utility.jaccard3D_pd_to_itk(p1,p2,ref_img) errs.append(e) np1 = utility.pd_to_numpy_vol(p1, spacing=ref_img.GetSpacing(), shape=ref_img.GetSize(), origin=ref_img.GetOrigin() ) np2 = utility.pd_to_numpy_vol(p2, spacing=ref_img.GetSpacing(), shape=ref_img.GetSize(), origin=ref_img.GetOrigin() ) if np.sum(np1) > 0 and np.sum(np2) > 0: e = hd(np1,np2, ref_img.GetSpacing()[0]) dorf.append(e) e_asd = assd(np1,np2, ref_img.GetSpacing()[0]) asd.append(e_asd) e_ravd = abs(ravd(np1,np2)) ravd_arr.append(e_asd) e_dc = dc(np1,np2) dc_arr.append(e_dc) vols.append(np.sum(np1)*ref_img.GetSpacing()[0]) np.save(output_dir+'{}.jaccard.npy'.format(c),errs) np.save(output_dir+'{}.dorf.npy'.format(c),dorf) np.save(output_dir+'{}.assd.npy'.format(c),asd) np.save(output_dir+'{}.ravd.npy'.format(c),ravd_arr) np.save(output_dir+'{}.dc.npy'.format(c),dc_arr) np.save(output_dir+'{}.vols.npy'.format(c),vols) return '{} , {}, {}, {}, {}, {}, {}, {}, {}, {}, {}\n'.format(\ c,np.mean(errs),np.std(errs),np.mean(dorf),np.std(dorf),np.mean(asd),\ np.std(asd), np.mean(ravd_arr),np.std(ravd_arr),np.mean(dc_arr),np.std(dc_arr))
def evaluate_metrics(prediction, reference): results = {} for c,key in enumerate(["_RV", "_MYO", "_LV"],start=1): ref = np.copy(reference) pred = np.copy(prediction) ref = ref if c==0 else np.where(ref!=c, 0, ref) pred = pred if c==0 else np.where(np.rint(pred)!=c, 0, pred) try: results["DSC" + key] = binary.dc(np.where(ref!=0, 1, 0), np.where(np.rint(pred)!=0, 1, 0)) except: results["DSC" + key] = 0 try: results["HD" + key] = binary.hd(np.where(ref!=0, 1, 0), np.where(np.rint(pred)!=0, 1, 0)) except: results["HD" + key] = np.nan return results
def evaluateSegmentation(gt, pred): pred = pred.astype(dtype='int') gt = gt.astype(dtype='int') # print(np.unique(pred)) # print('pred',pred.shape) numClasses = np.unique(gt) # print('gt',numClasses) dsc = np.zeros((1, len(numClasses) - 1)) for i_n in range(1, len(numClasses)): gt_c = np.zeros(gt.shape) y_c = np.zeros(gt.shape) gt_c[np.where(gt == i_n)] = 1 # print(gt_c[:,0:18,0:18]) y_c[np.where(pred == i_n)] = 1 # print(y_c[:,0:18,0:18]) dsc[0, i_n - 1] = dc(gt_c, y_c) return dsc
def metrics(img_gt, img_pred, ifhd=True, ifasd=True): """ Function to compute the metrics between two segmentation maps given as input. img_gt: Array of the ground truth segmentation map. img_pred: Array of the predicted segmentation map. Return: A list of metrics in this order, [Dice endo, HD endo, ASD endo, Dice RV, HD RV, ASD RV, Dice MYO, HD MYO, ASD MYO] """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res = [] # cat = {500: 'endo', 600: 'rv', 200: 'myo'} for c in [500, 600, 200]: # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) h_d, a_sd = -1, -1 if ifhd or ifasd: if np.sum(gt_c_i) == 0 or np.sum(pred_c_i) == 0: dice = -1 h_d = -1 a_sd = -1 else: h_d = hd(gt_c_i, pred_c_i) if ifhd else h_d a_sd = asd(gt_c_i, pred_c_i) if ifasd else a_sd res += [dice, h_d, a_sd] return res
def evaluate(img_gt, img_pred, apply_hd=False, apply_asd=False): """ Function to compute the metrics between two segmentation maps given as input. :param img_gt: Array of the ground truth segmentation map. :param img_pred: Array of the predicted segmentation map. :param apply_hd: whether to compute Hausdorff Distance. :param apply_asd: Whether to compute Average Surface Distance. :return: A list of metrics in this order, [dice myo, hd myo, asd myo, dice lv, hd lv asd lv, dice rv, hd rv, asd rv] """ if img_gt.ndim != img_pred.ndim: raise ValueError("The arrays 'img_gt' and 'img_pred' should have the " "same dimension, {} against {}".format(img_gt.ndim, img_pred.ndim)) res = {} class_name = ["myo", "lv", "rv"] # Loop on each classes of the input images for c, cls_name in zip([1, 2, 3], class_name) : # Copy the gt image to not alterate the input gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 # Copy the pred image to not alterate the input pred_c_i = np.copy(img_pred) pred_c_i[pred_c_i != c] = 0 # Clip the value to compute the volumes gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) # Compute the Dice dice = dc(gt_c_i, pred_c_i) h_d, a_sd = 0, 0 if apply_hd: h_d = hd(gt_c_i, pred_c_i) if apply_asd: a_sd = asd (gt_c_i, pred_c_i) # Compute volume res[cls_name] = [dice, h_d, a_sd] return res
def eval_net_3D(net, test_image_names, device, dir_path, save_dir): net.eval() tot = [] for image_name in test_image_names: img, lab = get_3d_image_and_label(dir_path, image_name) for i in range(lab.shape[2]): lab[:, :, i] = cv2.resize(lab[:, :, i], dsize=(512, 512), interpolation=cv2.INTER_NEAREST) current_image = img[:, :, i] current_image = torch.from_numpy(current_image) current_image = current_image.to(device=device) current_image = current_image.unsqueeze(dim=0) current_image = current_image.unsqueeze(dim=0) current_image = current_image.float() mask_pred = net(current_image).squeeze(dim=0) mask_pred = mask_pred.cpu().detach().numpy() mask_pred = np.argmax(mask_pred, 0) img[:, :, i] = mask_pred if save_dir is not None: num = re.findall('\d+', image_name) save_name = os.path.join(save_dir, str(num[0]).zfill(4) + '.' + str(i+1).zfill(4) + '.png') cv2.imwrite(save_name, mask_pred * 30) res = [] for c in [1, 2, 3, 4, 5, 6, 7]: gt_c_i = np.copy(lab) gt_c_i[gt_c_i != c] = 0 pred_c_i = np.copy(img) pred_c_i[pred_c_i != c] = 0 gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) dice = dc(gt_c_i, pred_c_i) res += [dice] print(image_name, res, sum(res)/len(res)) tot += [res] tot = np.sum(tot, axis=0) tot = np.divide(tot, len(test_image_names)) return tot
def dice_calculation(gt, seg): gt, hd_gt = nrrd.read(gt) seg, hd_seg = nrrd.read(seg) if (hd_seg['space origin'] == hd_gt['space origin']).all(): seg = np.squeeze(seg) gt = gt.astype('uint16') seg = seg.astype('uint16') dice = dc(seg, gt) else: dice = None # vox_gt = np.sum(gt) # vox_seg = np.sum(seg) # try: # common = np.sum(gt & seg) # except: # print(gt) # dice = (2*common)/(vox_gt+vox_seg) return dice
def eval_net(net, dataset, device, n_val): net.eval() tot = 0 for i, b in tqdm(enumerate(dataset), total=n_val, desc='Validation round', unit='img'): img = b[0] true_mask = b[1][0] img = torch.from_numpy(img).unsqueeze(0) true_mask = torch.from_numpy(true_mask) img = img.to(device=device) true_mask = true_mask.to(device=device) mask_pred = net(img).squeeze(dim=0) mask_pred = mask_pred.cpu().detach().numpy() true_mask = true_mask.cpu().detach().numpy() mask_pred = np.argmax(mask_pred, 0) # print(np.unique(true_mask), np.unique(mask_pred)) if (len(np.unique(true_mask)) == 1 and np.unique(true_mask) == [0]): n_val -= 1 else: current_dice = 0 classes = np.unique(true_mask) for c in [1, 2, 3, 4, 5, 6, 7]: gt_c_i = np.copy(true_mask) gt_c_i[gt_c_i != c] = 0 pred_c_i = np.copy(mask_pred) pred_c_i[pred_c_i != c] = 0 gt_c_i = np.clip(gt_c_i, 0, 1) pred_c_i = np.clip(pred_c_i, 0, 1) dice = dc(gt_c_i, pred_c_i) current_dice += dice # print(current_dice / (len(classes)-1)) tot += (current_dice / (len(classes)-1)) # plot_img_and_mask(true_mask, mask_pred) return tot / n_val
def main(): parser = argparse.ArgumentParser( description='Iterative Fully Convolutional Network') parser.add_argument('--label_dir', type=str, default='./crop_isotropic_dataset/test/seg', help='folder of test label') parser.add_argument('--pred_dir', type=str, default='./pred', help='folder of pred masks') args = parser.parse_args() labels = [ os.path.join(args.label_dir, x) for x in os.listdir(os.path.join(args.label_dir)) if 'raw' not in x ] preds = [ os.path.join(args.pred_dir, x) for x in os.listdir(os.path.join(args.pred_dir)) if 'raw' not in x ] n = 0 avg_dc = 0. for l, p in zip(labels, preds): logging.info("Process %s and %s" % (p, l)) label = sitk.GetArrayFromImage(sitk.ReadImage(l)) pred = sitk.GetArrayFromImage(sitk.ReadImage(p)) for i in np.unique(label): l = label[label == i] p = pred[label == i] l[l > 0] = 1 p[p > 0] = 1 avg_dc += dc(p, l) n += 1 logging.info( "Average Dice Coefficient for %s individual vertebrae test : %s" % (n, avg_dc / n))