def Hausdorf(pred, gt, replace_NaN=100): HD95_dict = {} bg_hd = hd(pred == 0, gt == 0) if 1 in np.unique(pred): csf_hd = hd(pred == 1, gt == 1) else: csf_hd = replace_NaN if 2 in np.unique(pred): gm_hd = hd(pred == 2, gt == 2) else: gm_hd = replace_NaN if 3 in np.unique(pred): wm_hd = hd(pred == 3, gt == 3) else: wm_hd = replace_NaN if 4 in np.unique(pred): tm_hd = hd(pred == 4, gt == 4) else: tm_hd = replace_NaN HD95_dict['avg'] = (csf_hd + gm_hd + wm_hd + tm_hd) / 4 HD95_dict['bg'] = bg_hd HD95_dict['csf'] = csf_hd HD95_dict['gm'] = gm_hd HD95_dict['wm'] = wm_hd HD95_dict['tm'] = tm_hd return HD95_dict
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 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 hausdorff(preds: Tensor, target: Tensor, spacing: Tensor = None) -> Tensor: assert preds.shape == target.shape assert one_hot(preds) assert one_hot(target) B, K, *img_shape = preds.shape if not spacing: D: int = len(img_shape) spacing = torch.ones((B, D), dtype=torch.float32) assert spacing.shape == (B, len(img_shape)) res = torch.zeros((B, K), dtype=torch.float32, device=preds.device) n_pred = preds.cpu().numpy() n_target = target.cpu().numpy() n_spacing = spacing.cpu().numpy() for b in range(B): # if K == 2: # res[b, :] = hd(n_pred[b, 1], n_target[b, 1], voxelspacing=n_spacing[b]) # continue for k in range(K): if not n_pred[b, k].any() and not n_target[b, k].any(): res[b, k] = 0 continue elif not n_pred[b, k].any() or not n_target[b, k].any(): res[b, k] = 0 continue res[b, k] = hd(n_pred[b, k], n_target[b, k], voxelspacing=n_spacing[b]) 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 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 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 compute_metrics_on_directories_raw(dir_gt, dir_pred): """ Calculates all possible metrics (the ones from the metrics script as well as hausdorff and average symmetric surface distances) :param dir_gt: Directory of the ground truth segmentation maps. :param dir_pred: Directory of the predicted segmentation maps. :return: """ lst_gt = sorted(glob(os.path.join(dir_gt, '*')), key=natural_order) lst_pred = sorted(glob(os.path.join(dir_pred, '*')), key=natural_order) res = [] cardiac_phase = [] file_names = [] measure_names = [ 'Dice LV', 'Volume LV', 'Err LV(ml)', 'Dice RV', 'Volume RV', 'Err RV(ml)', 'Dice MYO', 'Volume MYO', 'Err MYO(ml)', 'Hausdorff LV', 'Hausdorff RV', 'Hausdorff Myo', 'ASSD LV', 'ASSD RV', 'ASSD Myo' ] res_mat = np.zeros((len(lst_gt), len(measure_names))) ind = 0 for p_gt, p_pred in zip(lst_gt, lst_pred): if os.path.basename(p_gt) != os.path.basename(p_pred): raise ValueError("The two files don't have the same name" " {}, {}.".format(os.path.basename(p_gt), os.path.basename(p_pred))) gt, _, header = load_nii(p_gt) pred, _, _ = load_nii(p_pred) zooms = header.get_zooms() res.append(metrics(gt, pred, zooms)) cardiac_phase.append( os.path.basename(p_gt).split('.nii.gz')[0].split('_')[-1]) file_names.append(os.path.basename(p_pred)) res_mat[ind, :9] = metrics(gt, pred, zooms) for ii, struc in enumerate([3, 1, 2]): gt_binary = (gt == struc) * 1 pred_binary = (pred == struc) * 1 res_mat[ind, 9 + ii] = hd(gt_binary, pred_binary, voxelspacing=zooms, connectivity=1) res_mat[ind, 12 + ii] = assd(pred_binary, gt_binary, voxelspacing=zooms, connectivity=1) ind += 1 return res_mat, cardiac_phase, measure_names, file_names
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 numpy_haussdorf(pred: np.ndarray, target: np.ndarray, voxelspacing: Union[float, List[float]] = None) -> float: assert len(pred.shape) == 2 assert pred.shape == target.shape # h = max(directed_hausdorff(pred, target)[0], directed_hausdorff(target, pred)[0]) try: h = hd(pred, target, voxelspacing) except RuntimeError: h = 0 return h
def compute_hausdorff(pred_label, gt_label, mode='max'): assert (pred_label.shape == gt_label.shape) hdf_dist = 0.0 n = 0 max_slice = 0 hd_list = [] #hausdorff_distance_filter = sitk.HausdorffDistanceImageFilter() for ii in range(pred_label.shape[0]): if (pred_label[ii].sum() == 0 or gt_label[ii].sum() == 0): hd_list.append(0) continue #print(ii,hd(pred_label[ii], gt_label[ii])) if mode == 'max': # hausdorff_distance_filter.Execute(sitk.GetImageFromArray(pred_label[ii]), sitk.GetImageFromArray(gt_label[ii])) # dist = hausdorff_distance_filter.GetHausdorffDistance() # hdf_dist = max(hdf_dist, dist) dist_i = hd(pred_label[ii], gt_label[ii]) if dist_i > hdf_dist: hdf_dist = dist_i max_slice = ii elif mode == 'avg': # hausdorff_distance_filter.Execute(sitk.GetImageFromArray(pred_label[ii]), sitk.GetImageFromArray(gt_label[ii])) # dist = hausdorff_distance_filter.GetHausdorffDistance() # hdf_dist += dist hdf_dist += hd(pred_label[ii], gt_label[ii]) n += 1 elif mode == 'every': dist_i = hd(pred_label[ii], gt_label[ii]) hd_list.append(dist_i) if mode == 'max': return hdf_dist, max_slice elif mode == 'avg': final_dist = hdf_dist / n if n != 0 else hdf_dist return final_dist else: return hd_list
def hausdorff(preds: Tensor, target: Tensor, spacing: Tensor = None) -> Tensor: assert preds.shape == target.shape assert one_hot(preds) assert one_hot(target) B, K, *img_shape = preds.shape if spacing is None: D: int = len(img_shape) spacing = torch.ones((B, D), dtype=torch.float32) assert spacing.shape == (B, len(img_shape)) res = torch.zeros((B, K), dtype=torch.float32, device=preds.device) n_pred = preds.cpu().numpy() n_target = target.cpu().numpy() n_spacing = spacing.cpu().numpy() for b in range(B): # print(spacing[b]) # if K == 2: # res[b, :] = hd(n_pred[b, 1], n_target[b, 1], voxelspacing=n_spacing[b]) # continue for k in range(K): if not n_target[b, k].any(): # No object to predict if n_pred[b, k].any(): # Predicted something nonetheless res[b, k] = sum( (dd * d)**2 for (dd, d) in zip(n_spacing[b], img_shape))**0.5 continue else: res[b, k] = 0 continue if not n_pred[b, k].any(): if n_target[b, k].any(): res[b, k] = sum( (dd * d)**2 for (dd, d) in zip(n_spacing[b], img_shape))**0.5 continue else: res[b, k] = 0 continue res[b, k] = hd(n_pred[b, k], n_target[b, k], voxelspacing=n_spacing[b]) return res
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 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 hausdorff_multilabel(y_true, y_pred, numLabels=4, channel='channel_first'): """ :param y_true: :param y_pred: :param numLabels: :return: """ assert channel=='channel_first' or channel=='channel_last', r"channel has to be either 'channel_first' or 'channel_last'" hd_score = 0 if channel == 'channel_first': y_true = np.moveaxis(y_true, 1, -1) y_pred = np.moveaxis(y_pred, 1, -1) for index in range(1, numLabels): temp = hd(reference=y_true[:, :, :, index], result=y_pred[:, :, :, index]) hd_score += temp hd_score = hd_score / (numLabels - 1) return hd_score
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 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 hd_3D(img_pred, img_gt, labels=[3, 1, 2]): res = [] for c in labels: gt_c_i = np.copy(img_gt) gt_c_i[gt_c_i != c] = 0 pred_c_i = np.copy(img_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) if np.sum(pred_c_i) == 0 or np.sum(gt_c_i) == 0: hausdorff = 0 else: hausdorff = hd(pred_c_i, gt_c_i) res += [hausdorff] return res
def run_hd(image1, image2, mode='max'): image1_data, hd1 = nrrd.read(image1) space_x = np.abs(hd1['space directions'][0, 0]) space_y = np.abs(hd1['space directions'][1, 1]) space_z = np.abs(hd1['space directions'][2, 2]) image2_data, hd2 = nrrd.read(image2) if (hd1['space origin'] == hd2['space origin']).all(): if mode == 'max': hd_val = hd(image1_data, image2_data, (space_x, space_y, space_z)) elif mode == '95': hd_val = hd95(image1_data, image2_data, (space_x, space_y, space_z)) else: raise Exception( 'Unknown mode "{}". Possible values are "max" or "95".'.format( mode)) else: hd_val = None return hd_val
def hausdorff_eval(y_true, y_pred, voxelspacing=None, connectivity=1, threshold=0.5): if not isinstance(y_true, (np.ndarray, np.generic)): y_true = np.asarray(y_true) if not isinstance(y_pred, (np.ndarray, np.generic)): y_pred = np.asarray(y_pred) y_pred = np.where(np.array(y_pred) > threshold, 1, 0) try: hd_score = hd(y_true, y_pred, voxelspacing=voxelspacing, connectivity=connectivity) except: hd_score = 0 return hd_score
def compute_scores(preds, labels): preds_data = preds.data.cpu().numpy() labels_data = labels.data.cpu().numpy() dice_score = dc(preds_data, labels_data) jaccard_coef = jc(preds_data, labels_data) hausdorff_dist = hd(preds_data, labels_data) asd_score = asd(preds_data, labels_data) assd_score = assd(preds_data, labels_data) precision_value = precision(preds_data, labels_data) recall_value = recall(preds_data, labels_data) sensitivity_value = sensitivity(preds_data, labels_data) specificity_value = specificity(preds_data, labels_data) return { 'dice score': dice_score, 'jaccard': jaccard_coef, 'hausdorff': hausdorff_dist, 'asd': asd_score, 'assd': assd_score, 'precision': precision_value, 'recall': recall_value, 'sensitivity': sensitivity_value, 'specificity': specificity_value }
def get_hd_metric(batch_result, batch_reference, pixel_size_mm=1, by_label=True): """Computes the Hausdorff Distance (HD) between two masks from two batches.""" if batch_result.shape != batch_reference.shape: raise ValueError('The input batches must be the same size') batch_result = get_one_hot_encoding_from_hard_segm( np.asarray(batch_result), labels=np.unique(batch_reference)).astype(np.bool) batch_reference = get_one_hot_encoding_from_hard_segm( np.asarray(batch_reference)).astype(np.bool) dims = batch_result.shape hd_values = np.ndarray(shape=(dims[0], dims[-1] - 1), dtype=np.float32) for i in range(dims[0]): for l in range(1, dims[-1]): hd_values[i, l - 1] = hd( batch_result[i, :, :, l], batch_reference[i, :, :, l]) if not by_label: hd_values = np.mean(hd_values, axis=1) return hd_values * float(pixel_size_mm)
def main(_): if not FLAGS.dataset_dir: raise ValueError('You must supply the dataset directory with --dataset_dir') tf.logging.set_verbosity(tf.logging.INFO) with tf.Graph().as_default(): tf_global_step = slim.get_or_create_global_step() ###################### # Gnerate the tfRecorder data # ###################### datareader,Volshape,rindex,spmap,labelOrg,imgOrg=EvalSample_Gnerate(FLAGS.dataset_dir, 'Glabel.nrrd') Patchsize=len(rindex) ###################### # Select the dataset # ###################### dataset = dataset_factory.get_dataset( FLAGS.dataset_name, FLAGS.dataset_split_name, FLAGS.dataset_dir,file_pattern=FLAGS.file_name,Datasize=Patchsize) #################### # Select the model # #################### #num_classes=2 with tf.Graph().as_default(): network_fn = nets_factory.get_network_fn( FLAGS.model_name, num_classes=(dataset.num_classes - FLAGS.labels_offset), is_training=False) ############################################################## # Create a dataset provider that loads data from the dataset # ############################################################## provider = slim.dataset_data_provider.DatasetDataProvider( dataset, shuffle=False, common_queue_capacity=2 * FLAGS.batch_size, common_queue_min=FLAGS.batch_size) [image, label] = provider.get(['image', 'label']) # label -= FLAGS.labels_offset ##################################### # Select the preprocessing function # ##################################### preprocessing_name = FLAGS.preprocessing_name or FLAGS.model_name image_preprocessing_fn = preprocessing_factory.get_preprocessing( preprocessing_name, is_training=False) eval_image_size = FLAGS.eval_image_size or network_fn.default_image_size image = image_preprocessing_fn(image, eval_image_size, eval_image_size) images, labels = tf.train.batch( [image, label], batch_size=FLAGS.batch_size, num_threads=FLAGS.num_preprocessing_threads, capacity=5 * FLAGS.batch_size) ################### # Define the model # #################### logits, end_points = network_fn(images) probabilities = tf.nn.softmax(logits) pred = tf.argmax(logits, dimension=1) # if FLAGS.moving_average_decay: # variable_averages = tf.train.ExponentialMovingAverage( # FLAGS.moving_average_decay, tf_global_step) # variables_to_restore = variable_averages.variables_to_restore( # slim.get_model_variables()) # variables_to_restore[tf_global_step.op.name] = tf_global_step # else: # variables_to_restore = slim.get_variables_to_restore() # #predictions = tf.argmax(logits, 1) # labels = tf.squeeze(labels) # # # Define the metrics: # names_to_values, names_to_updates = slim.metrics.aggregate_metric_map({ # 'Accuracy': slim.metrics.streaming_accuracy(predictions, labels), # 'Recall@5': slim.metrics.streaming_recall_at_k( # logits, labels, 5), # }) # # # Print the summaries to screen. # summary_ops = [] # for name, value in names_to_values.items(): # summary_name = 'eval/%s' % name # op = tf.scalar_summary(summary_name, value, collections=[]) # op = tf.Print(op, [value], summary_name) # tf.add_to_collection(tf.GraphKeys.SUMMARIES, op) # summary_ops.append(op) # # TODO(sguada) use num_epochs=1 # if FLAGS.max_num_batches: # num_batches = FLAGS.max_num_batches # else: # # This ensures that we make a single pass over all of the data. # num_batches = math.ceil(dataset.num_samples / float(FLAGS.batch_size)) if tf.gfile.IsDirectory(FLAGS.checkpoint_path): checkpoint_path = tf.train.latest_checkpoint(FLAGS.checkpoint_path) else: checkpoint_path = FLAGS.checkpoint_path tf.logging.info('Evaluating %s' % checkpoint_path) init_fn = slim.assign_from_checkpoint_fn( os.path.join(checkpoint_path), slim.get_model_variables())# vriable name??? #Volshape=(50,61,61) imgshape=spmap.shape segResult=np.zeros(imgshape) groundtruth=np.zeros(imgshape) segPromap=np.zeros(imgshape) segPromapEdge=np.zeros(imgshape) PreMap=[] labellist=[] seglist=[] conv1list=[] conv2list=[] imgorglist=[] fclist=[] with tf.Session() as sess: # Load weights init_fn(sess) # sess.run(images.initializer, feed_dict) # Start input enqueue threads. coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) num_iter = int(math.ceil(dataset.num_samples/float(FLAGS.batch_size))) step = 0 try: while step < num_iter and not coord.should_stop(): # Run evaluation steps or whatever segmentation,log,pmap,labelmap,imgpre,conv1,conv2,fc3= sess.run([pred,logits,probabilities,labels,images,end_points['conv1'],end_points['conv3'],end_points['fc3']]) step+=1 PreMap.extend(pmap) conv1list.extend(conv1) conv2list.extend(conv2) fclist.extend(fc3) imgorglist.extend(imgpre) seglist.append(segmentation) labellist.append(labelmap) print('The No. %d/%d caculation'%(step,num_iter)) #Miaimshow.subplots(Pro_imgs, num=step+2, cols=8) except tf.errors.OutOfRangeError: print('Done evalutaion -- epoch limit reached') finally: # When done, ask the threads to stop. coord.request_stop() PreMap = np.array(PreMap) np.save(os.path.join(FLAGS.dataset_dir,'liverspProbmap.npy'), PreMap) # PreMap=np.squeeze(PreMap,axis=1) # PreMap_flat = PreMap.ravel() # PreMap_flat=np.divide((PreMap_flat - np.amin(PreMap_flat)) * 255, (np.amax(PreMap_flat) - np.amin(PreMap_flat))) m = 0 for i in range(len(rindex)): segResult[spmap==rindex[i]]=np.array(seglist).ravel()[i] segPromap[spmap==rindex[i]]=PreMap[i,1] segPromapEdge[spmap==rindex[i]]=PreMap[i,2] groundtruth[spmap==rindex[i]]=np.array(labellist).ravel()[i] coord.join(threads) fig,ax= plt.subplots(nrows=2,ncols=3) from skimage.segmentation import mark_boundaries ax[0,0].set_title('Segmentation with superpixel map') ax[0,0].imshow(mark_boundaries(segResult, spmap)) ax[0,1].set_title('Segmentation with ground truth map') ax[0,1].imshow(segResult) ax[0,1].imshow(labelOrg,alpha=0.5,cmap='jet') ax[0,2].set_title('Reading label') ax[0,2].imshow(groundtruth) ax[1,0].set_title('liver Probabilities map') ax[1,0].imshow(segPromap) ax[1,1].set_title('edge Probabilities map') ax[1,1].imshow(segPromapEdge) ax[1,2].set_title('liver +edge Probabilities map') ax[1,2].imshow(segPromapEdge+segPromap) segthpro=segPromapEdge+segPromap segthpro[segthpro<0.8]=0 from skimage.segmentation import active_contour from skimage.measure import find_contours from skimage.filters import gaussian from skimage import morphology #edg=sobel(segResult.astype(int)) segmorp=morphology.remove_small_objects(segthpro.astype(bool),5000) segopen=morphology.opening(segmorp,morphology.disk(3)) segclose=morphology.closing(segopen,morphology.disk(15)) fig,ax=plt.subplots(1,3) ax=ax.ravel() ax[0].imshow(segmorp) ax[0].set_title('Removed the small objects') ax[1].imshow(segopen) ax[1].set_title('After open operation') ax[2].imshow(segclose) ax[2].imshow(labelOrg,alpha=0.5,cmap='jet') ax[2].set_title('After close operation') plt.axis('off') from MiaUtils import Miametrics as metric mt=metric.MiaMetrics(logger) dsc=mt.DSCMetric(segclose,labelOrg.astype(bool)) print('The dice similarity coefficient score is {}'.format(dsc)) voe=mt.VOEMetric(segclose,labelOrg.astype(bool)) print('The Volume overlap Error score is {}'.format(voe)) rvd=mt.RVDMetric(segclose,labelOrg.astype(bool)) print('The Relative voume difference score is {}'.format(rvd)) from medpy.metric.binary import hd from medpy.metric.binary import asd from medpy.metric.binary import obj_fpr from medpy.metric.binary import obj_tpr Asd=asd(segclose,labelOrg.astype(bool)) print('The Asd score is {}'.format(Asd)) HD=hd(segclose,labelOrg.astype(bool)) print('The Hausdorff Distance score is {}'.format(HD)) ###************************************************************************ ####superpixel-graph cuts mehtod computation #######******************************************************************** from skimage import segmentation, color,filters from skimage.future import graph img=DataNormalize(imgOrg)/255 img=np.dstack((np.dstack((img, img)), img)) labels1 = segmentation.slic(img, compactness=5, n_segments=2000,sigma=1) #labels1=spmap out1 = color.label2rgb(labels1, img, kind='avg') edge_map = filters.sobel(color.rgb2gray(img)) g = graph.rag_boundary(labels1, edge_map) #g = graph.rag_mean_color(img, labels1, mode='similarity') labels2 = graph.cut_normalized(labels1, g) out2 = color.label2rgb(labels2, img, kind='avg') fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True) ax[0].imshow(out1) ax[1].imshow(out2) for a in ax: a.axis('off') plt.tight_layout()
np.save(os.path.join(save_dir, str(epochs) + 'epochs_mask_prediction'), mask_prediction) np.save(os.path.join(save_dir, str(epochs) + 'test_images'), test_images) np.save(os.path.join(save_dir, str(epochs) + 'test_masks'), test_masks) np.save(os.path.join(save_dir, str(epochs) + 'rounded_mask_pred'), rounded_pred) mask_prediction = model.predict(test_images, verbose=0) mask_prediction = np.squeeze(mask_prediction, 3) rounded_dice = [] dice = [] thresholded_hausdorff = [] hausdorff = [] for s in range(test_masks.shape[0]): rounded_dice.append(getdicescore(test_masks[s, :, :, 0], rounded_pred[s, :, :])) if np.max(rounded_pred[s, :, :]) != 0: thresholded_hausdorff.append(hd(rounded_pred[s, :, :], test_masks[s, :, :, 0])) median_rounded_dice_score = np.median(rounded_dice) median_thresholded_hausdorff = np.mean(thresholded_hausdorff) median_thresholded_hausdorff = round(median_thresholded_hausdorff, 2) median_rounded_dice_score = round(median_rounded_dice_score, 3) #save_visualisation2(train_images[:, :, :, 0], train_masks[:, :, :, 0], median_rounded_dice_score, median_thresholded_hausdorff, save_dir) save_visualisation(test_images[:,:,:,0], test_masks[:,:,:,0], mask_prediction, rounded_pred, median_rounded_dice_score, median_thresholded_hausdorff, prefix, save_dir)
rounded_pred) rounded_dice = [] dice = [] thresholded_hausdorff = [] hausdorff = [] for s in range(test_masks.shape[0]): rounded_dice.append( getdicescore(test_masks[s, :, :, 0], rounded_pred[s, :, :])) dice.append( getdicescore(test_masks[s, :, :, 0], mask_prediction[s, :, :])) if np.max(rounded_pred[s, :, :]) != 0: thresholded_hausdorff.append( hd(rounded_pred[s, :, :], test_masks[s, :, :, 0])) if np.max(rounded_pred[s, :, :]) != 0: hausdorff.append( hd(rounded_pred[s, :, :], test_masks[s, :, :, 0])) median_rounded_dice_score = np.median( rounded_dice) median_thresholded_hausdorff = np.mean( thresholded_hausdorff) median_thresholded_hausdorff = round( median_thresholded_hausdorff, 2) median_rounded_dice_score = round( median_rounded_dice_score, 3)
def get_geometrical_results(model, data, groundtruths, path, inds, use_pp): """Compute Dices, Hausdorff distances and ASSDs between the model predictions on the inds indices of data and the groundtruths use_pp enables to use post-processing on the predictions. The original image sizes are stored in inds""" # Get predictions from the input data segmentations = model.predict(data, verbose=1) predictions = np.argmax(segmentations, axis=-1) voxel_spacing = [0.154, 0.308] nb_im = predictions.shape[0] nb_struct = groundtruths.shape[-1] - 1 results = np.zeros((nb_im, nb_struct, 3), dtype=np.float) size_file = open(join(path, 'ori_sizes.txt'), 'r') sizes = size_file.readlines() # get image indices indices = [] for ind in inds: indices.append(ind * 2) indices.append(ind * 2 + 1) for im in tnrange(nb_im, desc="Evaluation on each image"): # Reshape the prediction as a binary class matrix pred_cat = keras.utils.to_categorical(predictions[im, :, :], num_classes=4) # get original size from the relative indexing line = sizes[indices[im] - 600] ori_size = [int(line.split()[2][1:-1]), int(line.split()[3][0:-1])] for struct in range(1, nb_struct + 1): # Extract the structure channel pred = pred_cat[:, :, struct] gt = groundtruths[im, :, :, struct] # Resize to the original size pred = np.array( Image.fromarray(pred).resize( (ori_size[1], ori_size[0]), PIL.Image.NEAREST)).astype( 'uint8') #Image.resize inverts dimensions gt = np.array( Image.fromarray(gt).resize((ori_size[1], ori_size[0]), PIL.Image.NEAREST)).astype('uint8') # Transform into boolean array pred = (pred == 1) gt = (gt == 1) # Apply postprocessing if use_pp: pred = post_process(pred) # Compute geometrical metrics using the medpy library dice = dc(pred, gt) if np.sum( pred ) > 0: # If the structure is predicted on at least one pixel hausdorff = hd( pred, gt, voxelspacing=[voxel_spacing[0], voxel_spacing[1]]) asd = assd(pred, gt, voxelspacing=[voxel_spacing[0], voxel_spacing[1]]) else: print("on image ", nb_im, "the structure ", struct, " was not associated to any pixel") hausdorff = 'nan' asd = 'nan' results[im, struct - 1, :] = [dice, hausdorff, asd] return results, segmentations
ground_truth_componentSet = glob.glob(ground_truth_sequenceSet[0] + '/*') ground_truth_componentSet.sort() for component in range(0, len(componentSet)): time_frameSet = glob.glob(componentSet[component] + '/final_results/' + '*.nii.gz') time_frameSet.sort() ground_truth_time_frameSet = glob.glob( ground_truth_componentSet[component] + '/' + '*.nii.gz') ground_truth_time_frameSet.sort() ##### Dice score metric #sheet1.write(subject+1,component+1,Bin_dice(ground_truth_time_frameSet[0],time_frameSet[0])) #sheet2.write(subject+1,component+1,Bin_dice(ground_truth_time_frameSet[1],time_frameSet[len(time_frameSet)-1])) ##### Hausdroff distance metric im1 = nifti_to_array(ground_truth_time_frameSet[0]) im2 = nifti_to_array(time_frameSet[0]) im3 = nifti_to_array(ground_truth_time_frameSet[1]) im4 = nifti_to_array(time_frameSet[len(time_frameSet) - 1]) #sheet1.write(subject+1,component+1,hausdorff(np.argwhere(im1!=0), np.argwhere(im2!=0))) #sheet2.write(subject+1,component+1,hausdorff(np.argwhere(im3!=0), np.argwhere(im4!=0))) sheet1.write(subject + 1, component + 1, hd(im1, im2)) sheet2.write(subject + 1, component + 1, hd(im3, im4)) book.save(save_path)
def val_step(val_loader, model, criterion, weights_criterion, multiclass_criterion, binary_threshold, num_classes=4, generate_stats=False, generate_overlays=False, save_path="", swap_values=None): """ Perform a validation step :param val_loader: (Dataloader) Validation dataset loader :param model: Model used in training :param criterion: Choosed criterion :param weights_criterion: (list -> float) Choosed criterion weights :param multiclass_criterion: :param binary_threshold: (float) Threshold to set class as class 1. Typically 0.5 :param num_classes: Num total classes in predictions :param generate_stats: (bool) If true generate predictions stats via pandas :param generate_overlays: (bool) If true save mask predictions :param save_path: (string) If save_preds then which directory to save mask predictions :param swap_values: (list of lists) In predicted mask, swaps first item and second in list. Example: [[1,2]] :return: Intersection Over Union and Dice Metrics, Mean validation loss """ # https://stackoverflow.com/questions/8713620/appending-items-to-a-list-of-lists-in-python ious, dices = [[] for _ in range(num_classes) ], [[] for _ in range(num_classes)] hausdorffs, assds = [[] for _ in range(num_classes) ], [[] for _ in range(num_classes)] val_loss, df_info = [], [] model.eval() if save_path != "": os.makedirs(save_path, exist_ok=True) with torch.no_grad(): for sample_indx, (image, original_img, original_mask, mask, img_id) in enumerate(val_loader): original_mask = original_mask.cuda() image = image.type(torch.float).cuda() prob_pred = model(image) # ToDo: Fix val loss # val_loss.append(calculate_loss(mask, prob_pred, criterion, weights_criterion, multiclass_criterion).item()) val_loss.append(0.0) for indx, single_pred in enumerate(prob_pred): original_mask = original_mask[indx].data.cpu().numpy().astype( np.uint8).squeeze() # Calculate metrics resizing prediction to original mask shape pred_mask = convert_multiclass_mask( single_pred.unsqueeze(0)).data.cpu().numpy() pred_mask = reshape_masks(pred_mask.squeeze(0), original_mask.shape) if swap_values is not None: for swap_val in swap_values: pred_mask = np.where( pred_mask == swap_val[0], swap_val[1], np.where(pred_mask == swap_val[1], swap_val[0], pred_mask)) patient_iou = [-1, -1, -1] # LV, MYO, RV patient_dice = [-1, -1, -1] # LV, MYO, RV patient_hausddorf = [999, 999, 999] # LV, MYO, RV patient_assd = [999, 999, 999] # LV, MYO, RV for current_class in np.unique( np.concatenate((original_mask, pred_mask))): binary_ground_truth = np.where( original_mask == current_class, 1, 0).astype(np.int32) binary_pred_mask = np.where(pred_mask == current_class, 1, 0).astype(np.int32) tmp_iou = jaccard_coef(binary_ground_truth, binary_pred_mask) tmp_dice = dice_coef(binary_ground_truth, binary_pred_mask) # https://github.com/loli/medpy/blob/master/medpy/metric/binary.py#L1212 if not np.count_nonzero( binary_pred_mask) and not np.count_nonzero( binary_ground_truth): # The same, distances 0 tmp_assd = 0 tmp_hausdorff = 0 elif not np.count_nonzero( binary_pred_mask) or not np.count_nonzero( binary_ground_truth): # ToDo: equivalent worst value for Hausdorff and surface distances tmp_assd = 999 tmp_hausdorff = 999 else: tmp_assd = medmetrics.assd(binary_pred_mask, binary_ground_truth) tmp_hausdorff = medmetrics.hd(binary_pred_mask, binary_ground_truth) ious[current_class].append(tmp_iou) dices[current_class].append(tmp_dice) hausdorffs[current_class].append(tmp_hausdorff) assds[current_class].append(tmp_assd) # -1 Due index 0 is background if current_class != 0: patient_iou[current_class - 1] = tmp_iou patient_dice[current_class - 1] = tmp_dice patient_hausddorf[current_class - 1] = tmp_hausdorff patient_assd[current_class - 1] = tmp_assd if generate_stats: patient_info = img_id[0].split("_") df_info.append({ "patient": patient_info[0], "slice": patient_info[1][5:], "phase": patient_info[2][5:], "IOU_LV": patient_iou[0], "IOU_MYO": patient_iou[1], "IOU_RV": patient_iou[2], "IOU_MEAN": np.mean( np.array([ value for value in patient_iou if value != -1 ])), "DICE_LV": patient_dice[0], "DICE_MYO": patient_dice[1], "DICE_RV": patient_dice[2], "DICE_MEAN": np.mean( np.array([ value for value in patient_dice if value != -1 ])), "HAUSDORFF_LV": patient_hausddorf[0], "HAUSDORFF_MYO": patient_hausddorf[1], "HAUSDORFF_RV": patient_hausddorf[2], "HAUSDORFF_MEAN": np.mean( np.array([ value for value in patient_hausddorf if value != -999 ])), "ASSD_LV": patient_assd[0], "ASSD_MYO": patient_assd[1], "ASSD_RV": patient_assd[2], "ASSD_MEAN": np.mean( np.array([ value for value in patient_assd if value != -999 ])), }) if generate_overlays: plot_save_pred(original_img.data.cpu().numpy().squeeze(), original_mask, pred_mask, save_path, img_id[0]) stats = None if generate_stats: stats = pd.DataFrame(df_info) stats.to_csv(os.path.join(save_path, "val_patient_stats.csv"), index=False) iou = [np.mean(i) for i in ious] # Class mean, not global iou = np.append( np.mean(iou[1:]), iou) # Add as first value global class mean (without background) dice = [np.mean(i) for i in dices] dice = np.append(np.mean(dice[1:]), dice) hausdorff = [np.mean(i) for i in hausdorffs] hausdorff = np.append(np.mean(hausdorff[1:]), hausdorff) assd = [np.mean(i) for i in assds] assd = np.append(np.mean(assd[1:]), assd) return iou, dice, hausdorff, assd, np.mean(val_loss), stats
def __call__(self, prediction, target): try: return binary.hd(prediction, target) except Exception: return np.nan
def compute_metrics_on_directories_raw(dir_gt, dir_pred): """ Calculates a number of measures from the predicted and ground truth segmentations: - Dice - Hausdorff distance - Average surface distance - Predicted volume - Volume error w.r.t. ground truth :param dir_gt: Directory of the ground truth segmentation maps. :param dir_pred: Directory of the predicted segmentation maps. :return: Pandas dataframe with all measures in a row for each prediction and each structure """ filenames_gt = sorted(glob(os.path.join(dir_gt, '*')), key=natural_order) filenames_pred = sorted(glob(os.path.join(dir_pred, '*')), key=natural_order) cardiac_phase = [] file_names = [] structure_names = [] # 5 measures per structure: dices_list = [] hausdorff_list = [] assd_list = [] vol_list = [] vol_err_list = [] structures_dict = {1: 'RV', 2: 'Myo', 3: 'LV'} for p_gt, p_pred in zip(filenames_gt, filenames_pred): if os.path.basename(p_gt) != os.path.basename(p_pred): raise ValueError("The two files don't have the same name" " {}, {}.".format(os.path.basename(p_gt), os.path.basename(p_pred))) # load ground truth and prediction gt, _, header = utils.load_nii(p_gt) pred, _, _ = utils.load_nii(p_pred) zooms = header.get_zooms() # calculate measures for each structure for struc in [3,1,2]: gt_binary = (gt == struc) * 1 pred_binary = (pred == struc) * 1 volpred = pred_binary.sum() * np.prod(zooms) / 1000. volgt = gt_binary.sum() * np.prod(zooms) / 1000. vol_list.append(volpred) vol_err_list.append(volpred - volgt) if np.sum(gt_binary) == 0 and np.sum(pred_binary) == 0: dices_list.append(1) assd_list.append(0) hausdorff_list.append(0) elif np.sum(pred_binary) > 0 and np.sum(gt_binary) == 0 or np.sum(pred_binary) == 0 and np.sum(gt_binary) > 0: logging.warning('Structure missing in either GT (x)or prediction. ASSD and HD will not be accurate.') dices_list.append(0) assd_list.append(1) hausdorff_list.append(1) else: hausdorff_list.append(hd(gt_binary, pred_binary, voxelspacing=zooms, connectivity=1)) assd_list.append(assd(pred_binary, gt_binary, voxelspacing=zooms, connectivity=1)) dices_list.append(dc(gt_binary, pred_binary)) cardiac_phase.append(os.path.basename(p_gt).split('.nii.gz')[0].split('_')[-1]) file_names.append(os.path.basename(p_pred)) structure_names.append(structures_dict[struc]) df = pd.DataFrame({'dice': dices_list, 'hd': hausdorff_list, 'assd': assd_list, 'vol': vol_list, 'vol_err': vol_err_list, 'phase': cardiac_phase, 'struc': structure_names, 'filename': file_names}) return df
print('dice coefficient',maxdice) ############################# Val needs to be shown on GUI #itemindex = np.where(dice==maxdata) #itemindex = np.argmax(best_dice) if axis in range (0,3): itemindex= best_dice[200:255].argmax() + 200 elif axis == 3: itemindex= best_dice[90:255].argmax() + 90 print('Intensity value at max dice',itemindex) preds_perfect=(preds_train255>itemindex-1).astype(np.bool) preds_perfect = preds_perfect[...,axis].squeeze() haufdist= hd(preds_perfect,predictionmask,voxelspacing=None, connectivity=1) print('Hausdorff Distance.',haufdist) ############################# Val needs to be shown on GUI #################################################################################################################################################################### # P-value and A-bland altman plot pearson_stats=stats.pearsonr(preds_perfect.flatten(),predictionmask.flatten()) print('pearson values ','r-value :' ,pearson_stats[0],'p-value :',pearson_stats[1]) ############################# both Vals needs to be shown on GUI mask_graph=predictionmask*255 #mask_graph=cv2.imread(maskimg,0) #mask_graph=tf.keras.utils.to_categorical(mask_graph, num_classes=4, dtype='uint8')*255 #mask_graph= mask_graph[...,axis].squeeze()