def symmetric_contour_distance_l(im1, im2, lab, return_mm3, formula='normalised'):
"""
Generalised normalised symmetric contour distance.
On the set {d(x, contourY)) | x in contourX}, several statistics can be computed.
Mean, median and standard deviation can be useful, as well as a more robust normalisation
Formula can be
:param im1:
:param im2:
:param lab:
:param return_mm3:
:param formula: 'normalised', 'averaged', 'median', 'std'
'normalised' = (\sum_{x in contourX} d(x, contourY)) + \sum_{y in contourY} d(y, contourX))) / (|contourX| + |contourY|)
'averaged' = 0.5 (mean({d(x, contourY)) | x in contourX}) + mean({d(y, contourX)) | y in contourY}))
'median' = 0.5 (median({d(x, contourY)) | x in contourX}) + median({d(y, contourX)) | y in contourY}))
'std' = 0.5 \sqrt(std({d(x, contourY)) | x in contourX})^2 + std({d(y, contourX)) | y in contourY})^2)
:return:
"""
arr1 = im1.get_data() == lab
arr2 = im2.get_data() == lab
if np.count_nonzero(arr1) == 0 or np.count_nonzero(arr2) == 0:
return np.nan
arr1_contour = contour_from_array_at_label_l(arr1, 1)
arr2_contour = contour_from_array_at_label_l(arr2, 1)
if return_mm3:
dtb1 = nd.distance_transform_edt(1 - arr1_contour, sampling=list(np.diag(im1.affine[:3, :3])))
dtb2 = nd.distance_transform_edt(1 - arr2_contour, sampling=list(np.diag(im1.affine[:3, :3])))
else:
dtb1 = nd.distance_transform_edt(1 - arr1_contour)
dtb2 = nd.distance_transform_edt(1 - arr2_contour)
dist_border1_array2 = arr2_contour * dtb1
dist_border2_array1 = arr1_contour * dtb2
if formula == 'normalised':
return (np.sum(dist_border1_array2) + np.sum(dist_border2_array1)) / (np.count_nonzero(arr1_contour) + np.count_nonzero(arr2_contour))
elif formula == 'averaged':
return .5 * (np.mean(dist_border1_array2) + np.mean(dist_border2_array1))
elif formula == 'median':
return .5 * (np.median(dist_border1_array2) + np.median(dist_border2_array1))
elif formula == 'std':
return np.sqrt( .5 * (np.std(dist_border1_array2)**2 + np.std(dist_border2_array1)**2))
elif formula == 'average_std':
return .5 * (np.mean(dist_border1_array2) + np.mean(dist_border2_array1)), \
np.sqrt(.5 * (np.std(dist_border1_array2) ** 2 + np.std(dist_border2_array1) ** 2))
else:
raise IOError
# --- distances - (segm, segm) |-> pandas.Series (indexed by labels)
评论列表
文章目录