Python Hausdorff distance 豪斯多夫距离

  • github官方库
    https://github.com/deepmind/surface-distance
  • 代码示例
import os
import numpy as np
import codecs
import SimpleITK as sitk
import pandas as pd
import torch
import surface_distance as surfdist

def readlines(file):
    """
    read lines by removing '\n' in the end of line
    :param file: a text file
    :return: a list of line strings
    """
    fp = codecs.open(file, 'r', encoding='utf-8')
    linelist = fp.readlines()
    fp.close()
    for i in range(len(linelist)):
        linelist[i] = linelist[i].rstrip('\n') # cancel '\n' per line
    return linelist

def read_test_txt(imlist_file):
    '''
    :param imlist_file: image list file path
    :return: image list path divided into two list
    '''
    lines = readlines(imlist_file)
    num_cases = int(lines[0])

    if (len(lines) - 1) < (num_cases * 2):
        raise ValueError('too few lines in imlist file')
    im_list, seg_list = [], []
    for i in range(num_cases):
        im_path, seg_path = lines[1 + i * 2].strip(), lines[2 + i * 2].strip()
        assert os.path.exists(im_path), 'image not exist: {}'.format(im_path)
        assert os.path.exists(seg_path), 'mask not exist: {}'.format(seg_path)
        im_list.append(im_path)
        seg_list.append(seg_path)

    return im_list, seg_list

def hausdorff_95(input_np, target_np, num_class, spacing, epsilon=1e-6):
    '''
    :params input_tensor:   the result of segmentation
    :params target:         ground true mask
    :params num_class:      label number
    '''
    Hausdorff_95_score = []
    for i in range(1, num_class):
        input_np_copy = input_np.copy()
        target_np_copy = target_np.copy()
        input_np_copy[input_np_copy != i] = 0
        target_np_copy[target_np_copy != i] = 0
        input_np_copy = input_np_copy.astype(np.bool)
        target_np_copy = target_np_copy.astype(np.bool)
        # compute Hausdorff_95 score
        surface_distances = surfdist.compute_surface_distances(target_np_copy, input_np_copy, spacing)
        hd_dist_95 = surfdist.compute_robust_hausdorff(surface_distances, 95) 
        Hausdorff_95_score.append(hd_dist_95)
        print('class = {}, Hausdorff_95_score = {}'.format(i, hd_dist_95))
    return Hausdorff_95_score

def val(input_path, results_csv):
    if input_path.endswith('txt'):
        gt_list, pre_list = read_test_txt(input_path)
    else:
        raise ValueError('image test_list must either be a txt file or a csv file')
    
    Hausdorff_95_score_record = pd.DataFrame(columns = ['case_name', 'left', 'right'])
    for gt_path, pre_path in zip(gt_list, pre_list):
        print('{}: {}'.format(gt_path, pre_path))

        gt_mask = sitk.ReadImage(gt_path)
        pre_mask = sitk.ReadImage(pre_path)
        spacing = gt_mask.GetSpacing()
        case_name = gt_path.split('/')[-1].split('.')[0]
        gt_mask_np = sitk.GetArrayFromImage(gt_mask).astype(float)
        pre_mask_np = sitk.GetArrayFromImage(pre_mask).astype(float)
        num_label = np.unique(gt_mask_np)
        num_class = len(num_label)
        Hausdorff_95_score = hausdorff_95(pre_mask_np, gt_mask_np, num_class, spacing)
        if num_class == 3:
            df = pd.DataFrame({
                'case_name':case_name,
                'left': Hausdorff_95_score[0].item(),
                'right': Hausdorff_95_score[1].item()
            },index=[0]) 
        if num_class == 2:
            df = pd.DataFrame({
                'case_name': case_name,
                'seg_name':Hausdorff_95_score[0].item()
            },index=[0])
        
        Hausdorff_95_score_record = Hausdorff_95_score_record.append(df)
    Hausdorff_95_score_record.to_csv(results_csv, index=None)

input_path = 'dice_20220509_1.txt'
results_csv = '20220509_1.csv'
val(input_path, results_csv)
  • Reference

https://blog.csdn.net/lijiaqi0612/article/details/113925215
https://blog.csdn.net/hajlyx/article/details/105809129

你可能感兴趣的:(Python,医学图像处理,Pytorch,python,深度学习,机器学习)