metric_similarity.py 4.57 KB
Newer Older
Jiri Borovec's avatar
Jiri Borovec committed
1 2 3 4 5 6
"""


Copyright (C) 2015-2016 Jiri Borovec <jiri.borovec@fel.cvut.cz>
"""

Jiri Borovec's avatar
Jiri Borovec committed
7
import logging
Jiri Borovec's avatar
Jiri Borovec committed
8 9

import numpy as np
Jiri Borovec's avatar
Jiri Borovec committed
10
from sklearn import metrics
Jiri Borovec's avatar
Jiri Borovec committed
11

Jiri Borovec's avatar
Jiri Borovec committed
12 13 14 15 16 17 18 19 20 21 22
logger = logging.getLogger(__name__)


def compare_atlas_rnd_pairs(a1, a2):
    """ compare two atlases as taking random pixels pairs from both
    and evaluate that the are labeled equally of differently

    :param a1: np.array<w, h>
    :param a2: np.array<w, h>
    :return: float with 0 means no difference
    """
Jiri Borovec's avatar
Jiri Borovec committed
23 24
    logger.debug('comparing two atlases of shapes %s <-> %s',
                 repr(a1.shape), repr(a2.shape))
Jiri Borovec's avatar
Jiri Borovec committed
25 26
    assert np.array_equal(a1.shape, a2.shape)
    # assert A1.shape[0]==A2.shape[0] and A1.shape[1]==A2.shape[1]
Jiri Borovec's avatar
Jiri Borovec committed
27 28 29 30
    logger.debug('unique labels are %s and %s', repr(np.unique(a1).tolist()),
                 repr(np.unique(a2).tolist()))
    matrix_x, matrix_y = np.meshgrid(range(a1.shape[0]), range(a1.shape[1]))
    vec_x, vec_y = matrix_x.flatten(), matrix_y.flatten()
Jiri Borovec's avatar
Jiri Borovec committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
    vec_x_perm = np.random.permutation(vec_x)
    vec_y_perm = np.random.permutation(vec_y)
    diffs = 0
    for x1, y1, x2, y2 in zip(vec_x, vec_y, vec_x_perm, vec_y_perm):
        b1 = a1[x1, y1] == a1[x2, y2]
        b2 = a2[x1, y1] == a2[x2, y2]
        if not b1 == b2: # T&F or F&T
            # logger.debug('coords [{},{}], [{},{}] gives vals: {}, {}'.format(x1, y1, x2, y2, b1, b2))
            # logger.debug('diff: {}?={} and {}?={}'.format(A1[x1,y1], A1[x2,y2], A2[x1,y1], A2[x2,y2]))
            diffs += 1
    res = diffs / float(len(vec_x))
    return res


# Rand index, o tom uz jsme mluvili.
# Ted jde jen o to, jak tento index vypocitat efektivne. Coz, kdyz si
# rozmyslite, neni prilis tezke: udelate kontingencni tabulku=histogram, tedy oznacime n_ij kolik pixelu na stejnych
# souradnicich patri do tridy 'i'v prvnim obrazku a do tridy 'j' v druhem. Pak pocet shod(dva prvky jsou ve strejne
# tride v prvnim obrazku a ve stejne tride v druhem, nebo jsou v ruznych tridach v prvnim i v druhem) lze vyjadrit
# z histogramu - viz vzorec(1), clanek http://link.springer.com/article/10.1007%2FBF01908075
#
# Existuje i Adjusted Random Index, viz stejny clanek, nebo taky https://en.wikipedia.org/wiki/Rand_index
# Pro nase ucely je to asi jedno, proto budeme chtit jen porovnavat metody mezi sebou.


def compare_atlas_adjusted_rand(a1, a2):
    """ using adjusted rand and transform original values from (-1, 1) to (0, 1)
    http://scikit-learn.org/stable/modules/generated/sklearn.metrics.adjusted_rand_score.html

    :param a1: np.array<w, h>
    :param a2: np.array<w, h>
    :return: float with 0 means no difference
    """
    assert np.array_equal(a1.shape, a2.shape)
    ars = metrics.adjusted_rand_score(a1.ravel(), a2.ravel())
Jiri Borovec's avatar
Jiri Borovec committed
66
    res = 1 - abs(ars)
Jiri Borovec's avatar
Jiri Borovec committed
67 68 69 70 71 72 73 74 75
    return res


def overlap_matrix_mlabel_segm(seg1, seg2):
    """
    :param seg1: np.array<w, h>
    :param seg2: np.array<w, h>
    :return: np.array<w, h>
    """
Jiri Borovec's avatar
Jiri Borovec committed
76 77
    logger.debug('computing overlap of two segm of shapes %s <-> %s',
                 repr(seg1.shape), repr(seg2.shape))
Jiri Borovec's avatar
Jiri Borovec committed
78 79 80
    assert np.array_equal(seg1.shape, seg2.shape)
    u_lb1 = np.unique(seg1)
    u_lb2 = np.unique(seg2)
Jiri Borovec's avatar
Jiri Borovec committed
81 82 83
    u_lb1 = dict(zip(u_lb1, range(len(u_lb1))))
    u_lb2 = dict(zip(u_lb2, range(len(u_lb2))))
    logger.debug('unique labels:\n  %s\n  %s', repr(u_lb1), repr(u_lb2))
Jiri Borovec's avatar
Jiri Borovec committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    res = np.zeros([len(u_lb1), len(u_lb2)])
    for i in range(seg1.shape[0]):
        for j in range(seg1.shape[1]):
            u1, u2 = u_lb1[seg1[i, j]], u_lb2[seg2[i, j]]
            res[u1, u2] += 1
            res[u2, u1] += 1
    # logger.debug(res)
    return res


def compare_matrices(m1, m2):
    """
    :param m1: np.array<w, h>
    :param m2: np.array<w, h>
    :return: float
    """
    assert np.array_equal(m1.shape, m2.shape)
    diff = np.sum(abs(m1 - m2))
    return diff / float(np.product(m1.shape))


def compare_weights(c1, c2):
    """
    :param c1: np.array<w, h>
    :param c2: np.array<w, h>
    :return: float
    """
    return compare_matrices(c1, c2)


def test_atlases():
    """
    :return:
    """
    logger.info('testing METRIC')
    a = np.random.randint(0,4,(5,5))
    a2 = a.copy()
    a2[a2==0] = -1
    b = np.random.randint(0,4,(5,5))

Jiri Borovec's avatar
Jiri Borovec committed
124 125 126 127
    logger.debug('compare_atlas_rnd_pairs, a <-> a: %d', compare_atlas_rnd_pairs(a, a2))
    logger.debug('compare_atlas_rnd_pairs, a <-> b: %d', compare_atlas_rnd_pairs(a, b))
    logger.debug('compare_atlas_adjusted_rand, a <-> a: %d', compare_atlas_adjusted_rand(a, a2))
    logger.debug('compare_atlas_adjusted_rand, a <-> b: %d', compare_atlas_adjusted_rand(a, b))
Jiri Borovec's avatar
Jiri Borovec committed
128 129 130 131 132 133 134 135
    return None


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)

    test_atlases()

Jiri Borovec's avatar
Jiri Borovec committed
136
    logger.info('DONE')