Skip to content

Commit cb38dfc

Browse files
Carole SudreCarole Sudre
authored andcommitted
Setting to 1 for boundary IoU and NSD if both ref and pred are empty
1 parent b6da9e1 commit cb38dfc

File tree

2 files changed

+59
-38
lines changed

2 files changed

+59
-38
lines changed

MetricsReloaded/metrics/pairwise_measures.py

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,9 @@ def centreline_dsc(self):
10711071
10721072
:return: cDSC
10731073
"""
1074+
if self.n_pos_pred == 0 and self.n_pos_ref == 0:
1075+
warnings.warn("Both reference and prediction are empty - setting to max")
1076+
return 1
10741077
top_prec = self.topology_precision()
10751078
top_sens = self.topology_sensitivity()
10761079
numerator = 2 * top_sens * top_prec
@@ -1101,36 +1104,40 @@ def boundary_iou(self):
11011104
distance = self.dict_args["boundary_dist"]
11021105
else:
11031106
distance = 1
1104-
border_ref = MorphologyOps(self.ref, self.connectivity).border_map()
1105-
distance_border_ref = ndimage.distance_transform_edt(1 - border_ref)
1106-
1107-
border_pred = MorphologyOps(self.pred, self.connectivity).border_map()
1108-
distance_border_pred = ndimage.distance_transform_edt(1 - border_pred)
1107+
if int(self.n_pos_ref()) == 0 and int(self.n_pos_pred()) == 0:
1108+
warnings.warn("Both prediction and reference empty - setting to max for boudnary ioU")
1109+
return 1
1110+
else:
1111+
border_ref = MorphologyOps(self.ref, self.connectivity).border_map()
1112+
distance_border_ref = ndimage.distance_transform_edt(1 - border_ref)
11091113

1110-
lim_dbp = np.where(
1111-
np.logical_and(distance_border_pred < distance, self.pred>0),
1112-
np.ones_like(border_pred),
1113-
np.zeros_like(border_pred),
1114-
)
1115-
lim_dbr = np.where(
1116-
np.logical_and(distance_border_ref < distance, self.ref>0),
1117-
np.ones_like(border_ref),
1118-
np.zeros_like(border_ref),
1119-
)
1114+
border_pred = MorphologyOps(self.pred, self.connectivity).border_map()
1115+
distance_border_pred = ndimage.distance_transform_edt(1 - border_pred)
11201116

1121-
intersect = np.sum(lim_dbp * lim_dbr)
1122-
union = np.sum(
1123-
np.where(
1124-
lim_dbp + lim_dbr > 0,
1125-
np.ones_like(border_ref),
1117+
lim_dbp = np.where(
1118+
np.logical_and(distance_border_pred < distance, self.pred>0),
1119+
np.ones_like(border_pred),
11261120
np.zeros_like(border_pred),
11271121
)
1128-
)
1129-
if union == 0:
1130-
warnings.warn('Union empty for boundary iou - not defined')
1131-
return np.nan
1132-
boundary_iou = intersect / union
1133-
return boundary_iou
1122+
lim_dbr = np.where(
1123+
np.logical_and(distance_border_ref < distance, self.ref>0),
1124+
np.ones_like(border_ref),
1125+
np.zeros_like(border_ref),
1126+
)
1127+
1128+
intersect = np.sum(lim_dbp * lim_dbr)
1129+
union = np.sum(
1130+
np.where(
1131+
lim_dbp + lim_dbr > 0,
1132+
np.ones_like(border_ref),
1133+
np.zeros_like(border_pred),
1134+
)
1135+
)
1136+
# if union == 0:
1137+
# warnings.warn('Union empty for boundary iou - not defined')
1138+
# return np.nan
1139+
boundary_iou = intersect / union
1140+
return boundary_iou
11341141

11351142

11361143
@CacheFunctionOutput
@@ -1177,19 +1184,23 @@ def normalised_surface_distance(self):
11771184
else:
11781185
warnings.warn('No value set up for NSD tolerance - default to 1')
11791186
tau = 1
1180-
dist_ref, dist_pred, border_ref, border_pred = self.border_distance()
1181-
reg_ref = np.where(
1187+
if int(self.n_pos_pred()) == 0 and int(self.n_pos_ref()) == 0 :
1188+
warnings.warn("Both reference and prediction are empty - setting to best")
1189+
return 1
1190+
else:
1191+
dist_ref, dist_pred, border_ref, border_pred = self.border_distance()
1192+
reg_ref = np.where(
11821193
dist_ref <= tau, np.ones_like(dist_ref), np.zeros_like(dist_ref)
1183-
)
1184-
reg_pred = np.where(
1185-
dist_pred <= tau, np.ones_like(dist_pred), np.zeros_like(dist_pred)
1186-
)
1187-
# print(np.sum(border_pred),np.sum(reg_ref),np.sum(border_ref),np.sum(reg_pred))
1188-
# print(np.sum(border_pred*reg_ref),np.sum(border_ref*reg_pred))
1189-
numerator = np.sum(border_pred * reg_ref) + np.sum(border_ref * reg_pred)
1190-
denominator = np.sum(border_ref) + np.sum(border_pred)
1191-
# print(numerator, denominator, tau)
1192-
return numerator / denominator
1194+
)
1195+
reg_pred = np.where(
1196+
dist_pred <= tau, np.ones_like(dist_pred), np.zeros_like(dist_pred)
1197+
)
1198+
# print(np.sum(border_pred),np.sum(reg_ref),np.sum(border_ref),np.sum(reg_pred))
1199+
# print(np.sum(border_pred*reg_ref),np.sum(border_ref*reg_pred))
1200+
numerator = np.sum(border_pred * reg_ref) + np.sum(border_ref * reg_pred)
1201+
denominator = np.sum(border_ref) + np.sum(border_pred)
1202+
# print(numerator, denominator, tau)
1203+
return numerator / denominator
11931204

11941205
def measured_distance(self):
11951206
"""

test/test_metrics/test_pairwise_measures.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,16 @@ def test_boundary_iou():
870870
value_test2 = ppm212_2.boundary_iou()
871871
assert_allclose(value_test1, expected_biou_1, atol=0.1)
872872
assert_allclose(value_test2, expected_biou_2, atol=0.1)
873+
874+
def test_empty_ref_pred_nsd_biou():
875+
ref_empty = np.zeros([14,14])
876+
pred_empty = np.zeros([14,14])
877+
ppm_empty = PM(pred_empty, ref_empty)
878+
nsd = ppm_empty.normalised_surface_distance()
879+
assert nsd == 1
880+
biou = ppm_empty.boundary_iou()
881+
assert biou == 1
882+
873883

874884
def test_cldsc_s214():
875885
value_test1 = ppm214_1.centreline_dsc()

0 commit comments

Comments
 (0)