Last active
August 29, 2019 08:34
-
-
Save hanspinckaers/281fe48b8a9bfad3f873f21041ffc600 to your computer and use it in GitHub Desktop.
Metrics of GlaS challenge in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from scipy import stats | |
from sklearn.neighbors import NearestNeighbors | |
def ObjectHausdorff(S=None, G=None): | |
S = np.array(S).astype(np.uint8) | |
G = np.array(G).astype(np.uint8) | |
totalAreaS = (S > 0).sum() | |
totalAreaG = (G > 0).sum() | |
listLabelS = np.unique(S) | |
listLabelS = np.delete(listLabelS, np.where(listLabelS == 0)) | |
listLabelG = np.unique(G) | |
listLabelG = np.delete(listLabelG, np.where(listLabelG == 0)) | |
temp1 = 0 | |
for iLabelS in range(len(listLabelS)): | |
Si = (S == listLabelS[iLabelS]) | |
intersectlist = G[Si] | |
if intersectlist.any(): | |
indexGi = stats.mode(intersectlist).mode | |
Gi = (G == indexGi) | |
else: | |
tempDist = np.zeros((len(listLabelG), 1)) | |
for iLabelG in range(len(listLabelG)): | |
Gi = (G == listLabelG[iLabelG]) | |
tempDist[iLabelG] = Hausdorff(Gi, Si) | |
minIdx = np.argmin(tempDist) | |
Gi = (G == listLabelG[minIdx]) | |
omegai = Si.sum() / totalAreaS | |
temp1 = temp1 + omegai * Hausdorff(Gi, Si) | |
temp2 = 0 | |
for iLabelG in range(len(listLabelG)): | |
tildeGi = (G == listLabelG[iLabelG]) | |
intersectlist = S[tildeGi] | |
if intersectlist.any(): | |
indextildeSi = stats.mode(intersectlist).mode | |
tildeSi = (S == indextildeSi) | |
else: | |
tempDist = np.zeros((len(listLabelS), 1)) | |
for iLabelS in range(len(listLabelS)): | |
tildeSi = (S == listLabelS[iLabelS]) | |
tempDist[iLabelS] = Hausdorff(tildeGi, tildeSi) | |
minIdx = np.argmin(tempDist) | |
tildeSi = (S == listLabelS[minIdx]) | |
tildeOmegai = tildeGi.sum() / totalAreaG | |
temp2 = temp2 + tildeOmegai * Hausdorff(tildeGi, tildeSi) | |
objHausdorff = (temp1 + temp2) / 2 | |
return objHausdorff | |
def Hausdorff(S=None, G=None): | |
S = np.array(S).astype(np.uint8) | |
G = np.array(G).astype(np.uint8) | |
listS = np.unique(S) | |
listS = np.delete(listS, np.where(listS == 0)) | |
listG = np.unique(G) | |
listG = np.delete(listG, np.where(listG == 0)) | |
numS = len(listS) | |
numG = len(listG) | |
if numS == 0 and numG == 0: | |
hausdorffDistance = 0 | |
return hausdorffDistance | |
else: | |
if numS == 0 or numG == 0: | |
hausdorffDistance = np.Inf | |
return hausdorffDistance | |
y = np.where(S > 0) | |
x = np.where(G > 0) | |
x = np.vstack((x[0], x[1])).transpose() | |
y = np.vstack((y[0], y[1])).transpose() | |
nbrs = NearestNeighbors(n_neighbors=1, algorithm='ball_tree').fit(x) | |
distances, indices = nbrs.kneighbors(y) | |
dist1 = np.max(distances) | |
nbrs = NearestNeighbors(n_neighbors=1, algorithm='ball_tree').fit(y) | |
distances, indices = nbrs.kneighbors(x) | |
dist2 = np.max(distances) | |
hausdorffDistance = np.max((dist1, dist2)) | |
return hausdorffDistance | |
def F1score(S=None, G=None): | |
S = np.array(S).astype(np.uint8) | |
G = np.array(G).astype(np.uint8) | |
listS = np.unique(S) | |
listS = np.delete(listS, np.where(listS == 0)) | |
numS = len(listS) | |
listG = np.unique(G) | |
listG = np.delete(listG, np.where(listG == 0)) | |
numG = len(listG) | |
if numS == 0 and numG == 0: | |
return 1 | |
elif numS == 0 or numG == 0: | |
return 0 | |
tempMat = np.zeros((numS, 3)) | |
tempMat[:, 0] = listS | |
for iSegmentedObj in range(numS): | |
intersectGTObjs = G[S == tempMat[iSegmentedObj, 0]] | |
if intersectGTObjs.any(): | |
intersectGTObjs_flat = np.delete(intersectGTObjs.flatten(), | |
np.where(intersectGTObjs.flatten() == 0)) | |
if len(intersectGTObjs_flat) == 0: maxGTi = 0 | |
else: maxGTi = stats.mode(intersectGTObjs_flat).mode | |
tempMat[iSegmentedObj, 1] = maxGTi | |
for iSegmentedObj in range(numS): | |
if tempMat[iSegmentedObj, 1] != 0: | |
SegObj = (S == tempMat[iSegmentedObj, 0]) | |
GTObj = (G == tempMat[iSegmentedObj, 1]) | |
overlap = np.logical_and(SegObj, GTObj) | |
areaOverlap = overlap.sum() | |
areaGTObj = GTObj.sum() | |
if areaOverlap / areaGTObj > 0.5: | |
tempMat[iSegmentedObj, 2] = 1 | |
TP = (tempMat[:, 2] == 1).sum() | |
FP = (tempMat[:, 2] == 0).sum() | |
FN = numG - TP | |
precision = TP / (TP + FP) | |
recall = TP / (TP + FN) | |
if precision + recall == 0: | |
return 0 | |
score = (2 * precision * recall) / (precision + recall) | |
return score | |
def ObjectDice(S, G): | |
S = np.array(S).astype(np.uint8) | |
G = np.array(G).astype(np.uint8) | |
totalAreaG = (G > 0).sum() | |
listLabelS = np.unique(S) | |
listLabelS = np.delete(listLabelS, np.where(listLabelS == 0)) | |
numS = len(listLabelS) | |
listLabelG = np.unique(G) | |
listLabelG = np.delete(listLabelG, np.where(listLabelG == 0)) | |
numG = len(listLabelG) | |
if numS == 0 and numG == 0: | |
return 1 | |
elif numS == 0 or numG == 0: | |
return 0 | |
temp1 = 0 | |
totalAreaS = (S > 0).sum() | |
for iLabelS in range(len(listLabelS)): | |
Si = (S == listLabelS[iLabelS]) | |
intersectlist = G[Si] | |
if intersectlist.any(): | |
indexG1 = stats.mode(intersectlist).mode | |
Gi = (G == indexG1) | |
else: | |
Gi = np.zeros(G.shape) | |
omegai = Si.sum() / totalAreaS | |
temp1 += omegai * Dice(Gi, Si) | |
temp2 = 0 | |
totalAreaG = (G > 0).sum() | |
for iLabelG in range(len(listLabelG)): | |
tildeGi = (G == listLabelG[iLabelG]) | |
intersectlist = S[tildeGi] | |
if intersectlist.any(): | |
indextildeSi = stats.mode(intersectlist).mode | |
tildeSi = (S == indextildeSi) | |
else: | |
tildeSi = np.zeros(S.shape) | |
tildeOmegai = tildeGi.sum() / totalAreaG | |
temp2 += tildeOmegai * Dice(tildeGi, tildeSi) | |
return (temp1 + temp2) / 2 | |
def Dice(A, B): | |
intersection = np.logical_and(A, B) | |
return 2. * intersection.sum() / (A.sum() + B.sum()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment