Example #1
0
def match_parameters(p, q, method="munkres", discard_misses=False):
    """
    Match two sets of parameters.
    TODO: finish greedy
    """
    logger.info("Matching with method %s" % method)
    assert p.shape[1] == q.shape[1], (
        "Shapes do not match (%s vs %s)" % (p.shape, q.shape)
    )

    match_size = min(p.shape[0], q.shape[0])
    corrs = np.corrcoef(p, q)[match_size:, :match_size]
    corrs[np.isnan(corrs)] = 0

    if method == "munkres":
        m = Munkres()
        cl = 1 - np.abs(corrs)
        if (cl.shape[0] > cl.shape[1]):
            indices = m.compute(cl.T)
        else:
            indices = m.compute(cl)
            indices = [(i[1], i[0]) for i in indices]

    elif method == "greedy":
        q_idx = []
        raise NotImplementedError("Greedy not supported yet.")
        for c in range(q.shape[0]):
            idx = corrs[c, :].argmax()
            q_idx.append(idx)
            corrs[:,idx] = 0

    else:
        raise NotImplementedError("%s matching not supported" % method)

    return indices
Example #2
0
def Objmatch(objy,objx,ref,refc,L,W,im,length):
    global D_limit_s
    dmtx = np.zeros((L,W))
    cmtx = np.zeros((L,W))
    Wd = 0.5   #weight of distance
    Wc = 1-Wd  #weight of color
    
    for i in range(L):
        dmtx[i,:] =((objy - ref[i][0])**2+(objx - ref[i][1])**2).T
        cmtx[i,:] = Color_Dif(im,objx,objy,refc[i],length[i]) 

    dmtx = dmtx/diag # normalize the distance by divid diag
    dmtx[dmtx>D_limit_s] = 10**6    
    cmtx = cmtx*Wc + dmtx*Wd
    tmp = copy.deepcopy(cmtx)     
    m = Munkres()
    if L<=W:
        indexes = m.compute(cmtx)
    else:     # len(ori) > # live_blobs
        indexes = m.compute(cmtx.T)
        indexes = [(s[1],s[0]) for s in indexes]
    
    D_idx = []
    if vid_idx>=0:
        for i in range(len(indexes))[::-1]:
            if tmp[indexes[i][0],indexes[i][1]]>10**5:
                D_idx.append(i)
                indexes.pop(i)

    return indexes,D_idx  
Example #3
0
def fixColouringAndCompare(atk, btk):
    """
    15 April 2013
    input: atk, btk are clustering results
    output: btk['pattern'] and btk['centroids'][1] fixed
            returning the distanceSquaredMatrix and the indices
    """
    k = len(atk["centroids"][0])
    # k = a.k
    aClusters = [-999] * k  # initialising a length-k list for convenience
    bClusters = [-999] * k
    for i in range(k):
        # x-coord, y-coord, weight of the i-th cluster in a
        aClusters[i] = {
            "x": atk["centroids"][0][i][0],
            "y": atk["centroids"][0][i][1],
            "weight": len([v for v in atk["centroids"][1] if v == i]),
        }
        # doing the same for b
        bClusters[i] = {
            "x": btk["centroids"][0][i][0],
            "y": btk["centroids"][0][i][1],
            "weight": len([v for v in btk["centroids"][1] if v == i]),
        }
    distanceSquaredMatrix = np.ones((k, k)) * (-999.0)
    for i in range(k):
        for j in range(k):
            dist2 = (aClusters[i]["x"] - bClusters[j]["x"]) ** 2 + (aClusters[i]["y"] - bClusters[j]["y"]) ** 2
            # print i,j, dist2  #debug
            distanceSquaredMatrix[i, j] = dist2
    from munkres import Munkres

    m = Munkres()
    indices = m.compute(distanceSquaredMatrix.copy())  # munkres would alter the entries
    # indicies2=dict([(v[1], v[0]) for v in indices])
    indices2 = m.compute(distanceSquaredMatrix.copy().T)  # munkres would alter the entries
    indices2Dict = dict(indices2)
    # print indices2      #debug
    # print indices2Dict

    bData = btk["data"]
    bCentroids = btk["centroids"]
    for i in range(len(bCentroids[1])):
        newColour = indices2Dict[bCentroids[1][i]]
        btk["centroids"][1][i] = newColour
        btk["pattern"].matrix[bData[i][1], bData[i][0]] = newColour

    abCompare = {
        "distanceSquared": distanceSquaredMatrix,
        "indices": indices,
        "aClusters": aClusters,
        "bClusters": bClusters,
    }
    return abCompare
Example #4
0
def similar(list_current,list_called):
	global P,total
	# comparing the length of two files to compare smaller length to bigger 
	if len(list_current)<len(list_called):
		# calling comparison function to compare both files line by line for similarity 
		similarity = comparison(list_current,list_called)
		# storing the lenght of smaller 
		P = len(list_current)
		point=[[0 for x in range(len(list_called))] for y in range(len(list_current))]
	else:
		# calling comparison function to compare both files line by line for similarity
		similarity = comparison(list_called,list_current)
		P = len(list_called)
		point=[[0 for x in range(len(list_current))] for y in range(len(list_called))]
	# calling functions of munkres to form maximum weighted bipartite matching graph
	graph_matrix = make_cost_matrix(similarity, lambda cost: 1.0 - cost)
	m = Munkres()
	indexes =m.compute(graph_matrix)
	total = 0
	for row, column in indexes:
		# forming list of points(lines) of similarity between two files
		value = similarity[row][column]
		if value>0.0:
			total += 1
			point[row][column]=1
	return point
def hun(costMatrix):

    # Check first, if costmatrix is not empty
    if costMatrix.shape==(0,0):
        return []

    # Create squared temporary matrix
    tmpMatrix = numpy.copy(costMatrix)
    tmpMatrix = makeSquareWithNegValues(tmpMatrix)
    sqCostMatrix = numpy.copy(tmpMatrix)
    sqCostMatrix[tmpMatrix==-1]=10e10

    # Solve ASP on the temporary matrix
    m=Munkres()
    i=m.compute(sqCostMatrix)


    # Create resultin matrix that contains ones at matching
    # objects and remove all excluded matches
    binMatrix = numpy.zeros( tmpMatrix.shape,dtype=bool )
    for x,y in i:
        if tmpMatrix[x,y]==-1:
            continue
        binMatrix[x,y]=True

    return binMatrix
def __assign_labels_to_clusters__(assignment, labels, clusters, clusts_labels):
    cost_matrix = gen_assignment_cost_matrix(assignment, labels, clusters, clusts_labels)
    munkres = Munkres()
    assignment_list = munkres.compute(cost_matrix)
    # assignment_list = [(i,i) for i in xrange(len(clusters))] #for debugging
    assigned_clusts_labels = dict(assignment_list)  # dictionary {cluster_no: assigned_label_no}
    return assigned_clusts_labels
Example #7
0
def closest_permuted_matrix( A, B ):
    """Find a _row_ permutation of B that matches A most closely (i.e. min |A
    - B|_F)"""

    # The rows of A and B form a weighted bipartite graph. The weights
    # are computed using the vector_matching algorithm.
    # We need to find their minimal matching.
    assert( A.shape == B.shape )

    n, _ = A.shape
    m = Munkres()

    # Create the weight matrix
    W = sc.zeros( (n, n) )
    for i in xrange( n ):
        for j in xrange( n ):
            # Best matching between A and B
            W[i, j] = norm(A[i] - B[j])

    matching = m.compute( W )
    matching.sort()
    _, rowp = zip(*matching)
    rowp = array( rowp )
    # Permute the rows of B according to Bi
    B_ = B[ rowp ]

    return B_
 def match(self, model_manager):
     individuals = model_manager.individuals
     groups = model_manager.groups
     pref_matrix = []
     individual_count = len(individuals)        
     row_index = -1
     individuals_by_row = {}
     groups_by_col = {}
     for individual_id, individual in individuals.iteritems():
         row_index += 1
         individuals_by_row[str(row_index)] = individual
         pref_matrix_row = []
         col_index = -1
         for group_id, group in groups.iteritems():
             group_pref_value = individual.get_group_pref_value(group.id)
             # we use group slots to control the max number of individuals per group.  one individual per slot
             # each slot represents a potential membership within a group within the preference matrix. 
             # the len(pref_matrix_group_slots[grounp.id]) == min(group.max_size, len(individuals))
             group_slot_size = min(group.max_size, individual_count)
             for s in range(group_slot_size):
                 # multiply value by negative 1 because munkres finds
                 # the assignment with minimum net value, 
                 # and we want to find the assignment with
                 # maximum net value
                 pref_matrix_row.append(group_pref_value * -1)
                 col_index += 1
                 groups_by_col[str(col_index)] = group      
         pref_matrix.append(pref_matrix_row)  
     
     munkres = Munkres()
     optimal_match_indexes = munkres.compute(pref_matrix)
     assignments = [(individuals_by_row[str(row)], groups_by_col[str(col)]) for row, col in optimal_match_indexes]            
     return assignments
Example #9
0
def fix_parameters(true, guess, weights):
    """Find a column permutation of guess parameters that matches true parameters most closely (i.e. min |A
    - B|_F) also apply this to weights"""

    # The rows of A and B form a weighted bipartite graph. The weights
    # are computed using the vector_matching algorithm.
    # We need to find their minimal matching.
    assert true.shape == guess.shape

    d, k = true.shape
    m = Munkres()

    # Create the weight matrix
    W = sc.zeros((k, k))
    for i in xrange(k):
        for j in xrange(k):
            # Best matching between A and B
            W[i, j] = norm(true.T[i] - guess.T[j])

    matching = m.compute(W)
    matching.sort()
    _, colp = zip(*matching)
    colp = array(colp)
    # Permute the rows of B according to Bi
    guess = guess[:, colp]
    weights = weights[colp]

    return weights, guess
Example #10
0
def do_matching(gsrEvents, warnings):
    matrix = []

    M = len(gsrEvents)
    N = len(warnings)
    for m in range(M):
        row = []
        gsr = gsrEvents[m]
        for n in range(N):
            warn = warnings[n]
            if match(gsr, warn):
                row.append(get_quality(gsr, warn))
            else:
                row.append(.0)
        matrix.append(row)

    costMatrix = []
    #create the cost matrix
    for m in range(M):
        r = []
        gsr = gsrEvents[m]
        for n in range(N):
            warn = warnings[n]
            r.append(10 - matrix[m][n])
        costMatrix.append(r)

    m = Munkres()
    if M > 0 and N > 0:
        indexes = m.compute(costMatrix)
    else:
        return None, None

    return matrix, indexes
def loss1(usersPerCircle, usersPerCircleP):
  #psize: either the number of groundtruth, or the number of predicted circles (whichever is larger)
  psize = max(len(usersPerCircle),len(usersPerCircleP)) # Pad the matrix to be square
  # mm: matching matrix containing costs of matching groundtruth circles to predicted circles.
  #     mm[i][j] = cost of matching groundtruth circle i to predicted circle j
  mm = numpy.zeros((psize,psize))
  # mm2: copy of mm since the Munkres library destroys the data during computation
  mm2 = numpy.zeros((psize,psize))
  for i in range(psize):
    for j in range(psize):
      circleP = set() # Match to an empty circle (delete all users)
      circle = set() # Match to an empty circle (add all users)
      if (i < len(usersPerCircleP)):
        circleP = usersPerCircleP[i]
      if (j < len(usersPerCircle)):
        circle = usersPerCircle[j]
      nedits = len(circle.union(circleP)) - len(circle.intersection(circleP)) # Compute the edit distance between the two circles
      mm[i][j] = nedits
      mm2[i][j] = nedits

  if psize == 0:
    return 0 # Edge case in case there are no circles
  else:
    m = Munkres()
    #print mm2 # Print the pairwise cost matrix
    indices = m.compute(mm) # Compute the optimal alignment between predicted and groundtruth circles
    editCost = 0
    for row, column in indices:
      #print row,column # Print the optimal value selected by matching
      editCost += mm2[row][column]
    return int(editCost)
class HungarianMapper(BaseMapper):

    def __init__(self, cost=None):
        super(HungarianMapper, self).__init__(cost=cost)
        self._munkres = Munkres()

    def __call__(self, A, B):

        # Cooccurrence matrix
        matrix = self.cost(A, B)

        # Shape and labels
        nRows, nCols = matrix.shape
        rows = matrix.get_rows()
        cols = matrix.get_columns()

        # Cost matrix
        N = max(nCols, nRows)
        C = np.zeros((N, N))
        C[:nCols, :nRows] = (np.max(matrix.df.values) - matrix.df.values).T

        mapping = {}
        for b, a in self._munkres.compute(C):
            if (b < nCols) and (a < nRows):
                if matrix[rows[a], cols[b]] > 0:
                    mapping[rows[a]] = cols[b]

        return mapping
def getFileSim(fileA,fileB,alpha,beta):  	#to find the similarity of two files
	File1=open(dirname+'/'+fileA, "r")
	File2=open(dirname+'/'+fileB, "r")
	content1=File1.readlines()
	flag=0
	content2=File2.readlines()
	if len(content1) > len(content2):
		flag=1
		content1,content2 = content2,content1
	sim=[]
	for sen_A in content1:
		temp = []
		sen_A = sen_A.lower()
		for sen_B in content2:
			sen_B = sen_B.lower()
			temp.append(senSim(sen_A,sen_B,alpha))
		sim.append(temp)
	for i in range(len(sim))		 #to make it a maximum cost problem
		for j in range(len(sim[i])):
			sim[i][j] = 1.0-sim[i][j]
	m=Munkres()
	result_matrix=m.compute(sim)		#implementing hungarian 
	maxSimMatrix = []
	for row,column in result_matrix:
		if	sim[row][column]!=1.0:
			if flag==1:
				row,column=column,row
			maxSimMatrix.append([row,column])	#storing which lines are matched
	FileSim=float(len(maxSimMatrix))/(len(content1))
	
	if FileSim<beta:
		FileSim = 0
	return (FileSim, maxSimMatrix)
Example #14
0
    def __init__(self, G1, G2, nattr='weight', eattr='weight', lamb = 0.5):
        G1, G2 = sorted([G1, G2], key=lambda x: len(x))
        csim = gs.tacsim_combined_in_C(G1, G2, node_attribute=nattr, edge_attribute=eattr, lamb=lamb)
        self.csim = csim / np.sqrt(((csim * csim).sum())) # to ensure valid structural distance
        self.g1 = G1
        self.g2 = G2

        m = Munkres()
        cdist = (1 - self.csim).tolist()
        self.matching = m.compute(cdist)

        nmap = {}
        def _gen_nnid(node):
            if node not in nmap:
                nmap[node] = len(nmap)
            return nmap[node]

        self.mesos = nx.DiGraph()
        for (e1_idx, e2_idx) in self.matching:
            e1 = G1.edges()[e1_idx]
            e2 = G2.edges()[e2_idx]
            ns = _gen_nnid(e1[0])
            nt = _gen_nnid(e1[1])
            self.mesos.add_edge(ns, nt)
            self.mesos.edge[ns][nt][eattr] = 0.5 * (G1.edge[e1[0]][e1[1]][eattr] + G2.edge[e2[0]][e2[1]][eattr])
            self.mesos.node[ns][nattr] = 0.5 * (G1.node[e1[0]][nattr] + G2.node[e2[0]][nattr])
            self.mesos.node[nt][nattr] = 0.5 * (G1.node[e1[1]][nattr] + G2.node[e2[1]][nattr])
Example #15
0
def eval_result(labels, result_gen, cache_file):
    if path.exists(cache_file):
        print "Loading cached result..."
        with open(cache_file, "rb") as inf:
            lbl_clst = pickle.load(inf)
        print "Done."
    else:
        lbl_clst = result_gen()
        print "Saving result to cache..."
        with open(cache_file, "wb") as outf:
            pickle.dump(lbl_clst, outf)
        print "Done."
    all_langs = ["da", "de", "el", "en", "es", "fi", "fr", "it", "nl", "pt", "sv"]

    print "Constructing cost matrix..."
    nObj = len(labels)
    nLang = len(all_langs)
    G = [[0 for j in range(nLang)] for i in range(nLang)]
    for i in range(nLang):
        for j in range(nLang):
            G[i][j] = -sum([(lbl_clst[k] == i and labels[k] == all_langs[j]) for k in range(nObj)])
    print "Finding best mapping..."
    m = Munkres()
    idx = m.compute(G)
    print "Calculating accuracy..."
    total = 0
    for row, col in idx:
        total += G[row][col]
    accuracy = -total / float(nObj)
    print "Accuracy = %.4f" % accuracy
Example #16
0
def p345():
    A = [[  7, 53, 183, 439, 863, 497, 383, 563, 79, 973, 287, 63, 343, 169, 583],
        [627, 343, 773, 959, 943, 767, 473, 103, 699, 303, 957, 703, 583, 639, 913],
        [447, 283, 463, 29, 23, 487, 463, 993, 119, 883, 327, 493, 423, 159, 743],
        [217, 623, 3, 399, 853, 407, 103, 983, 89, 463, 290, 516, 212, 462, 350],
        [960, 376, 682, 962, 300, 780, 486, 502, 912, 800, 250, 346, 172, 812, 350],
        [870, 456, 192, 162, 593, 473, 915, 45, 989, 873, 823, 965, 425, 329, 803],
        [973, 965, 905, 919, 133, 673, 665, 235, 509, 613, 673, 815, 165, 992, 326],
        [322, 148, 972, 962, 286, 255, 941, 541, 265, 323, 925, 281, 601, 95, 973],
        [445, 721, 11, 525, 473, 65, 511, 164, 138, 672, 18, 428, 154, 448, 848],
        [414, 456, 310, 312, 798, 104, 566, 520, 302, 248, 694, 976, 430, 392, 198],
        [184, 829, 373, 181, 631, 101, 969, 613, 840, 740, 778, 458, 284, 760, 390],
        [821, 461, 843, 513, 17, 901, 711, 993, 293, 157, 274, 94, 192, 156, 574],
        [ 34, 124, 4, 878, 450, 476, 712, 914, 838, 669, 875, 299, 823, 329, 699],
        [815, 559, 813, 459, 522, 788, 168, 586, 966, 232, 308, 833, 251, 631, 107],
        [813, 883, 451, 509, 615, 77, 281, 613, 459, 205, 380, 274, 302, 35, 805]]

    for r in range(len(A)):
        for c in range(len(A[0])):
            A[r][c] *= -1

    from munkres import Munkres, print_matrix

    m = Munkres()
    indexes = m.compute(A)
    total = 0
    for row, column in indexes:
        value = A[row][column]
        total += value
    return -total
Example #17
0
def accuracy(labels_true, labels_pred):
    labels_true, labels_pred = check_clusterings(labels_true, labels_pred)
    n_samples = labels_true.shape[0]
    classes = np.unique(labels_true)
    clusters = np.unique(labels_pred)
    # Special limit cases: no clustering since the data is not split;
    # or trivial clustering where each document is assigned a unique cluster.
    # These are perfect matches hence return 1.0.
    if (classes.shape[0] == clusters.shape[0] == 1
            or classes.shape[0] == clusters.shape[0] == 0
            or classes.shape[0] == clusters.shape[0] == len(labels_true)):
        return 1.0
    
    # print "accuracy testing..."
    contingency = contingency_matrix(labels_true, labels_pred) #Type: <type 'numpy.ndarray'>:rows are clusters, cols are classes
    contingency = -contingency
    #print contingency
    contingency = contingency.tolist()
    m = Munkres() # Best mapping by using Kuhn-Munkres algorithm
    map_pairs = m.compute(contingency) #best match to find the minimum cost
    sum_value = 0
    for key,value in map_pairs:
        sum_value = sum_value + contingency[key][value]
    
    return float(-sum_value)/n_samples
Example #18
0
File: utils.py Project: kmwenja/ftm
def maximum_weight_bipartite(matrix):
    cost_matrix = make_cost_matrix(matrix, lambda cost: 100000 - cost)

    m = Munkres()
    indices = m.compute(cost_matrix)

    return indices
Example #19
0
    def get_suitability_score(customer_list, product_list):
        '''
        calculate the total maximum suitability score
        by using munkres algorithm and returns a detailed
        customer_product_enties & total suitability score
        '''
        suitability_scores = []
        customer_suitability_scores = []

        for customer in customer_list:
            for product in product_list:
                customer_suitability_scores.append(SuitabilityScore.calculate_suitability_score(customer,product))
            suitability_scores.append(customer_suitability_scores)
            customer_suitability_scores = []


        customer_product_entries = []
        cost_matrix = make_cost_matrix(suitability_scores, lambda cost: 1e10 - cost)
        munkres = Munkres()
        indexes = munkres.compute(cost_matrix)
        total_suitability_score = 0
        for customer_index, product_index  in indexes:
            suitability_score = suitability_scores[customer_index][product_index]
            total_suitability_score += suitability_score
            suitability_score_entry = SuitabilityScoreEntry(customer_list[customer_index],product_list[product_index],suitability_score)
            customer_product_entries.append(suitability_score_entry)
            #print(customer_index,product_index)

        return customer_product_entries,total_suitability_score
Example #20
0
File: align.py Project: borgr/ucca
def align(sen1, sen2):
	"""finds the best mapping of words from one sentence to the other"""
	#find lengths
	sen1 = list(map(preprocess_word, sen1.split()))
	sen2 = list(map(preprocess_word, sen2.split()))
	lengthDif = len(sen1) - len(sen2)
	if lengthDif > 0:
		shorter = sen2
		longer = sen1
	else:
		shorter = sen1
		longer = sen2
		lengthDif = abs(lengthDif)
	shorter += ["emptyWord"] * lengthDif

	#create matrix	
	matrix = np.zeros((len(longer), len(longer)))
	for i in range(len(longer)):
		for j in range(len(longer) - lengthDif):
			matrix[i,j] = distance.levenshtein(longer[i], shorter[j])
	print(matrix)
	
	#compare with munkres
	m = Munkres()
	indexes = m.compute(matrix)
	print("mapping is:",[(shorter[i], longer[j]) for (i,j) in indexes])
Example #21
0
def match(img_location, features, cluster):
    img = cv2.imread(img_location)

    detector = cv2.FeatureDetector_create("SIFT")
    descriptor = cv2.DescriptorExtractor_create("SIFT")
    
    keypoints = detector.detect(img)
    keypoints = sorted(keypoints, key=lambda x: -x.response)
    keypoints, img_features = descriptor.compute(img, keypoints[0:5])
    img_features = img_features.tolist()

    m = Munkres()

    distance = {}
    for filename in cluster:
        distance[filename] = 0
        fea = features[filename]
        matrix = [[0 for i in range(5)] for j in range(5)]
        for i in range(5):
            for j in range(5):
                if matrix[j][i] != 0:
                    matrix[i][j] = matrix[j][i]
                    continue
                try:
                    matrix[i][j] = np.linalg.norm( array(img_features[i]) - array(fea[j]) )
                except:
                    matrix[i][j] = 10000
        indexes = m.compute(matrix)
        for row, column in indexes:
            distance[filename] += matrix[row][column]

    results = sorted(cluster, key = lambda x: distance[x])
    # results = features.keys()
    return results, distance
def assign_projects():
    projects = Project.query.join(Priority).order_by(Project.id).all()
    users = User.query.join(Priority).order_by(User.id).all()
    user_ids = [user.id for user in users]
    default_priority = len(projects) + 1
    matrix = []

    for project in projects:
        priority_query = db.session.query(User.id, Priority.priority).\
            outerjoin(Priority, db.and_(User.id == Priority.user_id,
                                        Priority.project_id == project.id)).\
            filter(User.id.in_(user_ids)).\
            order_by(User.id).all()
        priorities = [user_priority_tuple.priority
                      if user_priority_tuple.priority is not None
                      else default_priority
                      for user_priority_tuple in priority_query]
        matrix.append(priorities)

    if len(matrix) != 0:
        db.session.query(Project).update({Project.assignee_id: None})
        m = Munkres()
        indexes = m.compute(matrix)
        for row, column in indexes:
            projects[row].assignee_id = user_ids[column]
        db.session.commit()

    flash('Project assignments updated.')
    return redirect(url_for('show_index'))
Example #23
0
def main(tutors, players):
  scores = []
  #create cross-scores
  for tutor in tutors:
    # create the score array for each tutor to every player
    scores.append([ getModFLF(tutor, player)*getBaseFLF(tutor,player) for player in players ])
  # print the matrix
  #pretty_print(scores)

  # find max
  maxscore = max(max(row) for row in scores)
  # turn the matrix into a min-problem
  for row in scores:
    for idx,col in enumerate(row):
      row[idx] = maxscore-col
  # using munkres (copy of tutorial)
  m = Munkres()
  indexes = m.compute(scores)

#  pretty_print(scores)
  total = 0
  print "[[Tutor ::: Player]]"
  for row, col in indexes:
    total += scores[row][col]
    print '{0} ::: {1}'.format(tutors[row],players[col])
  print 'total FLF: {0}'.format(maxscore*len(tutors)-total)
Example #24
0
 def find_ambiguous_mapping(self, res, aa,
                            non_ambiguous_mapping,
                            previous=False):
     from munkres import Munkres
     from numpy import fabs, sum, delete
     
     total_costs = None
     mapping = []
     ambiguous_keys = []
     ambiguous_shifts = []
     res_shifts, res_keys = res.get_carbons(previous)
     aa_shifts, aa_keys = aa.get_carbons()
     
     for i, j in non_ambiguous_mapping:
         if j in aa_keys:
             k = list(aa_keys).index(j)
             aa_shifts = delete(aa_shifts, k)
             aa_keys = delete(aa_keys, k)
     for i, key in enumerate(res_keys):
         if self.ambiguous(key, previous):
             ambiguous_keys.append(key)
             ambiguous_shifts.append(res_shifts[i])
             
     if len(aa_keys) > 0 and len(ambiguous_shifts) > 0:
         costs = fabs(subtract.outer(ambiguous_shifts, aa_shifts))
         munkres = Munkres()
         result = munkres.compute(costs * 1.)
         for i, j in result:
             mapping.append((ambiguous_keys[i], aa_keys[j]))
         
     return mapping
Example #25
0
    def evaluateFrame(self,X,Y, X_labels=None, Y_labels=None):
        """ Compute the OSPA metric between two sets of points. """
            
        # check for empty sets
        if numpy.size(X) == 0 and numpy.size(Y) == 0:
            return (0,0,0,0)
        elif numpy.size(X) == 0 or numpy.size(Y) == 0 :
            return (self.c,0,self.c, 0)
            
        # we assume that Y is the larger set
        m = numpy.size(X,0) 
        n = numpy.size(Y,0)
        switched = False
        if m > n:
            X,Y = Y,X
            m,n = n,m 
            switched = True       

        dists = self.calculateCostMatrix(X,Y)
        # Copy cost matrix for munkres module
        munkres_matrix = numpy.copy(dists)
        # Only run munkres on non-empty matrix
        if len(munkres_matrix) > 0:
            munkres = Munkres()
            indices = munkres.compute(munkres_matrix)
        else:
            indices = []
                
        # compute the OSPA metric
        total = 0 
        total_loc = 0
        for [i,j] in indices:
            total_loc += dists[i][j]**self.p
        # calculate cardinalization error
        err_cn = (float((self.c)**(self.p)*(n-m))/n)**(1/float(self.p))
        # calculate localization error
        err_loc = (float(total_loc)/n)**(1/float(self.p)) 

        # Not contained in version from github implemented 
        # acc. to paper "A Metric for Performance Evaluation of Multi-Target Tracking Algorithms"
        # Implementation of labeling error
        # Penalizes ID switches from frame to frame
        new_assignments = []
        for [i,j] in indices:
            if (switched):
                i,j = j,i
            new_assignments.append((X_labels[i], Y_labels[j]))
        wrong_labels =len(self.old_assignments) - len(set(new_assignments) & set(self.old_assignments))
        rospy.loginfo(wrong_labels)
        err_label = (float((float(self.a)**float(self.p))/n)*wrong_labels) **(1/float(self.p)) 
        # store current assignments of labels to track
        self.old_assignments = new_assignments
        #ospa_err = ( float(total_loc + (n-m)*self.c**self.p) / n)**(1/float(self.p))
        ospa_err = ( float(total_loc + self.a*wrong_labels + (n-m)*self.c**self.p) / n)**(1/float(self.p))
        ospa_tuple = (ospa_err,err_loc,err_cn, err_label) 

        rospy.loginfo(ospa_tuple)

        return ospa_tuple
def hungarian_mapping(inames, cnames, target, base):
    """
    Utilizes the hungarian/munkres matching algorithm to compute an initial
    mapping of inames to cnames. The base cost is the expected correct guesses
    if each object is matched to itself (i.e., a new object). Then the cost of
    each object-object match is evaluated by setting each individual object and
    computing the expected correct guesses.

    :param inames: the target component names
    :type inames: collection
    :param cnames: the base component names
    :type cnames: collection
    :param target: An instance or concept.av_counts object to be mapped to the
        base concept.
    :type target: :ref:`Instance<instance-rep>` or av_counts obj from concept
    :param base: A concept to map the target to
    :type base: TrestleNode
    :return: a mapping for renaming components in the instance.
    :rtype: frozenset

    """
    cnames = list(cnames)
    inames = list(inames)

    cost_matrix = []
    for o in inames:
        row = []
        for c in cnames:
            nm = {}
            nm[o] = c
            cost = mapping_cost({o: c}, target, base)
            row.append(cost)
        unmapped_cost = mapping_cost({}, target, base)
        for other_o in inames:
            if other_o == o:
                row.append(unmapped_cost)
            else:
                row.append(float('inf'))
        cost_matrix.append(row)

    m = Munkres()
    indices = m.compute(cost_matrix)

    # comments for using scipy hungarian
    # indices = linear_sum_assignment(cost_matrix)

    mapping = {}

    # for i in range(len(indices[0])):
    #     row = indices[0][i]
    #     col = indices[1][i]

    for row, col in indices:
        if col >= len(cnames):
            mapping[inames[row]] = inames[row]
        else:
            mapping[inames[row]] = cnames[col]

    return frozenset(mapping.items())
def execute_munkres(matrix):
    m = Munkres()
    points = m.compute(matrix)
    result = 0
    for point in points:
        result += matrix[point[0]][point[1]]

    return result
Example #28
0
 def _round(self, matrix):
     m = Munkres()
     lists = self.matrix_to_lists(matrix)
     indexes = m.compute(lists)
     matrix *= 0
     for row, column in indexes:
         matrix[row, column] = 1
     return matrix
Example #29
0
def match_labels(contingency_table):
    """Attempt to match the labels between ground truth and prediction using
    Hungarian algorithm. Extra prediction labels are moved to the right most
    columns.
    """
    m = Munkres()
    ind = m.compute(cost_matrix(contingency_table.as_matrix()))
    return rearrange_columns(ind, contingency_table.copy())
Example #30
0
    def allocate(self):
        from debate.models import AdjudicatorAllocation

        # remove trainees
        self.adjudicators = filter(lambda a: a.score > self.MIN_SCORE, self.adjudicators)

        # sort adjudicators and debates in descending score/importance
        self.adjudicators_sorted = list(self.adjudicators)
        self.adjudicators_sorted.sort(key=lambda a: a.score, reverse=True)
        self.debates_sorted = list(self.debates)
        self.debates_sorted.sort(key=lambda a: a.importance, reverse=True)

        n_adjudicators = len(self.adjudicators)
        n_debates = len(self.debates)

        n_solos = n_debates - (n_adjudicators - n_debates)/2

        # get adjudicators that can adjudicate solo
        chairs = self.adjudicators_sorted[:n_solos]
        #chairs = [a for a in self.adjudicators_sorted if a.score >
        #          self.CHAIR_CUTOFF]

        # get debates that will be judged by solo adjudicators
        chair_debates = self.debates_sorted[:len(chairs)]

        panel_debates = self.debates_sorted[len(chairs):]
        panellists = [a for a in self.adjudicators_sorted if a not in chairs]

        assert len(panel_debates) * 3 <= len(panellists)


        print "costing chairs"

        n = len(chairs)

        cost_matrix = [[0] * n for i in range(n)]

        for i, debate in enumerate(chair_debates):
            for j, adj in enumerate(chairs):
                cost_matrix[i][j] = self.calc_cost(debate, adj)

        print "optimizing"

        m = Munkres()
        indexes = m.compute(cost_matrix)

        total_cost = 0
        for r, c in indexes:
            total_cost += cost_matrix[r][c]

        print 'total cost for solos', total_cost
        print 'number of solo debates', n

        result = ((chair_debates[i], chairs[j]) for i, j in indexes if i <
                  len(chair_debates))
        alloc = [AdjudicatorAllocation(d, c) for d, c in result]

        print [(a.debate, a.chair) for a in alloc]
Example #31
0
def get_order(params, tile_struct, tilesegmentlists, exposurelist, observatory, config_struct):
    '''
    tile_struct: dictionary. key -> struct info. 
    tilesegmentlists: list of lists. Segments for each tile in tile_struct 
        that are available for observation.
    exposurelist: list of segments that the telescope is supposed to be working.
        consecutive segments from the start to the end, with each segment size
        being the exposure time.
    Returns a list of tile indices in the order of observation.
    '''
    keys = tile_struct.keys()

    exposureids_tiles = {}
    first_exposure = np.inf*np.ones((len(keys),))
    last_exposure = -np.inf*np.ones((len(keys),))
    tileprobs = np.zeros((len(keys),))
    tilenexps = np.zeros((len(keys),))
    tileexptime = np.zeros((len(keys),))
    tilefilts = {}
    tileavailable = np.zeros((len(keys),))
    tileavailable_tiles = {} 
    keynames = []

    nexps = 0
    for jj, key in enumerate(keys):
        tileprobs[jj] = tile_struct[key]["prob"]
        tilenexps[jj] = tile_struct[key]["nexposures"]
        tilefilts[key] = copy.deepcopy(tile_struct[key]["filt"])
        tileavailable_tiles[jj] = []
        keynames.append(key) 

        nexps = nexps + tile_struct[key]["nexposures"]

    if "dec_constraint" in config_struct:
        dec_constraint = config_struct["dec_constraint"].split(",")
        dec_min = float(dec_constraint[0])
        dec_max = float(dec_constraint[1])

    for ii in range(len(exposurelist)):
        exposureids_tiles[ii] = {}
        exposureids = []
        probs = []
        ras, decs = [], []
        for jj, key in enumerate(keys):
            tilesegmentlist = tilesegmentlists[jj]
            if tile_struct[key]["prob"] == 0: continue
            if "dec_constraint" in config_struct:
                if (tile_struct[key]["dec"] < dec_min) or (tile_struct[key]["dec"] > dec_max): continue
            if "epochs" in tile_struct[key]:
                if np.any(np.abs(exposurelist[ii][0]-tile_struct[key]["epochs"][:,2]) < params["mindiff"]/86400.0):
                    continue
            if tilesegmentlist.intersects_segment(exposurelist[ii]):
                exposureids.append(key)
                probs.append(tile_struct[key]["prob"])
                ras.append(tile_struct[key]["ra"])
                decs.append(tile_struct[key]["dec"])

                first_exposure[jj] = np.min([first_exposure[jj],ii])
                last_exposure[jj] = np.max([last_exposure[jj],ii])
                tileavailable_tiles[jj].append(ii)
                tileavailable[jj] = tileavailable[jj] + 1
        # in every exposure, the tiles available for observation
        exposureids_tiles[ii]["exposureids"] = exposureids # list of tile ids
        exposureids_tiles[ii]["probs"] = probs # the corresponding probs
        exposureids_tiles[ii]["ras"] = ras
        exposureids_tiles[ii]["decs"] = decs

    exposureids = []
    probs = []
    ras, decs = [], []
    for ii, key in enumerate(keys):
        # tile_struct[key]["nexposures"]: the number of exposures assigned to this tile
        for jj in range(tile_struct[key]["nexposures"]): 
            exposureids.append(key) # list of tile ids for every exposure it is allocated to observe
            probs.append(tile_struct[key]["prob"])
            ras.append(tile_struct[key]["ra"])
            decs.append(tile_struct[key]["dec"])

    idxs = -1*np.ones((len(exposureids_tiles.keys()),))
    filts = ['n'] * len(exposureids_tiles.keys())

    if nexps == 0:
        return idxs, filts    

    if params["scheduleType"] == "airmass_weighted":

        # # first step is to sort the array in order of descending probability
        indsort = np.argsort(-np.array(probs))
        probs = np.array(probs)[indsort]
        ras = np.array(ras)[indsort]
        decs = np.array(decs)[indsort]
        exposureids = np.array(exposureids)[indsort] 

        tilematrix = np.zeros((len(exposurelist), len(ras)))
        probmatrix = np.zeros((len(exposurelist), len(ras)))

        for ii in np.arange(len(exposurelist)):

            # first, create an array of airmass-weighted probabilities
            t = Time(exposurelist[ii][0], format='mjd')
            altaz = get_altaz_tiles(ras, decs, observatory, t)
            alts = altaz.alt.degree
            horizon = config_struct["horizon"]
            horizon_mask = alts <= horizon
            airmass = 1 / np.cos((90. - alts) * np.pi / 180.)
            below_horizon_mask = horizon_mask * 10.**100
            airmass = airmass + below_horizon_mask
            airmass_weight = 10 ** (0.4 * 0.1 * (airmass - 1) )
            tilematrix[ii, :] = np.array(probs/airmass_weight)
            probmatrix[ii, :] = np.array(probs * (True^horizon_mask))



    if params["scheduleType"] == "greedy":
        for ii in np.arange(len(exposurelist)): 
            exptimecheck = np.where(exposurelist[ii][0]-tileexptime <
                                    params["mindiff"]/86400.0)[0]
            exptimecheckkeys = [keynames[x] for x in exptimecheck]

            # find_tile finds the tile that covers the largest probablity
            # restricted by availability of tile and timeallocation
            idx2, exposureids, probs = find_tile(exposureids_tiles[ii],exposureids,probs,exptimecheckkeys=exptimecheckkeys)
            if idx2 in keynames:
                idx = keynames.index(idx2)
                tilenexps[idx] = tilenexps[idx] - 1
                tileexptime[idx] = exposurelist[ii][0]
                if len(tilefilts[idx2]) > 0:
                    filt = tilefilts[idx2].pop(0)
                    filts[ii] = filt
            idxs[ii] = idx2

            if not exposureids: break
    elif params["scheduleType"] == "greedy_slew":
        current_ra, current_dec = np.nan, np.nan
        for ii in np.arange(len(exposurelist)):
            exptimecheck = np.where(exposurelist[ii][0]-tileexptime <
                                    params["mindiff"]/86400.0)[0]
            exptimecheckkeys = [keynames[x] for x in exptimecheck]

            # find_tile finds the tile that covers the largest probablity
            # restricted by availability of tile and timeallocation
            idx2, exposureids, probs = find_tile(exposureids_tiles[ii],exposureids,probs,exptimecheckkeys=exptimecheckkeys,current_ra=current_ra,current_dec=current_dec,slew_rate=config_struct['slew_rate'],readout=config_struct['readout'])
            if idx2 in keynames:
                idx = keynames.index(idx2)
                tilenexps[idx] = tilenexps[idx] - 1
                tileexptime[idx] = exposurelist[ii][0]
                if len(tilefilts[idx2]) > 0:
                    filt = tilefilts[idx2].pop(0)
                    filts[ii] = filt
                current_ra = tile_struct[idx2]["ra"]
                current_dec = tile_struct[idx2]["dec"]

            idxs[ii] = idx2

            if not exposureids: break
    elif params["scheduleType"] == "sear":
        #for ii in np.arange(len(exposurelist)):
        iis = np.arange(len(exposurelist)).tolist()
        while len(iis) > 0: 
            ii = iis[0]
            mask = np.where((ii == last_exposure) & (tilenexps > 0))[0]

            exptimecheck = np.where(exposurelist[ii][0]-tileexptime <
                                    params["mindiff"]/86400.0)[0]
            exptimecheckkeys = [keynames[x] for x in exptimecheck]

            if len(mask) > 0:
                idxsort = mask[np.argsort(tileprobs[mask])]
                idx2, exposureids, probs = find_tile(exposureids_tiles[ii],exposureids,probs,idxs=idxsort,exptimecheckkeys=exptimecheckkeys) 
                last_exposure[mask] = last_exposure[mask] + 1
            else:
                idx2, exposureids, probs = find_tile(exposureids_tiles[ii],exposureids,probs,exptimecheckkeys=exptimecheckkeys)
            if idx2 in keynames:
                idx = keynames.index(idx2)
                tilenexps[idx] = tilenexps[idx] - 1
                tileexptime[idx] = exposurelist[ii][0]
                if len(tilefilts[idx2]) > 0:
                    filt = tilefilts[idx2].pop(0)
                    filts[ii] = filt
            idxs[ii] = idx2 
            iis.pop(0)

            if not exposureids: break

    elif params["scheduleType"] == "weighted":
        for ii in np.arange(len(exposurelist)):
            jj = exposureids_tiles[ii]["exposureids"]
            weights = tileprobs[jj] * tilenexps[jj] / tileavailable[jj]
            weights[~np.isfinite(weights)] = 0.0

            exptimecheck = np.where(exposurelist[ii][0]-tileexptime <
                                    params["mindiff"]/86400.0)[0]
            weights[exptimecheck] = 0.0

            if np.any(weights >= 0):
                idxmax = np.argmax(weights)
                idx2 = jj[idxmax]
                if idx2 in keynames:
                    idx = keynames.index(idx2)
                    tilenexps[idx] = tilenexps[idx] - 1
                    tileexptime[idx] = exposurelist[ii][0]
                    if len(tilefilts[idx2]) > 0:
                        filt = tilefilts[idx2].pop(0)
                        filts[ii] = filt
                idxs[ii] = idx2
            tileavailable[jj] = tileavailable[jj] - 1  

    elif params["scheduleType"] == "airmass_weighted":
        # then use the Hungarian algorithm (munkres) to schedule high prob tiles at low airmass
        tilematrix_mask = tilematrix > 10**(-10)

        if tilematrix_mask.any():
            print("Calculating Hungarian solution...")
            total_cost = 0
            cost_matrix = make_cost_matrix(tilematrix)
            m = Munkres()
            optimal_points = m.compute(cost_matrix)
            print("Hungarian solution calculated...")
            max_no_observ = min(tilematrix.shape)
            for jj in range(max_no_observ):
                idx0, idx1 = optimal_points[jj]
                # idx0 indexes over the time windows, idx1 indexes over the probabilities
                # idx2 gets the exposure id of the tile, used to assign tileexptime and tilenexps
                try:
                    idx2 = exposureids[idx1]
                    pamw = tilematrix[idx0][idx1]
                    total_cost += pamw
                    if len(tilefilts[idx2]) > 0:
                        filt = tilefilts[idx2].pop(0)
                        filts[idx0] = filt
                except: continue

                idxs[idx0] = idx2

        else: print("The localization is not visible from the site.")

    else:
        raise ValueError("Scheduling options are greedy/sear/weighted/airmass_weighted, or with _slew.")

    return idxs, filts
Example #32
0
    def compute3rdPartyMetrics(self):
        """
            Computes the metrics defined in
                - Stiefelhagen 2008: Evaluating Multiple Object Tracking Performance: The CLEAR MOT Metrics
                  MOTA, MOTAL, MOTP
                - Nevatia 2008: Global Data Association for Multi-Object Tracking Using Network Flows
                  MT/PT/ML
        """

        # construct Munkres object for Hungarian Method association
        hm = Munkres()
        max_cost = 1e9

        # go through all frames and associate ground truth and tracker results
        # groundtruth and tracker contain lists for every single frame containing lists of KITTI format detections
        fr, ids = 0, 0
        for seq_idx in range(len(self.groundtruth)):
            seq_gt = self.groundtruth[seq_idx]
            seq_dc = self.dcareas[seq_idx]  # don't care areas
            seq_tracker = self.tracker[seq_idx]
            seq_trajectories = defaultdict(list)
            seq_ignored = defaultdict(list)

            # statistics over the current sequence, check the corresponding
            # variable comments in __init__ to get their meaning
            seqtp = 0
            seqitp = 0
            seqfn = 0
            seqifn = 0
            seqfp = 0
            seqigt = 0
            seqitr = 0

            last_ids = [[], []]

            n_gts = 0
            n_trs = 0

            for f in range(len(seq_gt)):
                g = seq_gt[f]
                dc = seq_dc[f]

                t = seq_tracker[f]
                # counting total number of ground truth and tracker objects
                self.n_gt += len(g)
                self.n_tr += len(t)

                n_gts += len(g)
                n_trs += len(t)

                # use hungarian method to associate, using boxoverlap 0..1 as cost
                # build cost matrix
                cost_matrix = []
                this_ids = [[], []]
                for gg in g:
                    # save current ids
                    this_ids[0].append(gg.track_id)
                    this_ids[1].append(-1)
                    gg.tracker = -1
                    gg.id_switch = 0
                    gg.fragmentation = 0
                    cost_row = []
                    for tt in t:
                        # overlap == 1 is cost ==0
                        c = 1 - self.boxoverlap(gg, tt)
                        # gating for boxoverlap
                        if c <= self.min_overlap:
                            cost_row.append(c)
                        else:
                            cost_row.append(max_cost)  # = 1e9
                    cost_matrix.append(cost_row)
                    # all ground truth trajectories are initially not associated
                    # extend groundtruth trajectories lists (merge lists)
                    seq_trajectories[gg.track_id].append(-1)
                    seq_ignored[gg.track_id].append(False)

                if len(g) is 0:
                    cost_matrix = [[]]
                # associate
                association_matrix = hm.compute(cost_matrix)

                # tmp variables for sanity checks and MODP computation
                tmptp = 0
                tmpfp = 0
                tmpfn = 0
                tmpc = 0  # this will sum up the overlaps for all true positives
                tmpcs = [0] * len(
                    g)  # this will save the overlaps for all true positives
                # the reason is that some true positives might be ignored
                # later such that the corrsponding overlaps can
                # be subtracted from tmpc for MODP computation

                # mapping for tracker ids and ground truth ids
                for row, col in association_matrix:
                    # apply gating on boxoverlap
                    c = cost_matrix[row][col]
                    if c < max_cost:
                        g[row].tracker = t[col].track_id
                        this_ids[1][row] = t[col].track_id
                        t[col].valid = True
                        g[row].distance = c
                        self.total_cost += 1 - c
                        tmpc += 1 - c
                        tmpcs[row] = 1 - c
                        seq_trajectories[g[row].track_id][-1] = t[col].track_id

                        # true positives are only valid associations
                        self.tp += 1
                        tmptp += 1
                    else:
                        g[row].tracker = -1
                        self.fn += 1
                        tmpfn += 1

                # associate tracker and DontCare areas
                # ignore tracker in neighboring classes
                nignoredtracker = 0  # number of ignored tracker detections
                ignoredtrackers = dict()  # will associate the track_id with -1
                # if it is not ignored and 1 if it is
                # ignored;
                # this is used to avoid double counting ignored
                # cases, see the next loop

                for tt in t:
                    ignoredtrackers[tt.track_id] = -1
                    # ignore detection if it belongs to a neighboring class or is
                    # smaller or equal to the minimum height

                    tt_height = abs(tt.y1 - tt.y2)
                    if ((self.cls == "car" and tt.obj_type == "van") or
                        (self.cls == "pedestrian"
                         and tt.obj_type == "person_sitting")
                            or tt_height <= self.min_height) and not tt.valid:
                        nignoredtracker += 1
                        tt.ignored = True
                        ignoredtrackers[tt.track_id] = 1
                        continue
                    for d in dc:
                        overlap = self.boxoverlap(tt, d, "a")
                        if overlap > 0.5 and not tt.valid:
                            tt.ignored = True
                            nignoredtracker += 1
                            ignoredtrackers[tt.track_id] = 1
                            break

                # check for ignored FN/TP (truncation or neighboring object class)
                ignoredfn = 0  # the number of ignored false negatives
                nignoredtp = 0  # the number of ignored true positives
                nignoredpairs = 0  # the number of ignored pairs, i.e. a true positive
                # which is ignored but where the associated tracker
                # detection has already been ignored

                gi = 0
                for gg in g:
                    if gg.tracker < 0:
                        if gg.occlusion>self.max_occlusion or gg.truncation>self.max_truncation\
                                or (self.cls=="car" and gg.obj_type=="van") or (self.cls=="pedestrian" and gg.obj_type=="person_sitting"):
                            seq_ignored[gg.track_id][-1] = True
                            gg.ignored = True
                            ignoredfn += 1

                    elif gg.tracker >= 0:
                        if gg.occlusion>self.max_occlusion or gg.truncation>self.max_truncation\
                                or (self.cls=="car" and gg.obj_type=="van") or (self.cls=="pedestrian" and gg.obj_type=="person_sitting"):

                            seq_ignored[gg.track_id][-1] = True
                            gg.ignored = True
                            nignoredtp += 1

                            # if the associated tracker detection is already ignored,
                            # we want to avoid double counting ignored detections
                            if ignoredtrackers[gg.tracker] > 0:
                                nignoredpairs += 1

                            # for computing MODP, the overlaps from ignored detections
                            # are subtracted
                            tmpc -= tmpcs[gi]
                    gi += 1

                # the below might be confusion, check the comments in __init__
                # to see what the individual statistics represent

                # correct TP by number of ignored TP due to truncation
                # ignored TP are shown as tracked in visualization
                tmptp -= nignoredtp

                # count the number of ignored true positives
                self.itp += nignoredtp

                # adjust the number of ground truth objects considered
                self.n_gt -= (ignoredfn + nignoredtp)

                # count the number of ignored ground truth objects
                self.n_igt += ignoredfn + nignoredtp

                # count the number of ignored tracker objects
                self.n_itr += nignoredtracker

                # count the number of ignored pairs, i.e. associated tracker and
                # ground truth objects that are both ignored
                self.n_igttr += nignoredpairs

                # false negatives = associated gt bboxes exceding association threshold + non-associated gt bboxes
                #
                tmpfn += len(g) - len(association_matrix) - ignoredfn
                self.fn += len(g) - len(association_matrix) - ignoredfn
                self.ifn += ignoredfn

                # false positives = tracker bboxes - associated tracker bboxes
                # mismatches (mme_t)
                tmpfp += len(
                    t) - tmptp - nignoredtracker - nignoredtp + nignoredpairs
                self.fp += len(
                    t) - tmptp - nignoredtracker - nignoredtp + nignoredpairs
                #tmpfp   = len(t) - tmptp - nignoredtp # == len(t) - (tp - ignoredtp) - ignoredtp
                #self.fp += len(t) - tmptp - nignoredtp

                # update sequence data
                seqtp += tmptp
                seqitp += nignoredtp
                seqfp += tmpfp
                seqfn += tmpfn
                seqifn += ignoredfn
                seqigt += ignoredfn + nignoredtp
                seqitr += nignoredtracker

                # sanity checks
                # - the number of true positives minues ignored true positives
                #   should be greater or equal to 0
                # - the number of false negatives should be greater or equal to 0
                # - the number of false positives needs to be greater or equal to 0
                #   otherwise ignored detections might be counted double
                # - the number of counted true positives (plus ignored ones)
                #   and the number of counted false negatives (plus ignored ones)
                #   should match the total number of ground truth objects
                # - the number of counted true positives (plus ignored ones)
                #   and the number of counted false positives
                #   plus the number of ignored tracker detections should
                #   match the total number of tracker detections; note that
                #   nignoredpairs is subtracted here to avoid double counting
                #   of ignored detection sin nignoredtp and nignoredtracker
                if tmptp < 0:
                    print(tmptp, nignoredtp)
                    raise NameError("Something went wrong! TP is negative")
                if tmpfn < 0:
                    print(tmpfn, len(g), len(association_matrix), ignoredfn,
                          nignoredpairs)
                    raise NameError("Something went wrong! FN is negative")
                if tmpfp < 0:
                    print(tmpfp, len(t), tmptp, nignoredtracker, nignoredtp,
                          nignoredpairs)
                    raise NameError("Something went wrong! FP is negative")
                if tmptp + tmpfn is not len(g) - ignoredfn - nignoredtp:
                    print("seqidx", seq_idx)
                    print("frame ", f)
                    print("TP    ", tmptp)
                    print("FN    ", tmpfn)
                    print("FP    ", tmpfp)
                    print("nGT   ", len(g))
                    print("nAss  ", len(association_matrix))
                    print("ign GT", ignoredfn)
                    print("ign TP", nignoredtp)
                    raise NameError(
                        "Something went wrong! nGroundtruth is not TP+FN")
                if tmptp + tmpfp + nignoredtp + nignoredtracker - nignoredpairs is not len(
                        t):
                    print(seq_idx, f, len(t), tmptp, tmpfp)
                    print(len(association_matrix), association_matrix)
                    raise NameError(
                        "Something went wrong! nTracker is not TP+FP")

                # check for id switches or fragmentations
                for i, tt in enumerate(this_ids[0]):
                    if tt in last_ids[0]:
                        idx = last_ids[0].index(tt)
                        tid = this_ids[1][i]
                        lid = last_ids[1][idx]
                        if tid != lid and lid != -1 and tid != -1:
                            if g[i].truncation < self.max_truncation:
                                g[i].id_switch = 1
                                ids += 1
                        if tid != lid and lid != -1:
                            if g[i].truncation < self.max_truncation:
                                g[i].fragmentation = 1
                                fr += 1

                # save current index
                last_ids = this_ids
                # compute MOTP_t
                MODP_t = 1
                if tmptp != 0:
                    MODP_t = tmpc / float(tmptp)
                self.MODP_t.append(MODP_t)

            # remove empty lists for current gt trajectories
            self.gt_trajectories[seq_idx] = seq_trajectories
            self.ign_trajectories[seq_idx] = seq_ignored

            # gather statistics for "per sequence" statistics.
            self.n_gts.append(n_gts)
            self.n_trs.append(n_trs)
            self.tps.append(seqtp)
            self.itps.append(seqitp)
            self.fps.append(seqfp)
            self.fns.append(seqfn)
            self.ifns.append(seqifn)
            self.n_igts.append(seqigt)
            self.n_itrs.append(seqitr)

        # compute MT/PT/ML, fragments, idswitches for all groundtruth trajectories
        n_ignored_tr_total = 0
        for seq_idx, (seq_trajectories, seq_ignored) in enumerate(
                zip(self.gt_trajectories, self.ign_trajectories)):
            if len(seq_trajectories) == 0:
                continue
            tmpMT, tmpML, tmpPT, tmpId_switches, tmpFragments = [0] * 5
            n_ignored_tr = 0
            for g, ign_g in zip(seq_trajectories.values(),
                                seq_ignored.values()):
                # all frames of this gt trajectory are ignored
                if all(ign_g):
                    n_ignored_tr += 1
                    n_ignored_tr_total += 1
                    continue
                # all frames of this gt trajectory are not assigned to any detections
                if all([this == -1 for this in g]):
                    tmpML += 1
                    self.ML += 1
                    continue
                # compute tracked frames in trajectory
                last_id = g[0]
                # first detection (necessary to be in gt_trajectories) is always tracked
                tracked = 1 if g[0] >= 0 else 0
                lgt = 0 if ign_g[0] else 1
                for f in range(1, len(g)):
                    if ign_g[f]:
                        last_id = -1
                        continue
                    lgt += 1
                    if last_id != g[f] and last_id != -1 and g[f] != -1 and g[
                            f - 1] != -1:
                        tmpId_switches += 1
                        self.id_switches += 1
                    if f < len(g) - 1 and g[f - 1] != g[
                            f] and last_id != -1 and g[f] != -1 and g[f +
                                                                      1] != -1:
                        tmpFragments += 1
                        self.fragments += 1
                    if g[f] != -1:
                        tracked += 1
                        last_id = g[f]
                # handle last frame; tracked state is handled in for loop (g[f]!=-1)
                if len(g) > 1 and g[f - 1] != g[f] and last_id != -1 and g[
                        f] != -1 and not ign_g[f]:
                    tmpFragments += 1
                    self.fragments += 1

                # compute MT/PT/ML
                tracking_ratio = tracked / float(len(g) - sum(ign_g))
                if tracking_ratio > 0.8:
                    tmpMT += 1
                    self.MT += 1
                elif tracking_ratio < 0.2:
                    tmpML += 1
                    self.ML += 1
                else:  # 0.2 <= tracking_ratio <= 0.8
                    tmpPT += 1
                    self.PT += 1

        if (self.n_gt_trajectories - n_ignored_tr_total) == 0:
            self.MT = 0.
            self.PT = 0.
            self.ML = 0.
        else:
            self.MT /= float(self.n_gt_trajectories - n_ignored_tr_total)
            self.PT /= float(self.n_gt_trajectories - n_ignored_tr_total)
            self.ML /= float(self.n_gt_trajectories - n_ignored_tr_total)

        # precision/recall etc.
        if (self.fp + self.tp) == 0 or (self.tp + self.fn) == 0:
            self.recall = 0.
            self.precision = 0.
        else:
            self.recall = self.tp / float(self.tp + self.fn)
            self.precision = self.tp / float(self.fp + self.tp)
        if (self.recall + self.precision) == 0:
            self.F1 = 0.
        else:
            self.F1 = 2. * (self.precision * self.recall) / (self.precision +
                                                             self.recall)
        if sum(self.n_frames) == 0:
            self.FAR = "n/a"
        else:
            self.FAR = self.fp / float(sum(self.n_frames))

        # compute CLEARMOT
        if self.n_gt == 0:
            self.MOTA = -float("inf")
            self.MODA = -float("inf")
        else:
            self.MOTA = 1 - (self.fn + self.fp + self.id_switches) / float(
                self.n_gt)
            self.MODA = 1 - (self.fn + self.fp) / float(self.n_gt)
        if self.tp == 0:
            self.MOTP = float("inf")
        else:
            self.MOTP = self.total_cost / float(self.tp)
        if self.n_gt != 0:
            if self.id_switches == 0:
                self.MOTAL = 1 - (self.fn + self.fp +
                                  self.id_switches) / float(self.n_gt)
            else:
                self.MOTAL = 1 - (self.fn + self.fp + math.log10(
                    self.id_switches)) / float(self.n_gt)
        else:
            self.MOTAL = -float("inf")
        if sum(self.n_frames) == 0:
            self.MODP = "n/a"
        else:
            self.MODP = sum(self.MODP_t) / float(sum(self.n_frames))
        return True
Example #33
0
class GN():
    def __init__(self, seq_index, tt, cuda=True):
        '''
        Evaluating with the MotMetrics
        :param seq_index: the number of the sequence
        :param tt: train_test
        :param length: the number of frames which is used for training
        :param cuda: True - GPU, False - CPU
        '''
        self.bbx_counter = 0
        self.seq_index = seq_index
        self.hungarian = Munkres()
        self.device = torch.device("cuda" if cuda else "cpu")
        self.tt = tt
        self.missingCounter = 0
        self.sideConnection = 0

        print '     Loading the model...'
        self.loadModel()

        self.out_dir = t_dir + 'motmetrics_%s/'%type
        if not os.path.exists(self.out_dir):
            os.mkdir(self.out_dir)
        else:
            deleteDir(self.out_dir)
            os.mkdir(self.out_dir)
        self.initOut()

    def initOut(self):
        print '     Loading Data...'
        self.train_set = DatasetFromFolder(sequence_dir, '../MOT/MOT16/test/MOT16-%02d'%self.seq_index)

        detection_dir = self.out_dir +'res_training_det.txt'
        res_training = self.out_dir + 'res_training.txt'  # the result of the training data
        self.createTxt(detection_dir)
        self.createTxt(res_training)
        self.copyLines(self.seq_index, 1, detection_dir, self.tt, 1)

        self.evaluation(1, self.tt, detection_dir, res_training)

    def getSeqL(self, info):
        # get the length of the sequence
        f = open(info, 'r')
        f.readline()
        for line in f.readlines():
            line = line.strip().split('=')
            if line[0] == 'seqLength':
                seqL = int(line[1])
        f.close()
        return seqL

    def copyLines(self, seq, head, gt_seq, tail=-1, tag=0):
        '''
        Copy the groun truth within [head, head+num]
        :param seq: the number of the sequence
        :param head: the head frame number
        :param tail: the number the clipped sequence
        :param gt_seq: the dir of the output file
        :return: None
        '''
        if tt_tag:
            basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq, type)
        else:
            basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq, type)
        print '     Testing on', basic_dir, 'Length:', self.tt
        seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini')

        det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt'
        seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir)
        inStream = open(seq_dir, 'r')

        outStream = open(gt_seq, 'w')
        for line in inStream.readlines():
            line = line.strip()
            attrs = line.split(',')
            f_num = int(attrs[0])
            if f_num >= head and f_num <= seqL:
                print >> outStream, line
        outStream.close()

        inStream.close()
        return seqL

    def createTxt(self, out_file):
        f = open(out_file, 'w')
        f.close()

    def loadModel(self):
        name = 'all_6'
        self.Uphi = torch.load('Results/MOT16/IoU/%s/uphi_13.pth'%name).to(self.device)
        self.Ephi = torch.load('Results/MOT16/IoU/%s/ephi_13.pth'%name).to(self.device)
        self.u = torch.load('Results/MOT16/IoU/%s/u_13.pth'%name)
        self.u = self.u.to(self.device)

    def swapFC(self):
        self.cur = self.cur ^ self.nxt
        self.nxt = self.cur ^ self.nxt
        self.cur = self.cur ^ self.nxt

    def linearModel(self, out, attr1, attr2):
        # print 'I got you! *.*'
        t = attr1[-1]
        self.sideConnection += 1
        if t > f_gap:
            return
        frame = int(attr1[0])
        x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float(attr1[4]), float(attr1[5])
        x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float(attr2[4]), float(attr2[5])

        x_delta = (x2-x1)/t
        y_delta = (y2-y1)/t
        w_delta = (w2-w1)/t
        h_delta = (h2-h1)/2

        for i in xrange(1, t):
            frame += 1
            x1 += x_delta
            y1 += y_delta
            w1 += w_delta
            h1 += h_delta
            attr1[0] = str(frame)
            attr1[2] = str(x1)
            attr1[3] = str(y1)
            attr1[4] = str(w1)
            attr1[5] = str(h1)
            line = ''
            for attr in attr1[:-1]:
                line += attr + ','
            if show_recovering:
                line += '1'
            else:
                line = line[:-1]
            print >> out, line
            self.bbx_counter += 1
        self.missingCounter += t-1

    def evaluation(self, head, tail, gtFile, outFile):
        '''
        Evaluation on dets
        :param head: the head frame number
        :param tail: the tail frame number
        :param gtFile: the ground truth file name
        :param outFile: the name of output file
        :return: None
        '''
        gtIn = open(gtFile, 'r')
        self.cur, self.nxt = 0, 1
        line_con = [[], []]
        id_con = [[], []]
        id_step = 1

        step = head + self.train_set.setBuffer(head)
        while step < tail:
            # print '*********************************'
            t_gap = self.train_set.loadNext()
            step += t_gap
            # print head+step, 'F',

            u_ = self.Uphi(self.train_set.E, self.train_set.V, self.u)

            # print 'Fo'
            m = self.train_set.m
            n = self.train_set.n
            # print 'm = %d, n = %d'%(m, n)
            if n==0:
                print 'There is no detection in the rest of sequence!'
                break

            if id_step == 1:
                out = open(outFile, 'a')
                i = 0
                while i < m:
                    attrs = gtIn.readline().strip().split(',')
                    if float(attrs[6]) >= tau_conf_score:
                        attrs.append(1)
                        attrs[1] = str(id_step)
                        line = ''
                        for attr in attrs[:-1]:
                            line += attr + ','
                        if show_recovering:
                            line += '0'
                        else:
                            line = line[:-1]
                        print >> out, line
                        self.bbx_counter += 1
                        line_con[self.cur].append(attrs)
                        id_con[self.cur].append(id_step)
                        id_step += 1
                        i += 1
                out.close()

            i = 0
            while i < n:
                attrs = gtIn.readline().strip().split(',')
                if float(attrs[6]) >= tau_conf_score:
                    attrs.append(1)
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(-1)
                    i += 1

            # update the edges
            # print 'T',
            ret = self.train_set.getRet()
            for edge in self.train_set.candidates:
                e, vs_index, vr_index = edge
                if ret[vs_index][vr_index] == 1.0:
                    continue
                e = e.to(self.device).view(1,-1)
                v1 = self.train_set.getMotion(1, vs_index).to(self.device)
                v2 = self.train_set.getMotion(0, vr_index, vs_index, line_con[self.cur][vs_index][-1]).to(self.device)
                e_ = self.Ephi(e, v1, v2, u_)
                self.train_set.edges[vs_index][vr_index] = e_.data.view(-1)
                tmp = F.softmax(e_)
                tmp = tmp.cpu().data.numpy()[0]
                ret[vs_index][vr_index] = float(tmp[0])

            # self.train_set.showE(outFile)

            # for j in ret:
            #     print j
            results = self.hungarian.compute(ret)

            out = open(outFile, 'a')
            look_up = set(j for j in xrange(n))
            for (i, j) in results:
                # print (i,j)
                if ret[i][j] >= tau_threshold:
                    continue
                look_up.remove(j)
                self.train_set.updateVelocity(i, j, line_con[self.cur][i][-1], False)

                id = id_con[self.cur][i]
                id_con[self.nxt][j] = id
                attr1 = line_con[self.cur][i]
                attr2 = line_con[self.nxt][j]
                # print attrs
                attr2[1] = str(id)
                if attr1[-1] > 1:
                    # for the missing detections
                    self.linearModel(out, attr1, attr2)
                line = ''
                for attr in attr2[:-1]:
                    line += attr + ','
                if show_recovering:
                    line += '0'
                else:
                    line = line[:-1]
                print >> out, line
                self.bbx_counter += 1

            for j in look_up:
                self.train_set.updateVelocity(-1, j, tag=False)

            for i in xrange(n):
                if id_con[self.nxt][i] == -1:
                    id_con[self.nxt][i] = id_step
                    attrs = line_con[self.nxt][i]
                    attrs[1] = str(id_step)
                    line = ''
                    for attr in attrs[:-1]:
                        line += attr + ','
                    if show_recovering:
                        line += '0'
                    else:
                        line = line[:-1]
                    print >> out, line
                    self.bbx_counter += 1
                    id_step += 1
            out.close()

            # For missing & Occlusion
            index = 0
            for (i, j) in results:
                while i != index:
                    attrs = line_con[self.cur][index]
                    # print '*', attrs, '*'
                    if attrs[-1] + t_gap <= gap:
                        attrs[-1] += t_gap
                        line_con[self.nxt].append(attrs)
                        id_con[self.nxt].append(id_con[self.cur][index])
                        self.train_set.moveMotion(index)
                    index += 1
                index += 1
            while index < m:
                attrs = line_con[self.cur][index]
                # print '*', attrs, '*'
                if attrs[-1] + t_gap <= gap:
                    attrs[-1] += t_gap
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(id_con[self.cur][index])
                    self.train_set.moveMotion(index)
                index += 1

            # con = self.train_set.cleanEdge()
            # for i in xrange(len(con)-1, -1, -1):
            #     index = con[i]
            #     del line_con[self.nxt][index]
            #     del id_con[self.nxt][index]

            line_con[self.cur] = []
            id_con[self.cur] = []
            # print head+step, results
            self.train_set.swapFC()
            self.swapFC()
        gtIn.close()
        print '     The results:', id_step, self.bbx_counter
class GN():
    def __init__(self, lr=5e-4, batchs=8, cuda=True):
        '''
        :param tt: train_test
        :param tag: 1 - evaluation on testing data, 0 - without evaluation on testing data
        :param lr:
        :param batchs:
        :param cuda:
        '''
        # all the tensor should set the 'volatile' as True, and False when update the network
        self.hungarian = Munkres()
        self.device = torch.device("cuda" if cuda else "cpu")
        self.nEpochs = 999
        self.lr = lr
        self.batchsize = batchs
        self.numWorker = 4

        self.show_process = 0  # interaction
        self.step_input = 1

        print '     Preparing the model...'
        self.resetU()

        self.Uphi = uphi().to(self.device)
        self.Ephi = ephi().to(self.device)

        self.criterion = nn.MSELoss() if criterion_s else nn.CrossEntropyLoss()
        self.criterion = self.criterion.to(self.device)

        self.optimizer = optim.Adam([{
            'params': self.Uphi.parameters()
        }, {
            'params': self.Ephi.parameters()
        }],
                                    lr=lr)

        # seqs = [2, 4, 5, 9, 10, 11, 13]
        # lengths = [600, 1050, 837, 525, 654, 900, 750]

        seqs = [2, 4, 5, 10]
        lengths = [600, 1050, 837, 654]

        for i in xrange(len(seqs)):
            self.writer = SummaryWriter()
            # print '     Loading Data...'
            seq = seqs[i]
            self.seq_index = seq
            start = time.time()
            sequence_dir = '../MOT/MOT16/train/MOT16-%02d' % seq
            self.outName = t_dir + 'result_%02d.txt' % seq
            self.train_set = DatasetFromFolder(sequence_dir, self.outName)

            self.train_test = lengths[i]
            self.tag = 0
            self.loss_threhold = 0.03
            self.update()

            print '     Logging...'
            t_data = time.time() - start
            self.log(t_data)

    def showNetwork(self):
        # add the graph into tensorboard
        E = torch.rand(1, 2).to(self.device)
        V = torch.rand(1, 512).to(self.device)
        u = torch.rand(1, 100).to(self.device)
        self.writer.add_graph(self.Uphi, (E, V, u))

        E = torch.rand(1, 2).to(self.device)
        V1 = torch.rand(1, 512).to(self.device)
        V2 = torch.rand(1, 512).to(self.device)
        u = torch.rand(1, 100).to(self.device)
        self.writer.add_graph(self.Ephi, (E, V1, V2, u))

    def log(self, t_data):
        out = open(self.outName, 'a')
        print >> out, self.criterion
        print >> out, 'lr:{}'.format(self.lr)
        print >> out, self.optimizer.state_dict()
        print >> out, self.Uphi
        print >> out, self.Ephi
        print >> out, 'Time consuming for loading datasets:', t_data
        out.close()
        # self.showNetwork()

    def resetU(self):
        if u_initial:
            self.u = torch.FloatTensor(
                [random.random() for i in xrange(u_num)]).view(1, -1)
        else:
            self.u = torch.FloatTensor([0.0
                                        for i in xrange(u_num)]).view(1, -1)
        self.u = self.u.to(self.device)

    def updateNetwork(self):
        self.train_set.setBuffer(1)
        step = 1
        average_epoch = 0
        edge_counter = 0.0
        for head in xrange(1, self.train_test):
            self.train_set.loadNext()  # Get the next frame
            edge_counter += self.train_set.m * self.train_set.n
            start = time.time()
            show_name = 'LOSS_{}'.format(step)
            print '         Step -', step
            data_loader = DataLoader(dataset=self.train_set,
                                     num_workers=self.numWorker,
                                     batch_size=self.batchsize,
                                     shuffle=True)
            for epoch in xrange(1, self.nEpochs):
                num = 0
                epoch_loss = 0.0
                arpha_loss = 0.0
                for iteration in enumerate(data_loader, 1):
                    index, (e, gt, vs_index, vr_index) = iteration
                    # print '*'*36
                    # print e.size()
                    # print gt.size()
                    e = e.to(self.device)
                    gt = gt.to(self.device)

                    self.optimizer.zero_grad()

                    u_ = self.Uphi(self.train_set.E, self.train_set.V, self.u)
                    v1 = self.train_set.getMotion(1, vs_index).to(self.device)
                    v2 = self.train_set.getMotion(0, vr_index,
                                                  vs_index).to(self.device)
                    e_ = self.Ephi(e, v1, v2, u_)

                    if self.show_process:
                        print '-' * 66
                        print vs_index, vr_index
                        print 'e:', e.cpu().data.numpy()[0][0],
                        print 'e_:', e_.cpu().data.numpy()[0][0],
                        if criterion_s:
                            print 'GT:', gt.cpu().data.numpy()[0][0]
                        else:
                            print 'GT:', gt.cpu().data.numpy()[0]

                    # Penalize the u to let its value not too big
                    # arpha = torch.mean(torch.abs(u_))
                    # arpha_loss += arpha.item()
                    # arpha.backward(retain_graph=True)

                    #  The regular loss
                    # print e_.size(), e_
                    # print gt.size(), gt
                    loss = self.criterion(e_, gt.squeeze(1))
                    # print loss
                    epoch_loss += loss.item()
                    loss.backward()

                    # update the network: Uphi and Ephi
                    self.optimizer.step()

                    #  Show the parameters of the Uphi and Ephi to check the process of optimiser
                    # print self.Uphi.features[0].weight.data
                    # print self.Ephi.features[0].weight.data
                    # raw_input('continue?')

                    num += self.batchsize

                if self.show_process and self.step_input:
                    a = raw_input(
                        'Continue(0-step, 1-run, 2-run with showing)?')
                    if a == '1':
                        self.show_process = 0
                    elif a == '2':
                        self.step_input = 0

                epoch_loss /= num
                print '         Loss of epoch {}: {}.'.format(
                    epoch, epoch_loss)
                self.writer.add_scalars(show_name, {
                    'regular': epoch_loss,
                    'u': arpha_loss / num * self.batchsize
                }, epoch)
                if epoch_loss < self.loss_threhold:
                    break

            print '         Time consuming:{}\n\n'.format(time.time() - start)
            self.updateUE()
            self.train_set.showE()
            self.showU()
            average_epoch += epoch
            self.writer.add_scalar('epoch', epoch, step)
            step += 1
            self.train_set.swapFC()
        out = open(self.outName, 'a')
        print >> out, 'Average edge:', edge_counter * 1.0 / step, '.',
        print >> out, 'Average epoch:', average_epoch * 1.0 / step, 'for',
        print >> out, 'Random' if edge_initial else 'IoU'
        out.close()

    def saveModel(self):
        print 'Saving the Uphi model...'
        torch.save(self.Uphi, t_dir + 'uphi_%02d.pth' % self.seq_index)
        print 'Saving the Ephi model...'
        torch.save(self.Ephi, t_dir + 'ephi_%02d.pth' % self.seq_index)
        print 'Saving the global variable u...'
        torch.save(self.u, t_dir + 'u_%02d.pth' % self.seq_index)
        print 'Done!'

    def updateUE(self):
        u_ = self.Uphi(self.train_set.E, self.train_set.V, self.u)

        self.u = u_.data

        # update the edges
        for edge in self.train_set:
            e, gt, vs_index, vr_index = edge
            e = e.to(self.device).view(1, -1)
            v1 = self.train_set.getMotion(1, vs_index).to(self.device)
            v2 = self.train_set.getMotion(0, vr_index,
                                          vs_index).to(self.device)
            e_ = self.Ephi(e, v1, v2, u_)
            self.train_set.edges[vs_index][vr_index] = e_.data.view(-1)

    def update(self):
        start = time.time()
        self.evaluation(1)
        if self.tag:
            self.evaluation(self.train_test)
        self.updateNetwork()
        self.saveModel()
        self.evaluation(1)
        if self.tag:
            self.evaluation(self.train_test)
        out = open(self.outName, 'a')
        print >> out, 'The final time consuming:{}\n\n'.format(
            (time.time() - start) / 60)
        out.close()
        self.outputScalars()

    def outputScalars(self):
        self.writer.export_scalars_to_json(t_dir + 'scalars_%02d.json' %
                                           self.seq_index)
        self.writer.close()

    def evaluation(self, head):
        self.train_set.setBuffer(head)
        total_gt = 0.0
        total_ed = 0.0
        for step in xrange(1, self.train_test):
            self.train_set.loadNext()
            # print head+step, 'F',

            u_ = self.Uphi(self.train_set.E, self.train_set.V, self.u)

            # print 'Fo'
            m = self.train_set.m
            n = self.train_set.n
            ret = [[0.0 for i in xrange(n)] for j in xrange(m)]
            step_gt = self.train_set.step_gt
            total_gt += step_gt

            # update the edges
            # print 'T',
            for edge in self.train_set.candidates:
                e, gt, vs_index, vr_index = edge
                e = e.to(self.device).view(1, -1)
                v1 = self.train_set.getMotion(1, vs_index).to(self.device)
                v2 = self.train_set.getMotion(0, vr_index,
                                              vs_index).to(self.device)
                e_ = self.Ephi(e, v1, v2, u_)
                self.train_set.edges[vs_index][vr_index] = e_.data.view(-1)
                tmp = F.softmax(e_)
                tmp = tmp.cpu().data.numpy()[0]
                ret[vs_index][vr_index] = float(tmp[0])

            self.train_set.showE()
            self.showU()

            # for j in ret:
            #     print j
            results = self.hungarian.compute(ret)
            # print head+step, results,
            step_ed = 0.0
            for (j, k) in results:
                step_ed += self.train_set.gts[j][k].item()
            total_ed += step_ed

            # print 'Fi'
            print '     ', head + step, 'Step ACC:{}/{}({}%)'.format(
                int(step_ed), int(step_gt), step_ed / step_gt * 100)
            self.train_set.swapFC()

        tra_tst = 'training sets' if head == 1 else 'testing sets'
        print 'Final {} ACC:{}/{}({}%)'.format(tra_tst, int(total_ed),
                                               int(total_gt),
                                               total_ed / total_gt * 100)
        out = open(self.outName, 'a')
        print >> out, 'Final {} ACC:{}/{}({}%)'.format(
            tra_tst, int(total_ed), int(total_gt), total_ed / total_gt * 100)
        out.close()

    def showU(self):
        out = open(self.outName, 'a')
        print >> out, '     u'
        print >> out, self.u.view(
            10, -1)  # reshape the size of z with aspect of 10 * 10
        out.close()
Example #35
0
def py_max_match(scores):
    m = Munkres()
    tmp = m.compute(scores)
    tmp = np.array(tmp).astype(np.int32)
    return tmp
Example #36
0
def draw(users, year, courses):
    """
    We produce the following matrix
        [
         (user1) [ item1, item1, item1, (in fact item1 * item1.count, item2, item2, ... item2.count ],
         (user2)
         (user3)
            .
            .
        ]

    This means the hungarian algorithm is going to find the "lowest cost", where every user hopefully
    one of his choices.

    This algorithm has a very bad worst case complexity O(n^3), and we need to construct an array of
    the size user.count * number of items * item.count.
    This works well when the number of users is < 200 and the number of items < 30.
    """

    matrix = []
    for user in users:
        x = []
        for course in courses:
            for _ in range(0, course['max']):
                want = False
                for inner in user['selection'][year]:
                    if inner['name'] == course['name']:
                        x.append(4 - inner['importance']
                                 )  # higher importance => "lower cost"
                        want = True
                if not want:
                    x.append(10)
        matrix.append(x)

    start = datetime.datetime.now()
    m = Munkres()
    indexes = m.compute(matrix)
    print 'Computation took: ' + str(datetime.datetime.now() - start)

    counter = {}
    good = 0

    if len(indexes) < len(users):
        raise Exception('Could not calculate any sane result!')

    for row, column in indexes:
        index = 0

        # try to match the course from the colum index
        for course in courses:
            index += course['max']
            if column <= index:
                name = course['name']
                break

        if not counter.has_key(name):
            counter[name] = 1
        else:
            counter[name] += 1

        user = users[row]
        for selection in user['selection'][year]:
            if selection['name'] == name:
                good += 1

        if not user.has_key('result'):
            user['result'] = [None, None]
        user['result'][year] = name

    print '%d of %d got at least one of their choices' % (good, len(users))
Example #37
0
#Nodes and edges in bio-DRN
NBD = []
EBD = []

#Corresponding mapped node of reference GRN
NRG = []

for i in range(len(L1)):
    print(i)
    YM = Y[L1[i], :][:, L2[i]]
    YM = reverse(YM)
    YM = YM.tolist()
    m = Munkres()

    indexes = m.compute(YM)
    print(indexes)

    for each in indexes:
        NBD.append(L2[i][each[1]])
        NRG.append(L1[i][each[0]])

#Introduce edges in Bio-DRN
for u in NBD:
    for v in NBD:
        if (u, v) in G2.edges() and (NRG[NBD.index(u)],
                                     NRG[NBD.index(v)]) in G.edges():
            EBD.append((u, v))

print(len(NBD))
print(len(NRG))
Example #38
0
from munkres import Munkres, print_matrix
matrix = [[
    5,
    3,
], [3, 3], [3, 3]]
m = Munkres()
indexes = m.compute(matrix)
print_matrix(matrix, msg='Lowest cost through this matrix:')
total = 0
for row, column in indexes:
    value = matrix[row][column]
    total += value
    print('(%d, %d) -> %d' % (row, column, value))
print('total cost: %d' % total)
def calculateSimilarity(sent1, sent2, isTitle):
    # Case Correction
    sent1 = sent1.lower()
    sent2 = sent2.lower()

    # Tokenization
    normalizer = Normalizer()
    _tokens1 = word_tokenize(
        normalizer.normalize(
            sent1.replace('\u200f', '').replace('\ufeff', '')))
    _tokens2 = word_tokenize(
        normalizer.normalize(
            sent2.replace('\u200f', '').replace('\ufeff', '')))

    # Remove punctuations
    _tokens1 = [x for x in _tokens1 if x not in string.punctuation]
    _tokens2 = [x for x in _tokens2 if x not in string.punctuation]

    # Trigram Replacement
    tokens1_tmp = []
    i = 0
    while i < len(_tokens1) - 2:
        trigram = _tokens1[i] + '_' + _tokens1[i + 1] + '_' + _tokens1[i + 2]
        if trigram in model.wv.vocab:
            tokens1_tmp.append(_tokens1[i] + '_' + _tokens1[i + 1] + '_' +
                               _tokens1[i + 2])
            i += 3
        else:
            tokens1_tmp.append(_tokens1[i])
            i += 1
    try:
        tokens1_tmp.append(_tokens1[len(_tokens1) - 2])
        tokens1_tmp.append(_tokens1[len(_tokens1) - 1])
    except:
        pass

    tokens2_tmp = []
    i = 0
    while i < len(_tokens2) - 2:
        trigram = _tokens2[i] + '_' + _tokens2[i + 1] + '_' + _tokens2[i + 2]
        if trigram in model.wv.vocab:
            tokens2_tmp.append(_tokens2[i] + '_' + _tokens2[i + 1] + '_' +
                               _tokens2[i + 2])
            i += 3
        else:
            tokens2_tmp.append(_tokens2[i])
            i += 1
    try:
        tokens2_tmp.append(_tokens2[len(_tokens2) - 2])
        tokens2_tmp.append(_tokens2[len(_tokens2) - 1])
    except:
        pass

    # Bigrams Replacement
    tokens1 = []
    i = 0
    while i < len(tokens1_tmp) - 1:
        bigram = tokens1_tmp[i] + '_' + tokens1_tmp[i + 1]
        if bigram in model.wv.vocab:
            tokens1.append(tokens1_tmp[i] + '_' + tokens1_tmp[i + 1])
            i += 2
        else:
            tokens1.append(tokens1_tmp[i])
            i += 1
    try:
        tokens1.append(_tokens1[len(tokens1_tmp) - 1])
    except:
        pass

    tokens2 = []
    i = 0
    while i < len(tokens2_tmp) - 1:
        bigram = tokens2_tmp[i] + '_' + tokens2_tmp[i + 1]
        if bigram in model.wv.vocab:
            tokens2.append(tokens2_tmp[i] + '_' + tokens2_tmp[i + 1])
            i += 2
        else:
            tokens2.append(tokens2_tmp[i])
            i += 1
    try:
        tokens2.append(_tokens2[len(tokens2_tmp) - 1])
    except:
        pass

    # Model has token?
    tokens1 = [x for x in tokens1 if x in model.wv.vocab]
    tokens2 = [x for x in tokens2 if x in model.wv.vocab]

    tmp_matched_ngrams = 0
    tmp_matched_1grams = 0

    if len(tokens1) > 0 and len(tokens2) > 0:
        m = Munkres()

        pairMatrix = []
        for t1 in tokens1:
            tmpList = []
            for t2 in tokens2:
                tmpList.append(100 * cosine_sim(model[t1], model[t2]))
            pairMatrix.append(tmpList)

        cost_matrix = make_cost_matrix(pairMatrix, lambda cost: 100 - cost)
        indexes = m.compute(cost_matrix)
        # print_matrix(pairMatrix, msg='Lowest cost through this matrix:')

        total = 0
        for row, column in indexes:
            value = pairMatrix[row][column]
            total += value
            if not isTitle:
                if '_' in tokens1[row]:
                    tmp_matched_ngrams += 1
                elif '_' in tokens2[column]:
                    tmp_matched_ngrams += 1
                else:
                    tmp_matched_1grams += 1
        # print('(%d, %d) -> %d' % (row, column, value))
        # print('total cost: %d' % total)
        # print(total / len(indexes))

        # return total / len(indexes) / 100
        return [
            2 * total / (len(tokens1) + len(tokens2)) / 100,
            tmp_matched_ngrams, tmp_matched_1grams
        ]
    else:
        return [0, 0, 0]
Example #40
0
class BaseHungarianAllocator(BaseAdjudicatorAllocator):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        t = self.tournament
        self.min_score = t.pref('adj_min_score')
        self.max_score = t.pref('adj_max_score')
        self.min_voting_score = t.pref('adj_min_voting_score')
        self.conflict_penalty = t.pref('adj_conflict_penalty')
        self.history_penalty = t.pref('adj_history_penalty')
        self.no_panellists = t.pref('no_panellist_position')
        self.no_trainees = t.pref('no_trainee_position')
        self.duplicate_allocations = t.pref('duplicate_adjs')
        self.feedback_weight = self.round.feedback_weight
        self.extra_messages = ""  # Surfaced to users for non-error disclosures

        self.munkres = Munkres()

    def allocate(self):
        self.populate_adj_scores(self.adjudicators)
        return self.run_allocation(), self.extra_messages

    def populate_adj_scores(self, adjudicators):
        score_min = self.min_score
        score_range = self.max_score - score_min

        for adj in adjudicators:
            adj._weighted_score = adj.weighted_score(
                self.feedback_weight)  # used in min_voting_score filter
            try:
                adj._normalized_score = (adj._weighted_score - score_min
                                         ) / score_range * 5  # to 0-5 range
            except ZeroDivisionError:
                adj._normalized_score = 0.0

        ntoolarge = [adj._normalized_score > 5.0
                     for adj in adjudicators].count(True)
        if ntoolarge > 0:
            warning_msg = ngettext(
                "%(count)s normalised score is larger than 5.0.",
                "%(count)s normalised scores are larger than 5.0.",
                ntoolarge) % {
                    'count': ntoolarge
                }
            self.extra_messages += " " + warning_msg
            logger.warning(warning_msg)
        ntoosmall = [adj._normalized_score < 0.0
                     for adj in adjudicators].count(True)
        if ntoosmall > 0:
            warning_msg = ngettext(
                "%(count)s normalised score is smaller than 0.0.",
                "%(count)s normalised scores are smaller than 0.0.",
                ntoosmall) % {
                    'count': ntoosmall
                }
            self.extra_messages += " " + warning_msg
            logger.warning(warning_msg)

    def calc_cost(self, debate, adj, adjustment=0, chair=None):
        cost = 0

        # Normalise debate importances back to the 1-5 (not ±2) range expected
        normalised_importance = debate.importance + 3

        for team in debate.teams:
            cost += self.conflict_penalty * self.conflicts.conflict_adj_team(
                adj, team)
            cost += self.history_penalty * self.history.seen_adj_team(
                adj, team)
        if chair:
            cost += self.conflict_penalty * self.conflicts.conflict_adj_adj(
                adj, chair)
            cost += self.history_penalty * self.history.seen_adj_adj(
                adj, chair)

        impt = normalised_importance + adjustment
        diff = 5 + impt - adj._normalized_score
        if diff > 0.25:
            cost += 1000 * exp(diff - 0.25)

        cost += self.max_score - adj._normalized_score

        return cost

    def allocate_trainees(self, trainees, allocation, debates):
        if len(trainees) > 0 and len(debates) > 0:
            allocation_by_debate = {aa.container: aa for aa in allocation}

            logger.info("costing trainees")
            cost_matrix = []
            for debate in debates:
                chair = allocation_by_debate[debate].chair
                row = [
                    self.calc_cost(debate, adj, adjustment=-2.0, chair=chair)
                    for adj in trainees
                ]
                cost_matrix.append(row)

            logger.info(
                "optimizing trainees (matrix size: %d positions by %d trainees)",
                len(cost_matrix), len(cost_matrix[0]))
            indices = self.munkres.compute(cost_matrix)
            total_cost = sum(cost_matrix[i][j] for i, j in indices)
            logger.info('total cost for %d trainees: %f', len(indices),
                        total_cost)

            result = ((debates[i], trainees[j]) for i, j in indices
                      if i < len(debates))
            for debate, trainee in result:
                allocation_by_debate[debate].trainees.append(trainee)
                logger.info("allocating to %s: %s (t)", debate, trainee)

    def check_matrix_exists(self, n_debates, n_voting):
        if n_voting == 0:
            info = _(
                "There are no adjudicators eligible to be a chair or "
                "panellist. Try changing the \"Minimum feedback score "
                "required to be allocated as chair or panellist\" setting "
                "to something lower than at least some adjudicators' "
                "current scores, and try again.")
            logger.info("No adjudicators able to panel or chair")
            raise AdjudicatorAllocationError(info)
        if n_debates == 0:
            info = _("There are no debates for this round. "
                     "Maybe you haven't created a draw yet?")
            logger.info("No debates available for allocator")
            raise AdjudicatorAllocationError(info)
Example #41
0
    def __init__(self, orig_cost_matrix, required_cells, excluded_cells,
                 orig_cost_matrix_index):
        '''
        Following the terminology used by [1], a node is defined to be a nonempty subset of possible
        assignments to a cost matrix.  Every assignment in node N is required to contain
        required_cells and exclude excluded_cells.

        Inputs:
        - orig_cost_matrix: (2d numpy array) the original cost matrix
        - required_cells: (list of pairs) where each pair represents a (zero indexed) location
            in the assignment matrix that must be a 1
        - excluded_cells: list of pairs) where each pair represents a (zero indexed) location
            in the assignment matrix that must be a 0
        - orig_cost_matrix_index: index of the cost matrix this Node is descended from, used when
            when finding the k lowest cost assignments among a group of assignment matrices
            (k_best_assign_mult_cost_matrices)
        '''
        self.orig_cost_matrix = np.array(orig_cost_matrix, copy=True)
        self.required_cells = required_cells[:]
        self.excluded_cells = excluded_cells[:]
        self.orig_cost_matrix_index = orig_cost_matrix_index
        if DEBUG:
            print "New Node:"
            print "self.required_cells:", self.required_cells
            print "self.excluded_cells:", self.excluded_cells

        #we will transform the cost matrix into the "remaining cost matrix" as described in [1]
        self.remaining_cost_matrix = self.construct_remaining_cost_matrix()
        assert ((self.remaining_cost_matrix >
                 0).all()), self.remaining_cost_matrix
        #solve the assignment problem for the remaining cost matrix
        hm = Munkres()
        # we get a list of (row, col) associations, or 1's in the minimum assignment matrix
        association_list = hm.compute(self.remaining_cost_matrix.tolist())
        if DEBUG:
            print "remaining cost matrix:"
            print self.remaining_cost_matrix
            print "association_list"
            print association_list

        #compute the minimum cost assignment for the node
        self.minimum_cost = 0
        for (row, col) in association_list:
            #            print 'a', self.minimum_cost, type(self.minimum_cost)
            #            print 'b', self.remaining_cost_matrix[row][col], type(self.remaining_cost_matrix[row][col])
            #            print 'c', self.minimum_cost +self.remaining_cost_matrix[row][col], type(self.minimum_cost +self.remaining_cost_matrix[row][col])
            #np.asscalar important for avoiding overflow problems
            self.minimum_cost += np.asscalar(
                self.remaining_cost_matrix[row][col])
        for (row, col) in self.required_cells:
            #np.asscalar important for avoiding overflow problems
            self.minimum_cost += np.asscalar(orig_cost_matrix[row][col])

        #store the minimum cost associations with indices consistent with the original cost matrix
        self.min_cost_associations = self.get_orig_indices(association_list)

        if DEBUG:
            print "New Node:"
            print "self.required_cells:", self.required_cells
            print "self.excluded_cells:", self.excluded_cells
            print
            print
Example #42
0
                ]

                # Model has token?
                posTokens1 = [x for x in posTokens1 if x[0] in model.vocab]
                posTokens2 = [x for x in posTokens2 if x[0] in model.vocab]

                m = Munkres()

                pairMatrix = []
                for t1 in tokens1:
                    tmpList = []
                    for t2 in tokens2:
                        tmpList.append(100 * cosine_sim(model[t1], model[t2]))
                    pairMatrix.append(tmpList)

                cost_matrix = make_cost_matrix(pairMatrix,
                                               lambda cost: 100 - cost)
                indexes = m.compute(cost_matrix)
                # print_matrix(pairMatrix, msg='Lowest cost through this matrix:')
                total = 0
                for row, column in indexes:
                    value = pairMatrix[row][column]
                    total += value
                    # print('(%d, %d) -> %d' % (row, column, value))
                # print('total cost: %d' % total)
                # print(total / len(indexes))
                g.write(str(int(total / len(indexes) / 20)))
                g.write('\n')

# print(stats.pearsonr([1, 2, 3, 4, 5], [1, 2, 3, 4, 4000]))
Example #43
0
class TestHungarian():
    """
    Imported Munkres module that provides an implementation of the Munkres algorithm
    that can be used to test my implementation. Generates 10 balanced matrices and 10
    unbalanced matrices of maximum size 'max_problem_size that tests are run on

    How to install munkres test module:
    try: 'pip install munkres3'
    If pip install does not work the module named 'munkres3-1.0.5.5' exists in the same folder as this file.
    When inside folder run: 'python3 setup.py install'
    """
    def __init__(self, max_problem_size):
        self.h = Hungarian()
        self.m = Munkres()
        self.matrices = []
        self.rectangular_matrices = []

        # Generate random matrices used for testing
        for i in range(1, 11):
            rand_int1 = randint(1, max_problem_size)
            rand_int2 = randint(1, max_problem_size)
            self.matrices.append(
                np.random.randint(max_problem_size,
                                  size=(rand_int1,
                                        rand_int1)))  # balanced matrices
            self.rectangular_matrices.append(
                np.random.randint(max_problem_size,
                                  size=(rand_int1,
                                        rand_int2)))  # unbalanced matrices

    def pretty_print_assignments(self, assignments, matrix):
        """ Pretty prints assignments and it's profit
        :param assignments: assignments from node in X to node in Y. dict<int, int>
        :param matrix: NxN profit matrix. Profit from X assigned to Y.
        :return: Total profit of assignments """
        total_profit = 0
        for key, value in assignments.items():
            profit = matrix[key][value]
            total_profit += profit
            print('(%d, %d) -> %d' % (key, value, profit))

        print('total profit=%d' % total_profit)
        return total_profit

    def max_to_min_problem(self, matrix):
        """ Convert from maximization to min problem """
        cost_matrix = []
        for row in matrix:
            cost_row = []
            for col in row:
                cost_row += [sys.maxsize - col]
            cost_matrix += [cost_row]
        return cost_matrix

    def convert_to_dict(self, indexes):
        """ This module uses lists to represents assignments whereas my
        implementation uses dict """
        assignments = {}
        for pair in indexes:
            assignments[pair[0]] = pair[1]
        return assignments

    def compute_test_assignments(self, matrix):
        """ Compute assignments using imported munkres """
        cost_matrix = self.max_to_min_problem(matrix)
        indexes = self.m.compute(cost_matrix)
        total = 0
        return self.convert_to_dict(indexes)

    def print_balanced_matrix(self, matrix, msg):
        (a, b) = matrix.shape
        if a > b:
            padding = ((0, 0), (0, a - b))
        else:
            padding = ((0, b - a), (0, 0))
        balanced_matrix = np.pad(matrix,
                                 padding,
                                 mode='constant',
                                 constant_values=0)
        print_matrix(balanced_matrix, msg=msg)

    def run_test(self):
        """ Runs anton's implementation of the hungarian algorithm and compares the results to the results of the imported munkres module. The munkres module will balance the problem automatically. Anton's implementation has it's own balancing function. Assignments can differ between the two algorithms, but the total the number of assignments and total profit should always be equal.
        """
        test_matrices = self.matrices + self.rectangular_matrices

        for index, matrix in enumerate(test_matrices, start=1):
            print("\n\n----- TEST %d ------ " % (index))
            print_matrix(matrix, msg='Original matrix:')
            self.print_balanced_matrix(matrix, msg='\nBalanced matrix:')

            print("\nAnton's assignments:")
            self.h.compute_assignments(matrix)
            self.h.pretty_print_assignments()

            print("Correct assignments:")
            valid_assignments = self.compute_test_assignments(
                matrix)  # will balance matrices using munkres module
            valid_profit = self.pretty_print_assignments(
                valid_assignments, matrix)

            assert self.h.total_profit == valid_profit  # make sure total profit is correct
            assert len(self.h.matching) == len(
                valid_assignments
            )  # make sure that dummy row/columns have been removed
class GN():
    def __init__(self, seq_index, begin, end, cuda=True):
        '''
        Evaluating with the MotMetrics
        :param seq_index: the number of the sequence
        :param tt: train_test
        :param length: the number of frames which is used for training
        :param cuda: True - GPU, False - CPU
        '''
        self.bbx_counter = 0
        self.seq_index = seq_index
        self.hungarian = Munkres()
        self.device = torch.device("cuda" if cuda else "cpu")
        self.begin = begin
        self.end = end
        self.missingCounter = 0
        self.sideConnection = 0

        print '     Loading the model...'
        self.loadModel()

        if train_set_num == 4:
            self.out_dir = t_dir + 'motmetrics_%s_4%s%.2f%s%s/' % (
                type, decay_dir, decay, recover_dir, u_dir)
        else:
            # divide each sequence into two parts with proportion 4:1
            self.out_dir = t_dir + 'motmetrics_%s_4%s%.2f%s%s_fgap_%d_dseq_longer0/' % (
                type, decay_dir, decay, recover_dir, u_dir, f_gap)

        print self.out_dir

        if not os.path.exists(self.out_dir):
            os.mkdir(self.out_dir)
        else:
            deleteDir(self.out_dir)
            os.mkdir(self.out_dir)
        self.initOut()

    def initOut(self):
        print '     Loading Data...'
        self.train_set = DatasetFromFolder(
            sequence_dir, '../MOT/MOT16/train/MOT16-%02d' % self.seq_index,
            tau_conf_score)

        gt_training = self.out_dir + 'gt_training.txt'  # the gt of the training data
        self.copyLines(self.seq_index, self.begin, gt_training, self.end)

        detection_dir = self.out_dir + 'res_training_det.txt'
        res_training = self.out_dir + 'res_training.txt'  # the result of the training data
        self.createTxt(detection_dir)
        self.createTxt(res_training)
        self.copyLines(self.seq_index, self.begin, detection_dir, self.end, 1)

        self.evaluation(self.begin, self.end, detection_dir, res_training)

    def getSeqL(self, info):
        # get the length of the sequence
        f = open(info, 'r')
        f.readline()
        for line in f.readlines():
            line = line.strip().split('=')
            if line[0] == 'seqLength':
                seqL = int(line[1])
        f.close()
        return seqL

    def copyLines(self, seq, head, gt_seq, tail=-1, tag=0):
        '''
        Copy the groun truth within [head, head+num]
        :param seq: the number of the sequence
        :param head: the head frame number
        :param tail: the number the clipped sequence
        :param gt_seq: the dir of the output file
        :return: None
        '''
        if tt_tag:
            basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq,
                                                              type)
        else:
            basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq,
                                                               type)
        print '     Testing on', basic_dir, 'Length:', self.end - self.begin + 1
        seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini')

        det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt'
        seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir)
        inStream = open(seq_dir, 'r')

        outStream = open(gt_seq, 'w')
        for line in inStream.readlines():
            line = line.strip()
            attrs = line.split(',')
            f_num = int(attrs[0])
            if f_num >= head and f_num <= seqL:
                print >> outStream, line
        outStream.close()

        inStream.close()
        return seqL

    def createTxt(self, out_file):
        f = open(out_file, 'w')
        f.close()

    def loadModel(self):
        # name = 'longterm_all_%d'%train_set_num
        name = 'all_%d' % train_set_num

        tail = 10 if train_set_num == 4 else 13
        if edge_initial == 1:
            i_name = 'Random'
        elif edge_initial == 0:
            i_name = 'IoU'
        elif edge_initial == 3:
            i_name = 'Equal'
        print 'Loading model from', i_name
        self.Uphi = torch.load('Results/MOT16/%s/%s/uphi_%d.pth' %
                               (i_name, name, tail)).to(self.device)
        self.Ephi = torch.load('Results/MOT16/%s/%s/ephi_%d.pth' %
                               (i_name, name, tail)).to(self.device)
        self.u = torch.load('Results/MOT16/%s/%s/u_%d.pth' %
                            (i_name, name, tail))
        self.u = self.u.to(self.device)

    def linearModel(self, out, attr1, attr2):
        # print 'I got you! *.*'
        t = attr1[-1]
        self.sideConnection += 1
        if t > f_gap:
            return
        frame = int(attr1[0])
        x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float(
            attr1[4]), float(attr1[5])
        x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float(
            attr2[4]), float(attr2[5])

        x_delta = (x2 - x1) / t
        y_delta = (y2 - y1) / t
        w_delta = (w2 - w1) / t
        h_delta = (h2 - h1) / t

        if t > 1:
            print 'Linear:', attr1, attr2

        for i in xrange(1, t):
            frame += 1
            x1 += x_delta
            y1 += y_delta
            w1 += w_delta
            h1 += h_delta
            attr1[0] = str(frame)
            attr1[2] = str(x1)
            attr1[3] = str(y1)
            attr1[4] = str(w1)
            attr1[5] = str(h1)
            line = ''
            for attr in attr1[:-1]:
                line += attr + ','
            if show_recovering:
                line += '1'
            else:
                line = line[:-1]
            # print "liner:", line
            print >> out, line
            self.bbx_counter += 1
        self.missingCounter += t - 1

    def evaluation(self, head, tail, gtFile, outFile):
        '''
        Evaluation on dets
        :param head: the head frame number
        :param tail: the tail frame number
        :param gtFile: the ground truth file name
        :param outFile: the name of output file
        :return: None
        '''
        gtIn = open(gtFile, 'r')
        self.cur, self.nxt = 0, 1
        line_con = [[], []]
        id_con = []
        id_step = 1

        step = head + self.train_set.setBuffer(head)
        while step < tail:
            # print '*********************************'
            t_gap = self.train_set.loadNext()
            step += t_gap
            print head + step,
            if (head + step) % 30 == 0:
                print ''

            # print 'Fo'
            m = self.train_set.m
            n = self.train_set.n
            # print 'm = %d, n = %d'%(m, n)
            if n == 0:
                print 'There is no detection in the rest of sequence!'
                break

            if id_step == 1:
                out = open(outFile, 'a')
                i = 0
                while i < m:
                    attrs = gtIn.readline().strip().split(',')
                    if float(attrs[6]) >= tau_conf_score:
                        attrs.append(1)
                        attrs[1] = str(id_step)
                        line = ''
                        for attr in attrs[:-1]:
                            line += attr + ','
                        if show_recovering:
                            line += '0'
                        else:
                            line = line[:-1]
                        print >> out, line
                        self.bbx_counter += 1
                        line_con[self.cur].append(attrs)
                        id_con.append(id_step)
                        id_step += 1
                        i += 1
                out.close()

            i = 0
            while i < n:
                attrs = gtIn.readline().strip().split(',')
                if float(attrs[6]) >= tau_conf_score:
                    attrs.append(1)
                    line_con[self.nxt].append(attrs)
                    i += 1

            # update the edges
            # print 'T',
            if u_update:
                u_ = []
                for i in xrange(len(self.train_set.E)):
                    # print 'The aggregation of Edges and Nodes:'
                    # print self.train_set.E[i].size()
                    # print self.train_set.V[i].size()
                    # print self.u.size()
                    u_.append(
                        self.Uphi(self.train_set.E[i], self.train_set.V[i],
                                  self.u))
                self.u = u_[0].data

            ret = self.train_set.getRet()
            decay_tag = [0 for i in xrange(m)]
            for i in xrange(m):
                for j in xrange(n):
                    if ret[i][j] == 0:
                        decay_tag[i] += 1

            for edge in self.train_set.candidates:
                edges, indexes, vs_index, vr_index = edge
                if ret[vs_index][vr_index] == tau_threshold:
                    continue
                costs = []
                v1s = self.train_set.getMotion(1, vs_index)
                v2s = self.train_set.getMotion(0, vr_index, vs_index)
                for i in xrange(len(indexes)):
                    index = indexes[i]
                    e = edges[i]
                    if e is not None:
                        e = e.to(self.device).view(1, -1)
                        e_ = self.Ephi(e, v1s[index], v2s[index], u_[i])
                        tmp = F.softmax(e_)
                        tmp = tmp.cpu().data.numpy()[0]
                        costs.append(tmp[0])

                t = line_con[self.cur][vs_index][-1]
                # ret[vs_index][vr_index] = float(tmp[0])*pow(decay, t-1)
                cost = sum(costs) / len(costs)
                if decay_tag[vs_index] > 0:
                    ret[vs_index][vr_index] = min(cost * pow(decay, t - 1),
                                                  1.0)
                else:
                    ret[vs_index][vr_index] = float(cost)

            # self.train_set.showE(outFile)

            # for j in ret:
            #     print j
            results = self.hungarian.compute(ret)

            out = open(outFile, 'a')
            look_up = set(j for j in xrange(n))
            for (i, j) in results:
                # print (i,j)
                if ret[i][j] >= tau_threshold:
                    continue
                look_up.remove(j)
                self.train_set.updateVelocity(i, j, False)

                id = id_con[i]
                attr1 = line_con[self.cur][i]
                attr2 = line_con[self.nxt][j]
                # print attrs
                attr2[1] = str(id)
                if attr1[-1] > 1:
                    # for the missing detections
                    self.linearModel(out, attr1, attr2)
                line = ''
                for attr in attr2[:-1]:
                    line += attr + ','
                if show_recovering:
                    line += '0'
                else:
                    line = line[:-1]
                # print 'Association:', line
                print >> out, line
                self.bbx_counter += 1

                line_con[self.cur][i] = attr2
                # print attr1
                # print line_con[self.cur][i]
                # raw_input('continue?')

            for j in look_up:
                self.train_set.updateVelocity(-1, j, tag=False)
                attrs = line_con[self.nxt][j]
                attrs[1] = str(id_step)

                line_con[self.cur].append(line_con[self.nxt][j])
                id_con.append(id_step)

                line = ''
                for attr in attrs[:-1]:
                    line += attr + ','
                if show_recovering:
                    line += '0'
                else:
                    line = line[:-1]
                # print 'New objects:', line
                print >> out, line
                self.bbx_counter += 1
                id_step += 1
            out.close()

            # raw_input('Continue?')

            # Remove the occluded objects
            index = n - 1
            while index >= 0:
                attrs = line_con[self.cur][index]
                # print '*', attrs, '*'
                if attrs[-1] + t_gap <= gap:
                    attrs[-1] += t_gap - 1
                else:
                    del line_con[self.cur][index]
                    del id_con[index]
                    self.train_set.deleteMotion(index)
                index -= 1

            line_con[self.nxt] = []
            # print head+step, results
        gtIn.close()
        print '     The results:', id_step, self.bbx_counter
Example #45
0
class TrackingByDetection(object):
    """(Forward/backward) tracking by detection

    Parameters
    ----------
    detect_func : func
        Detection function. Should take video frame as input and return list
        (or iterable) of detections as (left, top, right, bottom) tuples.
    detect_smallest : int, optional
        Smallest object (height, in pixels) that `detect_func` can detect.
        Defaults to any object.
    detect_min_size : float, optional
        Approximate size (in video height ratio) of the smallest object that
        should be detected. Defaults to any object.
    detect_every : float, optional
        When provided, `detect_func` is applied every `detect_every` seconds.
        Defaults to processing every frame.
    track_min_confidence : float, optional
        Kill trackers whose confidence goes below this value. Defaults to 10.
    track_min_overlap_ratio : float, optional
        Do not associate trackers and detections if their overlap ratio goes
        below this value. Defaults to 0.3.
    track_max_gap : float, optional
        Bridge gaps with duration shorter than this value.

    Usage
    -----
    >>> from pyannote.video import Video, TrackingByDetection
    >>> video = Video(path_to_video)
    >>> # load segmentation into shots
    >>> tracking = TrackingByDetection()
    >>> for face_track in tracking(video, shots):
    ...     # do something with face track
    ...     pass
    """

    def __init__(self, detect_func, detect_smallest=1,
                 detect_min_size=0.,
                 detect_every=0.,
                 track_min_confidence=10., track_min_overlap_ratio=0.3,
                 track_max_gap=0.):

        super(TrackingByDetection, self).__init__()

        self.detect_func = detect_func
        self.detect_smallest = detect_smallest
        self.detect_min_size = detect_min_size
        self.detect_every = detect_every

        self.track_min_confidence = track_min_confidence
        self.track_min_overlap_ratio = track_min_overlap_ratio
        self.track_max_gap = track_max_gap

        self._hungarian = Munkres()

    def _kill_tracker(self, identifier):
        """Kill specific tracker"""
        del self._trackers[identifier]
        del self._confidences[identifier]
        del self._previous[identifier]

    def _match(self, rectangle1, rectangle2):
        overlap = rectangle1.intersect(rectangle2).area()
        if ((overlap < self.track_min_overlap_ratio * rectangle1.area()) or
            (overlap < self.track_min_overlap_ratio * rectangle2.area())):
            overlap = 0.
        return overlap

    def _associate(self, trackers, detections):
        """Associate trackers and detections with Hungarian algorithm

        Parameters
        ----------
        trackers : dict
            Dictionary where values are current trackers
            and keys are trackers identifiers.
        detections : list
            List of detections

        Returns
        -------
        match : dict
            Dictionary where values are trackers
            and keys are matched detection indices.
        """

        n_trackers, n_detections = len(trackers), len(detections)

        if n_trackers < 1 or n_detections < 1:
            return dict()

        n = max(n_trackers, n_detections)
        overlap_area = np.zeros((n, n))

        # list of (identifier, tracker) tuple
        trackers_ = trackers.items()
        for t, (identifier, tracker) in enumerate(trackers_):
            position = tracker.get_position()
            for d, detection in enumerate(detections):
                rectangle = dlib.drectangle(*detection)
                overlap_area[t, d] = self._match(position, rectangle)

        # find the best one-to-one mapping
        match = {}
        mapping = self._hungarian.compute(np.max(overlap_area) - overlap_area)
        for t, d in mapping:

            if t >= n_trackers or d >= n_detections:
                continue

            if overlap_area[t, d] > 0.:
                identifier, _ = trackers_[t]
                match[d] = identifier

        return match

    def _track(self, direction=FORWARD):
        """Actual tracking based on existing detections"""

        if direction == FORWARD:
            frame_cache = self._frame_cache
        elif direction == BACKWARD:
            frame_cache = reversed(self._frame_cache)
        else:
            raise NotImplementedError()

        self._trackers = {}
        self._confidences = {}
        self._previous = {}
        new_identifier = 0

        for t, frame in frame_cache:

            # update trackers & end those with low confidence
            for identifier, tracker in list(self._trackers.items()):
                confidence = tracker.update(frame)
                self._confidences[identifier] = confidence
                if confidence < self.track_min_confidence:
                    self._kill_tracker(identifier)

            # match trackers with detections at time t
            detections = [d for _, d, status in self._tracking_graph[t]
                          if status == DETECTION]
            match = self._associate(self._trackers, detections)

            # process all matched trackers
            for d, identifier in match.items():

                # connect the previous position of the tracker
                # to the (current) associated detection
                current = (t, detections[d], DETECTION)
                self._tracking_graph.add_edge(
                    self._previous[identifier], current,
                    confidence=self._confidences[identifier])

                # end the tracker
                self._kill_tracker(identifier)

            # process all unmatched trackers
            for identifier, tracker in self._trackers.items():

                # connect the previous position of the tracker
                # to the current position of the tracker
                position = tracker.get_position()
                position = (
                    position.left(),
                    position.top(),
                    position.right(),
                    position.bottom()
                )
                current = (t, position, direction)
                self._tracking_graph.add_edge(
                    self._previous[identifier], current,
                    confidence=self._confidences[identifier])

                # save current position of the tracker for next iteration
                self._previous[identifier] = current

            # start new trackers for all detections
            for d, detection in enumerate(detections):

                # start new tracker
                new_tracker = dlib.correlation_tracker()
                new_tracker.start_track(frame, dlib.drectangle(*detection))
                self._trackers[new_identifier] = new_tracker

                # save previous (t, position, status) tuple
                current = (t, detection, DETECTION)
                self._previous[new_identifier] = current

                # increment tracker identifier
                new_identifier = new_identifier + 1

    def _fix(self, track):
        """Fix track by merging matching forward/backward tracklets"""

        fixed_track = []
        for t, group in itertools.groupby(sorted(track), key=lambda x: x[0]):

            group = list(group)

            # make sure all positions are overlap enough
            error = False
            for (_, pos1, _), (_, pos2, _) in itertools.combinations(group, 2):

                rectangle1 = dlib.drectangle(*pos1)
                rectangle2 = dlib.drectangle(*pos2)

                if self._match(rectangle1, rectangle2) == 0:
                    error = True
                    break

            # status
            status = "+".join(
                sorted((status for _, _, status in group),
                       key=lambda s: {DETECTION: 2,
                                      FORWARD: 1,
                                      BACKWARD: 3}[s]))
            if error:
                status = "error({0})".format(status)

            # average position
            pos = tuple(int(round(v))
                        for v in np.mean(np.vstack([p for _, p, _ in group]),
                                         axis=0))

            fixed_track.append((t, pos, status))

        return fixed_track

    def _fill_gaps(self, tracks):

        # sort tracks by start and end timestamps
        tracks = sorted(tracks, key=get_min_max_t)

        # build graph where nodes are tracks and where matching tracks
        # less than "track_max_gap" away are connected
        graph = nx.Graph()
        for i in xrange(len(tracks)):
            graph.add_node(i)

        for i, j in itertools.combinations(xrange(len(tracks)), 2):

            # only try to match tracks with a short gap between them
            ti = tracks[i][-1][0]
            tj = tracks[j][0][0]
            if (tj < ti) or (tj - ti > self.track_max_gap):
                continue

            # match tracks whose last and first position match
            rectangle1 = dlib.drectangle(*tracks[i][-1][1])
            rectangle2 = dlib.drectangle(*tracks[j][0][1])
            if self._match(rectangle1, rectangle2):
                graph.add_edge(i, j)

        # merge tracks that are in the same connected component
        merged_tracks = []
        for group in nx.connected_components(graph):
            track = [item for t in sorted(group) for item in tracks[t]]
            merged_tracks.append(track)

        return merged_tracks

    def _forward_backward(self):

        # forward tracking
        self._track(direction=FORWARD)

        # backward tracking
        self._track(direction=BACKWARD)

        # remove timestamps
        timestamps = [t for t in self._tracking_graph
                      if not isinstance(t, tuple)]

        self._tracking_graph.remove_nodes_from(timestamps)

        # tracks are connected components in tracking graph
        tracks = nx.connected_components(
            self._tracking_graph.to_undirected(reciprocal=False))

        # merge matching backward/forward tracks
        tracks = [self._fix(track) for track in tracks]

        # fill gaps
        tracks = self._fill_gaps(tracks)

        # sort tracks by start and end timestamps
        for track in sorted(tracks, key=get_min_max_t):
            yield track

    def _reset(self):
        """Reset tracking"""
        self._frame_cache = []
        self._tracking_graph = nx.DiGraph()

    def _normalize_track(self, track, frame_width, frame_height):
        normalized_track = []
        for (t, (left, top, right, bottom), status) in track:
            left = left / frame_width
            right = right / frame_width
            top = top / frame_height
            bottom = bottom / frame_height
            normalized_track.append((t, (left, top, right, bottom), status))
        return normalized_track

    def __call__(self, video, segmentation):
        """
        Parameters
        ----------
        video : Video
        segmentation :
        """

        # should detection be applied to every frame or once every "x" frames?
        if self.detect_every > 0.0:
            every_x_frames = int(self.detect_every * video.frame_rate)
        else:
            every_x_frames = 1

        # estimate downscaling ratio
        width, height = video.size
        ratio = 1.0
        if self.detect_min_size > 0.0:
            ratio = self.detect_smallest / (self.detect_min_size * height)
            ratio = min(1.0, ratio)

        # tell video instance how to downscale its frames
        # (and keep track of previous setting)
        old_frame_width, old_frame_height = video.frame_size
        frame_width = int(width * ratio)
        frame_height = int(height * ratio)
        video.frame_size = (frame_width, frame_height)

        segment_generator = get_segment_generator(segmentation)
        segment_generator.send(None)
        self._reset()

        for i, (t, frame) in enumerate(video):

            segment = segment_generator.send(t)

            if segment:

                # forward/backward tracking
                for track in self._forward_backward():
                    yield self._normalize_track(track, frame_width, frame_height)

                # start fresh for next segment
                self._reset()

            # cache frame (for faster tracking)
            self._frame_cache.append((t, frame))

            self._tracking_graph.add_node(t)

            # apply detection every x frames
            if i % every_x_frames == 0:
                for detection in self.detect_func(frame):
                    self._tracking_graph.add_edge(t, (t, detection, DETECTION))

        for track in self._forward_backward():
            yield self._normalize_track(track, frame_width, frame_height)

        # revert frame size to its original setting
        if self.detect_min_size > 0.0:
            video.frame_size = (old_frame_width, old_frame_height)
Example #46
0
class GN():
    def __init__(self, seq_index, tt, cuda=True):
        '''
        Evaluating with the MotMetrics
        :param seq_index: the number of the sequence
        :param tt: train_test
        :param length: the number of frames which is used for training
        :param cuda: True - GPU, False - CPU
        '''
        self.bbx_counter = 0
        self.seq_index = seq_index
        self.hungarian = Munkres()
        self.device = torch.device("cuda" if cuda else "cpu")
        self.tt = tt
        self.alpha = 0.7
        self.missingCounter = 0
        self.sideConnection = 0

        print '     Loading the model...'
        self.loadAModel()
        self.loadMModel()

        self.out_dir = t_dir + 'motmetrics_%s_7%s%s_tau_crowdeddecay/' % (
            type, recover_dir, u_dir)
        print self.out_dir
        if not os.path.exists(self.out_dir):
            os.mkdir(self.out_dir)
        else:
            deleteDir(self.out_dir)
            os.mkdir(self.out_dir)
        self.initOut()

    def initOut(self):
        print '     Loading Data...'
        self.a_train_set = ADatasetFromFolder(
            sequence_dir, '../MOT/MOT16/test/MOT16-%02d' % self.seq_index,
            tau_conf_score)
        self.m_train_set = MDatasetFromFolder(
            sequence_dir, '../MOT/MOT16/test/MOT16-%02d' % self.seq_index,
            tau_conf_score)

        detection_dir = self.out_dir + 'res_training_det.txt'
        res_training = self.out_dir + 'res_training.txt'  # the result of the training data
        self.createTxt(detection_dir)
        self.createTxt(res_training)
        self.copyLines(self.seq_index, 1, detection_dir, self.tt, 1)

        self.evaluation(1, self.tt, detection_dir, res_training)

    def getSeqL(self, info):
        # get the length of the sequence
        f = open(info, 'r')
        f.readline()
        for line in f.readlines():
            line = line.strip().split('=')
            if line[0] == 'seqLength':
                seqL = int(line[1])
        f.close()
        return seqL

    def copyLines(self, seq, head, gt_seq, tail=-1, tag=0):
        '''
        Copy the groun truth within [head, head+num]
        :param seq: the number of the sequence
        :param head: the head frame number
        :param tail: the number the clipped sequence
        :param gt_seq: the dir of the output file
        :return: None
        '''
        if tt_tag:
            basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq,
                                                              type)
        else:
            basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq,
                                                               type)
        print '     Testing on', basic_dir, 'Length:', self.tt
        seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini')

        det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt'
        seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir)
        inStream = open(seq_dir, 'r')

        outStream = open(gt_seq, 'w')
        for line in inStream.readlines():
            line = line.strip()
            attrs = line.split(',')
            f_num = int(attrs[0])
            if f_num >= head and f_num <= seqL:
                print >> outStream, line
        outStream.close()

        inStream.close()
        return seqL

    def createTxt(self, out_file):
        f = open(out_file, 'w')
        f.close()

    def loadAModel(self):
        from mot_model import uphi, ephi, vphi
        if edge_initial == 0:
            model_dir = 'App2_bb'
            name = '%s_7' % app_dir
            i_name = 'IoU'
        elif edge_initial == 1:
            model_dir = 'App2_bb'
            name = '%s_7' % app_dir
            i_name = 'Random'
        tail = 13
        self.AUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%02d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.AVphi = torch.load('../%s/Results/MOT16/%s/%s/vphi_%02d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.AEphi1 = torch.load('../%s/Results/MOT16/%s/%s/ephi1_%02d.pth' %
                                 (model_dir, i_name, name, tail)).to(
                                     self.device)
        self.AEphi2 = torch.load('../%s/Results/MOT16/%s/%s/ephi2_%02d.pth' %
                                 (model_dir, i_name, name, tail)).to(
                                     self.device)
        self.Au = torch.load('../%s/Results/MOT16/%s/%s/u_%02d.pth' %
                             (model_dir, i_name, name, tail))
        self.Au = self.Au.to(self.device)

    def loadMModel(self):
        from m_mot_model import uphi, ephi
        if edge_initial == 0:
            model_dir = 'Motion1_bb'
            name = 'all_7'
            i_name = 'IoU'
        elif edge_initial == 1:
            model_dir = 'Motion1_bb'
            name = 'all_7'
            i_name = 'Random'
        tail = 13
        self.MUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.MEphi = torch.load('../%s/Results/MOT16/%s/%s/ephi_%d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.Mu = torch.load('../%s/Results/MOT16/%s/%s/u_%d.pth' %
                             (model_dir, i_name, name, tail))
        self.Mu = self.Mu.to(self.device)

    def swapFC(self):
        self.cur = self.cur ^ self.nxt
        self.nxt = self.cur ^ self.nxt
        self.cur = self.cur ^ self.nxt

    def linearModel(self, out, attr1, attr2):
        # print 'I got you! *.*'
        t = attr1[-1]
        self.sideConnection += 1
        if t > f_gap:
            return
        frame = int(attr1[0])
        x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float(
            attr1[4]), float(attr1[5])
        x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float(
            attr2[4]), float(attr2[5])

        x_delta = (x2 - x1) / t
        y_delta = (y2 - y1) / t
        w_delta = (w2 - w1) / t
        h_delta = (h2 - h1) / 2

        for i in xrange(1, t):
            frame += 1
            x1 += x_delta
            y1 += y_delta
            w1 += w_delta
            h1 += h_delta
            attr1[0] = str(frame)
            attr1[2] = str(x1)
            attr1[3] = str(y1)
            attr1[4] = str(w1)
            attr1[5] = str(h1)
            line = ''
            for attr in attr1[:-1]:
                line += attr + ','
            if show_recovering:
                line += '1'
            else:
                line = line[:-1]
            print >> out, line
            self.bbx_counter += 1
        self.missingCounter += t - 1

    def evaluation(self, head, tail, gtFile, outFile):
        '''
        Evaluation on dets
        :param head: the head frame number
        :param tail: the tail frame number
        :param gtFile: the ground truth file name
        :param outFile: the name of output file
        :return: None
        '''
        gtIn = open(gtFile, 'r')
        self.cur, self.nxt = 0, 1
        line_con = [[], []]
        id_con = [[], []]
        id_step = 1

        a_step = head + self.a_train_set.setBuffer(head)
        m_step = head + self.m_train_set.setBuffer(head)
        if a_step != m_step:
            print 'Something is wrong!'
            print 'a_step =', a_step, ', m_step =', m_step
            raw_input('Continue?')

        while a_step < tail:
            # print '*********************************'
            a_t_gap = self.a_train_set.loadNext()
            m_t_gap = self.m_train_set.loadNext()
            if a_t_gap != m_t_gap:
                print 'Something is wrong!'
                print 'a_t_gap =', a_t_gap, ', m_t_gap =', m_t_gap
                raw_input('Continue?')
            a_step += a_t_gap
            m_step += m_step
            # print head+step, 'F',

            m_u_ = self.MUphi(self.m_train_set.E, self.m_train_set.V, self.Mu)

            # print 'Fo'
            a_m = self.a_train_set.m
            a_n = self.a_train_set.n
            m_m = self.m_train_set.m
            m_n = self.m_train_set.n

            if a_m != m_m or a_n != m_n:
                print 'Something is wrong!'
                print 'a_m = %d, m_m = %d' % (
                    a_m, m_m), ', a_n = %d, m_n = %d' % (a_n, m_n)
                raw_input('Continue?')
            # print 'm = %d, n = %d'%(m, n)
            if a_n == 0:
                print 'There is no detection in the rest of sequence!'
                break

            if id_step == 1:
                out = open(outFile, 'a')
                i = 0
                while i < a_m:
                    attrs = gtIn.readline().strip().split(',')
                    if float(attrs[6]) >= tau_conf_score:
                        attrs.append(1)
                        attrs[1] = str(id_step)
                        line = ''
                        for attr in attrs[:-1]:
                            line += attr + ','
                        if show_recovering:
                            line += '0'
                        else:
                            line = line[:-1]
                        print >> out, line
                        self.bbx_counter += 1
                        line_con[self.cur].append(attrs)
                        id_con[self.cur].append(id_step)
                        id_step += 1
                        i += 1
                out.close()

            i = 0
            while i < a_n:
                attrs = gtIn.readline().strip().split(',')
                if float(attrs[6]) >= tau_conf_score:
                    attrs.append(1)
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(-1)
                    i += 1

            # update the edges
            # print 'T',
            candidates = []
            E_CON, V_CON = [], []
            for edge in self.a_train_set.candidates:
                e, vs_index, vr_index = edge
                e = e.view(1, -1).to(self.device)
                vs = self.a_train_set.getApp(1, vs_index)
                vr = self.a_train_set.getApp(0, vr_index)

                e1 = self.AEphi1(e, vs, vr, self.Au)
                vr1 = self.AVphi(e1, vs, vr, self.Au)
                candidates.append((e1, vs, vr1, vs_index, vr_index))
                E_CON.append(e1)
                V_CON.append(vs)
                V_CON.append(vr1)

            E = self.a_train_set.aggregate(E_CON).view(1, -1)
            V = self.a_train_set.aggregate(V_CON).view(1, -1)
            u1 = self.AUphi(E, V, self.Au)

            ret = self.a_train_set.getRet()
            decay_tag = [0 for i in xrange(a_m)]
            for i in xrange(a_m):
                for j in xrange(a_n):
                    if ret[i][j] == 0:
                        decay_tag[i] += 1

            for i in xrange(len(self.a_train_set.candidates)):
                e1, vs, vr1, a_vs_index, a_vr_index = candidates[i]
                m_e, m_vs_index, m_vr_index = self.m_train_set.candidates[i]
                if a_vs_index != m_vs_index or a_vr_index != m_vr_index:
                    print 'Something is wrong!'
                    print 'a_vs_index = %d, m_vs_index = %d' % (a_vs_index,
                                                                m_vs_index)
                    print 'a_vr_index = %d, m_vr_index = %d' % (a_vr_index,
                                                                m_vr_index)
                    raw_input('Continue?')
                if ret[a_vs_index][a_vr_index] == tau_threshold:
                    continue

                e2 = self.AEphi2(e1, vs, vr1, u1)
                self.a_train_set.edges[a_vs_index][a_vr_index] = e1.data.view(
                    -1)

                a_tmp = F.softmax(e2)
                a_tmp = a_tmp.cpu().data.numpy()[0]

                m_e = m_e.to(self.device).view(1, -1)
                m_v1 = self.m_train_set.getMotion(1, m_vs_index)
                m_v2 = self.m_train_set.getMotion(
                    0, m_vr_index, m_vs_index,
                    line_con[self.cur][m_vs_index][-1])
                m_e_ = self.MEphi(m_e, m_v1, m_v2, m_u_)
                self.m_train_set.edges[m_vs_index][
                    m_vr_index] = m_e_.data.view(-1)
                m_tmp = F.softmax(m_e_)
                m_tmp = m_tmp.cpu().data.numpy()[0]

                t = line_con[self.cur][a_vs_index][-1]
                if decay_tag[a_vs_index] > 0:
                    A = min(float(a_tmp[0]) * pow(decay, t - 1), 1.0)
                    M = min(float(m_tmp[0]) * pow(decay, t - 1), 1.0)
                else:
                    A = float(a_tmp[0])
                    M = float(m_tmp[0])
                ret[a_vs_index][a_vr_index] = A * self.alpha + M * (1 -
                                                                    self.alpha)

            # self.a_train_set.showE(outFile)
            # self.m_train_set.showE(outFile)

            # for j in ret:
            #     print j
            results = self.hungarian.compute(ret)

            out = open(outFile, 'a')
            look_up = set(j for j in xrange(a_n))
            nxt = self.a_train_set.nxt
            for (i, j) in results:
                # print (i,j)
                if ret[i][j] >= tau_threshold:
                    continue
                e1 = self.a_train_set.edges[i][j].view(1, -1).to(self.device)
                vs = self.a_train_set.getApp(1, i)
                vr = self.a_train_set.getApp(0, j)

                vr1 = self.AVphi(e1, vs, vr, self.Au)
                self.a_train_set.detections[nxt][j][0] = vr1.data

                look_up.remove(j)
                self.m_train_set.updateVelocity(i, j,
                                                line_con[self.cur][i][-1],
                                                False)

                id = id_con[self.cur][i]
                id_con[self.nxt][j] = id
                attr1 = line_con[self.cur][i]
                attr2 = line_con[self.nxt][j]
                # print attrs
                attr2[1] = str(id)
                if attr1[-1] > 1:
                    # for the missing detections
                    self.linearModel(out, attr1, attr2)
                line = ''
                for attr in attr2[:-1]:
                    line += attr + ','
                if show_recovering:
                    line += '0'
                else:
                    line = line[:-1]
                print >> out, line
                self.bbx_counter += 1

            if u_update:
                self.Mu = m_u_.data
                self.Au = u1.data

            for j in look_up:
                self.m_train_set.updateVelocity(-1, j, tag=False)

            for i in xrange(a_n):
                if id_con[self.nxt][i] == -1:
                    id_con[self.nxt][i] = id_step
                    attrs = line_con[self.nxt][i]
                    attrs[1] = str(id_step)
                    line = ''
                    for attr in attrs[:-1]:
                        line += attr + ','
                    if show_recovering:
                        line += '0'
                    else:
                        line = line[:-1]
                    print >> out, line
                    self.bbx_counter += 1
                    id_step += 1
            out.close()

            # For missing & Occlusion
            index = 0
            for (i, j) in results:
                while i != index:
                    attrs = line_con[self.cur][index]
                    # print '*', attrs, '*'
                    if attrs[-1] + a_t_gap <= gap:
                        attrs[-1] += a_t_gap
                        line_con[self.nxt].append(attrs)
                        id_con[self.nxt].append(id_con[self.cur][index])
                        self.a_train_set.moveApp(index)
                        self.m_train_set.moveMotion(index)
                    index += 1
                if ret[i][j] >= tau_threshold:
                    attrs = line_con[self.cur][index]
                    # print '*', attrs, '*'
                    if attrs[-1] + a_t_gap <= gap:
                        attrs[-1] += a_t_gap
                        line_con[self.nxt].append(attrs)
                        id_con[self.nxt].append(id_con[self.cur][index])
                        self.a_train_set.moveApp(index)
                        self.m_train_set.moveMotion(index)
                index += 1
            while index < a_m:
                attrs = line_con[self.cur][index]
                # print '*', attrs, '*'
                if attrs[-1] + a_t_gap <= gap:
                    attrs[-1] += a_t_gap
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(id_con[self.cur][index])
                    self.a_train_set.moveApp(index)
                    self.m_train_set.moveMotion(index)
                index += 1

            # con = self.m_train_set.cleanEdge()
            # for i in xrange(len(con)-1, -1, -1):
            #     index = con[i]
            #     del line_con[self.nxt][index]
            #     del id_con[self.nxt][index]

            line_con[self.cur] = []
            id_con[self.cur] = []
            # print head+step, results
            self.a_train_set.swapFC()
            self.m_train_set.swapFC()
            self.swapFC()
        gtIn.close()
        print '     The results:', id_step, self.bbx_counter
    def compute_3rd_party_metrics(self):
        """
            Computes the metrics defined in
                - Stiefelhagen 2008: Evaluating Multiple Object Tracking Performance: The CLEAR MOT Metrics
                  MOTA, MOTAL, MOTP
                - Nevatia 2008: Global Data Association for Multi-Object Tracking Using Network Flows
                  mostly_tracked/partialy_tracked/mostly_lost
        """
        # construct Munkres object for Hungarian Method association
        hm = Munkres()
        max_cost = 1e9

        # go through all frames and associate ground truth and tracker results
        # groundtruth and tracker contain lists for every single frame containing lists of KITTI format detections
        seq_gt = self.groundtruth
        seq_dc = self.dcareas  # don't care areas
        seq_result_data = self.result_data
        seq_trajectories = defaultdict(list)
        seq_ignored = defaultdict(list)

        last_frame_ids = [[], []]

        for i_frame in tqdm(range(len(seq_gt))):
            frame_gts = seq_gt[i_frame]
            frame_dcs = seq_dc[i_frame]

            frame_results = seq_result_data[i_frame]
            # counting total number of ground truth and tracker objects
            self.n_gt += len(frame_gts)
            self.n_tr += len(frame_results)

            # use hungarian method to associate, using boxoverlap 0..1 as cost
            # build cost matrix
            cost_matrix = []
            frame_ids = [[], []]
            # loop over ground truth objects in one frame
            for gt in frame_gts:
                # save current ids
                frame_ids[0].append(gt.track_id)
                frame_ids[1].append(-1)
                gt.tracker = -1
                gt.id_switch = 0
                gt.fragmentation = 0
                cost_row = []
                # loop over tracked objects in one frame
                for result in frame_results:
                    # overlap == 1 means cost == 0
                    # Rect(cx, cy, l, w, angle)
                    r1 = Rect(gt.cx, gt.cy, gt.l, gt.w, gt.yaw)
                    r2 = Rect(result.cx, result.cy, result.l, result.w,
                              result.yaw)
                    iou = r1.intersection_over_union(r2)
                    cost = 1 - iou
                    # gating for boxoverlap
                    if cost <= self.min_overlap:
                        cost_row.append(cost)
                    else:
                        cost_row.append(max_cost)  # = 1e9
                # return
                cost_matrix.append(cost_row)
                # all ground truth trajectories are initially not associated
                # extend groundtruth trajectories lists (merge lists)
                seq_trajectories[gt.track_id].append(-1)
                seq_ignored[gt.track_id].append(False)

            if len(frame_gts) is 0:
                cost_matrix = [[]]
            # associate
            association_matrix = hm.compute(cost_matrix)

            # tmp variables for sanity checks
            tmptp = 0
            tmpfp = 0
            tmpfn = 0

            # mapping for tracker ids and ground truth ids
            for row, col in association_matrix:
                # apply gating on boxoverlap
                c = cost_matrix[row][col]
                if c < max_cost:
                    frame_gts[row].tracker = frame_results[col].track_id
                    frame_ids[1][row] = frame_results[col].track_id
                    frame_results[col].valid = True
                    frame_gts[row].distance = c
                    seq_trajectories[frame_gts[row].track_id][
                        -1] = frame_results[col].track_id

                    # true positives are only valid associations
                    self.tp += 1
                    tmptp += 1
                else:
                    # wrong data association
                    frame_gts[row].tracker = -1
                    self.fn += 1
                    tmpfn += 1

            # associate tracker and DontCare areas
            # ignore tracker in neighboring classes
            nignoredtracker = 0  # number of ignored tracker detections
            ignoredtrackers = dict()  # will associate the track_id with -1
            # if it is not ignored and 1 if it is
            # ignored;
            # this is used to avoid double counting ignored
            # cases, see the next loop

            # check for ignored FN/TP (truncation or neighboring object class)
            nignoredfn = 0  # the number of ignored false negatives
            nignoredtp = 0  # the number of ignored true positives

            gi = 0
            for gt in frame_gts:
                if gt.tracker < 0:
                    if gt.occlusion > self.max_occlusion or gt.truncation > self.max_truncation:
                        seq_ignored[gt.track_id][-1] = True
                        gt.ignored = True
                        nignoredfn += 1

                elif gt.tracker >= 0:
                    if gt.occlusion > self.max_occlusion or gt.truncation > self.max_truncation:
                        seq_ignored[gt.track_id][-1] = True
                        gt.ignored = True
                        nignoredtp += 1

                gi += 1

            # the below might be confusion, check the comments in __init__
            # to see what the individual statistics represent

            # correct TP by number of ignored TP due to truncation
            # ignored TP are shown as tracked in visualization
            tmptp -= nignoredtp

            # count the number of ignored true positives
            self.itp += nignoredtp

            # adjust the number of ground truth objects considered
            self.n_gt -= (nignoredfn + nignoredtp)

            # count the number of ignored ground truth objects
            self.n_igt += nignoredfn + nignoredtp

            # count the number of ignored tracker objects
            self.n_itr += nignoredtracker

            # false negatives = associated gt bboxes exceding association threshold + non-associated gt bboxes
            tmpfn += len(frame_gts) - len(association_matrix) - nignoredfn
            self.fn += len(frame_gts) - len(association_matrix) - nignoredfn
            self.ifn += nignoredfn

            # false positives = tracker bboxes - associated tracker bboxes
            tmpfp += len(frame_results) - tmptp - nignoredtracker - nignoredtp
            self.fp += len(
                frame_results) - tmptp - nignoredtracker - nignoredtp

            # sanity checks
            # - the number of true positives minues ignored true positives
            #   should be greater or equal to 0
            # - the number of false negatives should be greater or equal to 0
            # - the number of false positives needs to be greater or equal to 0
            #   otherwise ignored detections might be counted double
            # - the number of counted true positives (plus ignored ones)
            #   and the number of counted false negatives (plus ignored ones)
            #   should match the total number of ground truth objects
            # - the number of counted true positives (plus ignored ones)
            #   and the number of counted false positives
            #   plus the number of ignored tracker detections should
            #   match the total number of tracker detections; note that
            #   nignoredpairs is subtracted here to avoid double counting
            #   of ignored detection sin nignoredtp and nignoredtracker
            if tmptp < 0:
                print(tmptp, nignoredtp)
                raise NameError("Something went wrong! TP is negative")
            if tmpfn < 0:
                print(tmpfn, len(frame_gts), len(association_matrix),
                      nignoredfn, nignoredpairs)
                raise NameError("Something went wrong! FN is negative")
            if tmpfp < 0:
                print(tmpfp, len(frame_results), tmptp, nignoredtracker,
                      nignoredtp, nignoredpairs)
                raise NameError("Something went wrong! FP is negative")
            if tmptp + tmpfn is not len(frame_gts) - nignoredfn - nignoredtp:
                print("seqidx", seq_idx)
                print("frame ", f)
                print("TP    ", tmptp)
                print("FN    ", tmpfn)
                print("FP    ", tmpfp)
                print("nGT   ", len(frame_gts))
                print("nAss  ", len(association_matrix))
                print("ign GT", nignoredfn)
                print("ign TP", nignoredtp)
                raise NameError(
                    "Something went wrong! nGroundtruth is not TP+FN")
            if tmptp + tmpfp + nignoredtp + nignoredtracker is not len(
                    frame_results):
                print(seq_idx, f, len(frame_results), tmptp, tmpfp)
                print(len(association_matrix), association_matrix)
                raise NameError("Something went wrong! nTracker is not TP+FP")

            # loop over ground truth track_id
            # check for id switches or fragmentations
            for i, gt_id in enumerate(frame_ids[0]):
                if gt_id in last_frame_ids[0]:
                    idx = last_frame_ids[0].index(gt_id)
                    tid = frame_ids[1][i]
                    lid = last_frame_ids[1][idx]
                    if tid != lid and lid != -1 and tid != -1:
                        if frame_gts[i].truncation < self.max_truncation:
                            frame_gts[i].id_switch = 1
                    if tid != lid and lid != -1:
                        if frame_gts[i].truncation < self.max_truncation:
                            frame_gts[i].fragmentation = 1

            # save current index
            last_frame_ids = frame_ids

        # compute mostly_tracked/partialy_tracked/mostly_lost, fragments, idswitches for all groundtruth trajectories
        n_ignored_tr_total = 0

        if len(seq_trajectories) == 0:
            print("Error: There is no trajectories data")
            return
        n_ignored_tr = 0
        for g, ign_g in zip(seq_trajectories.values(), seq_ignored.values()):
            # all frames of this gt trajectory are ignored
            if all(ign_g):
                n_ignored_tr += 1
                n_ignored_tr_total += 1
                continue
            # all frames of this gt trajectory are not assigned to any detections
            if all([this == -1 for this in g]):
                self.mostly_lost += 1
                continue
            # compute tracked frames in trajectory
            last_id = g[0]
            # first detection (necessary to be in gt_trajectories) is always tracked
            tracked = 1 if g[0] >= 0 else 0
            lgt = 0 if ign_g[0] else 1
            for f in range(1, len(g)):
                if ign_g[f]:
                    last_id = -1
                    continue
                lgt += 1
                if last_id != g[f] and last_id != -1 and g[f] != -1 and g[
                        f - 1] != -1:
                    self.id_switches += 1
                if f < len(g) - 1 and g[f - 1] != g[f] and last_id != -1 and g[
                        f] != -1 and g[f + 1] != -1:
                    self.fragments += 1
                if g[f] != -1:
                    tracked += 1
                    last_id = g[f]
            # handle last frame; tracked state is handled in for loop (g[f]!=-1)
            if len(g) > 1 and g[f - 1] != g[f] and last_id != -1 and g[
                    f] != -1 and not ign_g[f]:
                self.fragments += 1

            # compute mostly_tracked/partialy_tracked/mostly_lost
            tracking_ratio = tracked / float(len(g) - sum(ign_g))
            if tracking_ratio > 0.8:
                self.mostly_tracked += 1
            elif tracking_ratio < 0.2:
                self.mostly_lost += 1
            else:  # 0.2 <= tracking_ratio <= 0.8
                self.partialy_tracked += 1

        if (self.n_gt_trajectories - n_ignored_tr_total) == 0:
            self.mostly_tracked = 0.
            self.partialy_tracked = 0.
            self.mostly_lost = 0.
        else:
            self.mostly_tracked /= float(self.n_gt_trajectories -
                                         n_ignored_tr_total)
            self.partialy_tracked /= float(self.n_gt_trajectories -
                                           n_ignored_tr_total)
            self.mostly_lost /= float(self.n_gt_trajectories -
                                      n_ignored_tr_total)

        # precision/recall
        if (self.fp + self.tp) == 0 or (self.tp + self.fn) == 0:
            self.recall = 0.
            self.precision = 0.
        else:
            self.recall = self.tp / float(self.tp + self.fn)
            self.precision = self.tp / float(self.fp + self.tp)
        return True
#Hungarian starts
#%%
def cost_matrix(y_pred, y, k):
    size_y = len(y)
    init_cost_mat = np.zeros((k, k))
    for i in range(k):
        for j in range(k):
            bool_array = np.logical_and(y_pred == i, y == j)
            init_cost_mat[i][j] = np.sum(bool_array)
    return (1 - init_cost_mat)


#%%
# y_pred1
mun = Munkres()
index = mun.compute(cost_matrix(y_pred1, y, n_digits))
mp = {prev: cur for (prev, cur) in index}
munkres_label = np.array([mp[i] for i in y_pred1])
cnf_mat = confusion_matrix(y, munkres_label, labels=range(n_digits))
accuracy = np.trace(cnf_mat, dtype=float) / np.sum(cnf_mat)

#%%
# y_pred
mun = Munkres()
index = mun.compute(cost_matrix(y_pred, y, n_digits))
mp = {prev: cur for (prev, cur) in index}
munkres_label = np.array([mp[i] for i in y_pred])
cnf_mat = confusion_matrix(y, munkres_label, labels=range(n_digits))
accuracy = np.trace(cnf_mat, dtype=float) / np.sum(cnf_mat)
#%%
#Spectral_Clustering_Starts
Example #49
0
def main():
    gt_file = './ground-truth/armstrong-setcore-20171009.json'
    # warning_dir = './cause-effect/warnings/'
    warning_dir = '/Users/tozammel/cause/isi-code/effect-forecasting-models/warnings_jul_sep_17/armstrong_malicious-email/'

    start_date = datetime.date(2017, 7, 1)
    end_date = datetime.date(2017, 7, 31)
    target_org = 'armstrong'

    # Potentially filter by event type
    #   None -> Score for ALL event types
    #   Otherwise, restrict to 'endpoint-malware', 'malicious-email', or 'malicious-destination'
    event_type = None

    # First need to parse input data
    warnings = load_warnings(warning_dir, target_org, event_type, start_date,
                             end_date)
    events = load_gt(gt_file, target_org, event_type, start_date, end_date)

    print("# warnings = %d" % len(warnings))
    print("# events = %d" % len(events))

    # Now need to perform matching on warnings + events
    # To do this first have to score every possible warning-event pair
    # The official pair_objects.py is heavily dependent on python classes *not* provided to us by govt, so we recreate here
    M = Metrics()
    matching_matrix = np.zeros((len(events), len(warnings)))
    matching_dict = dict()
    for e_idx in range(len(events)):
        for w_idx in range(len(warnings)):
            # Check if we meet base criteria threshold
            if M.base_criteria(events[e_idx], warnings[w_idx]):
                # If so, calculate quality score
                pair = Pair.build(warnings[w_idx], events[e_idx],
                                  'fake-performer', 'fake-provider')
                matching_matrix[e_idx, w_idx] = -pair.quality
                matching_dict["%d,%d" % (e_idx, w_idx)] = pair

    # Now do Hungarian matching
    munk = Munkres()
    pairings = munk.compute(matching_matrix.tolist())
    valid_pairings = list(
        filter(lambda p: matching_matrix[p[0], p[1]] != 0, pairings))

    nMatched = len(valid_pairings)
    nUnmatchedGT = len(events) - nMatched
    nUnmatchedW = len(warnings) - nMatched

    avg_qs = 0
    for e_idx, w_idx in valid_pairings:
        # pair = matching_dict["%d,%d" % (e_idx, w_idx)]
        # avg_qs += pair.quality
        avg_qs += matching_matrix[e_idx, w_idx]

    avg_qs /= len(valid_pairings)
    avg_qs = -1 * avg_qs

    # calculate recall
    recall = nMatched / (nMatched + nUnmatchedGT)

    # calculate precision  (Srawls: Note: comment below is straight from official code, not mine)
    # should these include warns and gts from the previous month?
    precision = nMatched / (nMatched + nUnmatchedW)

    print("Precision = %0.2f%%" % (100 * precision))
    print("Recall = %0.2f%%" % (100 * recall))
    print("Average Quality Score = %0.2f" % avg_qs)

    return
Example #50
0
class AutoFormationDetector(object):
    """docstring for TrackingAnalysis
	This class for running AutoFormationDetector

	Args:
		params_dict(dict) : Dictionary of Parameters
		data_dict(dict) : Dictionary of Input Tracking data
		range_dict(dict) : Dictionary of Pitch Range
	"""
    def __init__(self, params_dict, data_dict, range_dict=None):
        self.__dict__ = params_dict.copy()
        self.data_dict = data_dict

        # get range_dict
        if not range_dict:
            self.range_dict = {'xmin': [], 'xmax': [], 'ymin': [], 'ymax': []}
            for k, data_array in self.data_dict.items():
                xmin, ymin = data_array.reshape(-1, 2).min(axis=0)
                xmax, ymax = data_array.reshape(-1, 2).max(axis=0)

                self.range_dict['xmin'].append(xmin)
                self.range_dict['xmax'].append(xmax)
                self.range_dict['ymin'].append(ymin)
                self.range_dict['ymax'].append(ymax)

            self.range_dict = {
                k: np.min(v) if 'min' in k else np.max(v)
                for k, v in self.range_dict.items()
            }

        # define munk
        self.munk = Munkres()

    def compute_entropy(self, data_array):
        """
		this module to compute entropy

		Args:
			data_array(np.ndarray) : dataset of tracking data, shape=(T, n_players, 2)

		Returns:
			- list of scipy.stats.multivariate_normal object
			- mean value of each position's KL-Divergence
			- list of KL-Divergence
		"""

        x, y = np.mgrid[
            self.range_dict['xmin']:self.range_dict['xmax']:self.mesh_size,
            self.range_dict['ymin']:self.range_dict['ymax']:self.mesh_size]
        pos = np.empty(x.shape + (2, ))
        pos[:, :, 0] = x
        pos[:, :, 1] = y

        rv_list = [
            multivariate_normal(mean=np.mean(data, axis=0), cov=np.cov(data.T))
            for data in data_array
        ]
        Pn_list = [rv.pdf(pos) for rv in rv_list]

        P = np.mean(np.array(Pn_list), axis=0)

        Vn_list = []

        for i, Pn in enumerate(Pn_list):
            Vn = entropy(Pn, P)
            Vn[Vn == np.inf] = 0
            Vn[np.isnan(Vn)] = 0
            Vn_list.append(Vn)

        V = np.mean(Vn_list)

        return rv_list, V, Pn_list

    def optimize_role_distribution(self, data_array, key=None):
        """
		this module to optimize role distributions

		Args:
			key : name of data
			data_array(list) : shape = (T, n_players, 2)

		Returns:
			- list of optimized multivaiate_normal objects (list)
		"""

        # initialize gaussian_kde by all time frames
        rv_list, V, _ = self.compute_entropy(data_array.transpose(1, 0, 2))
        V_pre = V
        attacking_direction = 'left' if 'Home' in key else 'right' if 'Away' in key else None

        if key:
            plot_formation_distribution(
                rv_list, os.path.join(self.fig_dir, key + '_init.png'),
                self.range_dict, self.mesh_size, attacking_direction)

        # optimize algorithm
        V_list = []
        V_list.append(V)
        for _iter in range(self.n_iterations):
            roles_list = []
            start_time = time.time()
            for t, data in tqdm(enumerate(data_array)):
                Et = np.array([[
                    -np.log(rv.pdf(loc)) if rv.pdf(loc) != 0 else np.inf
                    for rv in rv_list
                ] for loc in data])
                roles = [r_tuple[1] for r_tuple in self.munk.compute(Et)]
                roles_list.append(roles)

            data_array = np.array(
                [data[roles] for (data, roles) in zip(data_array, roles_list)])
            # kde_list, V, _ = self.compute_entropy(data_array.transpose(1,0,2))
            rv_list, V, _ = self.compute_entropy(data_array.transpose(1, 0, 2))
            print('diff of V at iteration {}: {} ({} [sec])'.format(
                _iter, V_pre - V,
                time.time() - start_time))

            if V_pre - V <= 0 or np.isnan(V):
                if _iter != 0:
                    # kde_list = kde_list_pre
                    rv_list = rv_list_pre
                break

            V_pre = V
            V_list.append(V)
            rv_list_pre = rv_list

        if key:
            plot_formation_distribution(
                rv_list, os.path.join(self.fig_dir, key + '_opt.png'),
                self.range_dict, self.mesh_size, attacking_direction)

            # save decrease of V each iterations
            plt.figure(figsize=(5, 3))
            plt.plot(V_list)
            plt.xlabel('number of iterations')
            plt.ylabel('V')
            plt.savefig(os.path.join(self.fig_dir, key + '_V.png'))
            plt.close()

        return rv_list

    def run(self):
        """
		this module to estimating set of role distribution, 
		and clustering all set of role distribution to K
		"""

        # optimize role distribution for each data
        if self.load:
            print('loading role distribution ...')
            self.rv_dict = load_model(self.modeldir)
        else:
            print('optimizing role distribution ...')
            self.rv_dict = {}
            for n, (key, data_array) in enumerate(self.data_dict.items()):
                print(f'optimize -> {key} ({n+1}/{len(self.data_dict)})')
                rv_list = self.optimize_role_distribution(data_array, key)

                # self.kde_dict[key] = kde_list
                self.rv_dict[key] = rv_list

            save_model(self.rv_dict, self.modeldir)

        # agglomerative clustering based on EMD(=Wasserstein distance)
        print('Running Agglomerative Clustering of role_distribution')
        emd_matrix = compute_emd(list(self.rv_dict.values()), self.range_dict)
        agg = AgglomerativeClustering(n_clusters=self.n_clusters,
                                      affinity='precomputed',
                                      linkage='average')
        k_array = agg.fit_predict(emd_matrix)

        self.k_list = []
        for i, key in enumerate(self.rv_dict.keys()):
            print(f'{key} = {k_array[i]}')
            self.k_list.append(k_array[i])

        print('Plotting Clustering Results')
        plot_mean_formation_distribution(
            self.k_list, self.rv_dict,
            os.path.join(self.fig_dir, 'formation_clustering_results'),
            self.range_dict)
Example #51
0
class GN():
    def __init__(self, seq_index, tt, a, cuda=True):
        '''
        Evaluating with the MotMetrics
        :param seq_index: the number of the sequence
        :param tt: train_test
        :param length: the number of frames which is used for training
        :param cuda: True - GPU, False - CPU
        '''
        self.bbx_counter = 0
        self.seq_index = seq_index
        self.hungarian = Munkres()
        self.device = torch.device("cuda" if cuda else "cpu")
        self.tt = tt
        self.alpha = a
        self.missingCounter = 0
        self.sideConnection = 0

        print '     Loading the model...'
        self.loadAModel()
        self.loadMModel()

        self.out_dir = t_dir + 'motmetrics_%s_show/' % (type)
        print '		', self.out_dir
        if not os.path.exists(self.out_dir):
            os.mkdir(self.out_dir)
        else:
            deleteDir(self.out_dir)
            os.mkdir(self.out_dir)
        self.initWin()
        self.initOut()

    def initWin(self):
        self.color = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
        self.img_dir = '../MOT/MOT16/test/MOT16-%02d/img1/' % self.seq_index
        self.pre_win = 'Show/Previous'

        self.cur_win = 'Show/Current'

    def initOut(self):
        print '     Loading Data...'
        self.a_train_set = ADatasetFromFolder(
            sequence_dir, '../MOT/MOT16/test/MOT16-%02d' % self.seq_index)
        self.m_train_set = MDatasetFromFolder(
            sequence_dir, '../MOT/MOT16/test/MOT16-%02d' % self.seq_index)

        # gt_training = self.out_dir + 'gt_training.txt'  # the gt of the training data
        # self.copyLines(self.seq_index, 1, gt_training, self.tt)

        detection_dir = self.out_dir + 'res_training_det.txt'
        res_training = self.out_dir + 'res_training.txt'  # the result of the training data
        self.createTxt(detection_dir)
        self.createTxt(res_training)
        self.copyLines(self.seq_index, 1, detection_dir, self.tt, 1)

        self.evaluation(1, self.tt, detection_dir, res_training)

    def getSeqL(self, info):
        # get the length of the sequence
        f = open(info, 'r')
        f.readline()
        for line in f.readlines():
            line = line.strip().split('=')
            if line[0] == 'seqLength':
                seqL = int(line[1])
        f.close()
        return seqL

    def copyLines(self, seq, head, gt_seq, tail=-1, tag=0):
        '''
        Copy the groun truth within [head, head+num]
        :param seq: the number of the sequence
        :param head: the head frame number
        :param tail: the number the clipped sequence
        :param gt_seq: the dir of the output file
        :return: None
        '''
        if tt_tag:
            basic_dir = '../MOT/MOT%d/test/MOT%d-%02d-%s/' % (year, year, seq,
                                                              type)
        else:
            basic_dir = '../MOT/MOT%d/train/MOT%d-%02d-%s/' % (year, year, seq,
                                                               type)
        print '     Testing on', basic_dir, 'Length:', self.tt
        seqL = tail if tail != -1 else self.getSeqL(basic_dir + 'seqinfo.ini')

        det_dir = 'gt/gt_det.txt' if test_gt_det else 'det/det.txt'
        seq_dir = basic_dir + ('gt/gt.txt' if tag == 0 else det_dir)
        inStream = open(seq_dir, 'r')

        outStream = open(gt_seq, 'w')
        for line in inStream.readlines():
            line = line.strip()
            attrs = line.split(',')
            f_num = int(attrs[0])
            if f_num >= head and f_num <= seqL:
                print >> outStream, line
        outStream.close()

        inStream.close()
        return seqL

    def createTxt(self, out_file):
        f = open(out_file, 'w')
        f.close()

    def loadAModel(self):
        from mot_model import uphi, ephi
        if edge_initial == 0:
            model_dir = 'MOT'
            name = 'all_det_ft'
            i_name = 'IoU'
        elif edge_initial == 1:
            model_dir = 'Appearance'
            name = 'all_7_CE'
            i_name = 'Random'
        tail = 10
        self.AUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%02d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.AEphi = torch.load('../%s/Results/MOT16/%s/%s/ephi_%02d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.Au = torch.load('../%s/Results/MOT16/%s/%s/u_%02d.pth' %
                             (model_dir, i_name, name, tail))
        self.Au = self.Au.to(self.device)

    def loadMModel(self):
        from m_mot_model import uphi, ephi
        if edge_initial == 0:
            model_dir = 'MOT_Motion'
            name = 'all_v2_4'
            i_name = 'IoU'
        elif edge_initial == 1:
            model_dir = 'Motion'
            name = 'all_7_CE'
            i_name = 'Random'
        tail = 10
        self.MUphi = torch.load('../%s/Results/MOT16/%s/%s/uphi_%d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.MEphi = torch.load('../%s/Results/MOT16/%s/%s/ephi_%d.pth' %
                                (model_dir, i_name, name, tail)).to(
                                    self.device)
        self.Mu = torch.load('../%s/Results/MOT16/%s/%s/u_%d.pth' %
                             (model_dir, i_name, name, tail))
        self.Mu = self.Mu.to(self.device)

    def swapFC(self):
        self.cur = self.cur ^ self.nxt
        self.nxt = self.cur ^ self.nxt
        self.cur = self.cur ^ self.nxt

    def linearModel(self, out, attr1, attr2):
        # print 'I got you! *.*'
        t = attr1[-1]
        self.sideConnection += 1
        if t > f_gap:
            return
        frame = int(attr1[0])
        x1, y1, w1, h1 = float(attr1[2]), float(attr1[3]), float(
            attr1[4]), float(attr1[5])
        x2, y2, w2, h2 = float(attr2[2]), float(attr2[3]), float(
            attr2[4]), float(attr2[5])

        x_delta = (x2 - x1) / t
        y_delta = (y2 - y1) / t
        w_delta = (w2 - w1) / t
        h_delta = (h2 - h1) / 2

        for i in xrange(1, t):
            frame += 1
            x1 += x_delta
            y1 += y_delta
            w1 += w_delta
            h1 += h_delta
            attr1[0] = str(frame)
            attr1[2] = str(x1)
            attr1[3] = str(y1)
            attr1[4] = str(w1)
            attr1[5] = str(h1)
            line = ''
            for attr in attr1[:-1]:
                line += attr + ','
            if show_recovering:
                line += '1'
            else:
                line = line[:-1]
            print >> out, line
            self.bbx_counter += 1
        self.missingCounter += t - 1

    def evaluation(self, head, tail, gtFile, outFile):
        '''
        Evaluation on dets
        :param head: the head frame number
        :param tail: the tail frame number
        :param gtFile: the ground truth file name
        :param outFile: the name of output file
        :return: None
        '''
        gtIn = open(gtFile, 'r')
        self.cur, self.nxt = 0, 1

        imgs = [None, None]  # 0 - previous img, 1 - current img
        going_tag = 0  # 0 - frame by frame, 1 - goto going_f

        line_con = [[], []]
        id_con = [[], []]
        id_step = 1

        a_step = head + self.a_train_set.setBuffer(head)
        m_step = head + self.m_train_set.setBuffer(head)
        if a_step != m_step:
            print 'Something is wrong!'
            print 'a_step =', a_step, ', m_step =', m_step
            raw_input('Continue?')

        imgs[self.cur] = readImg(self.img_dir + '%06d.jpg' % a_step)
        going_f = a_step
        while a_step < tail:
            # print '*********************************'
            if going_f <= a_step:
                going_tag = 0

            a_t_gap = self.a_train_set.loadNext()
            m_t_gap = self.m_train_set.loadNext()
            if a_t_gap != m_t_gap:
                print 'Something is wrong!'
                print 'a_t_gap =', a_t_gap, ', m_t_gap =', m_t_gap
                raw_input('Continue?')
            a_step += a_t_gap
            m_step += m_step
            # print head+step, 'F',

            a_u_ = self.AUphi(self.a_train_set.E, self.a_train_set.V, self.Au)
            m_u_ = self.MUphi(self.m_train_set.E, self.m_train_set.V, self.Mu)

            # print 'Fo'
            a_m = self.a_train_set.m
            a_n = self.a_train_set.n
            m_m = self.m_train_set.m
            m_n = self.m_train_set.n

            if a_m != m_m or a_n != m_n:
                print 'Something is wrong!'
                print 'a_m = %d, m_m = %d' % (
                    a_m, m_m), ', a_n = %d, m_n = %d' % (a_n, m_n)
                raw_input('Continue?')
            # print 'm = %d, n = %d'%(m, n)
            if a_n == 0:
                print 'There is no detection in the rest of sequence!'
                break

            if id_step == 1:
                out = open(outFile, 'a')
                i = 0
                while i < a_m:
                    attrs = gtIn.readline().strip().split(',')
                    if float(attrs[6]) >= tau_conf_score:
                        attrs.append(1)
                        attrs[1] = str(id_step)
                        line = ''
                        for attr in attrs[:-1]:
                            line += attr + ','
                        if show_recovering:
                            line += '0'
                        else:
                            line = line[:-1]
                        print >> out, line
                        self.bbx_counter += 1

                        # draw the rectangle
                        x, y = int(float(attrs[2])), int(float(attrs[3]))
                        w, h = int(float(attrs[4])), int(float(attrs[5]))
                        cv2.rectangle(imgs[self.cur], (x, y), (x + w, y + h),
                                      self.color[0], 2)
                        cv2.putText(imgs[self.cur], attrs[1] + '_B',
                                    (x + 3, y + 15), font, 0.6, self.color[0],
                                    2, cv2.LINE_AA)

                        line_con[self.cur].append(attrs)
                        id_con[self.cur].append(id_step)
                        id_step += 1
                        i += 1
                out.close()

            print '     Frame:', a_step
            print id_con[self.cur]
            imgs[self.nxt] = readImg(self.img_dir + '%06d.jpg' % a_step)
            i = 0
            while i < a_n:
                attrs = gtIn.readline().strip().split(',')
                if float(attrs[6]) >= tau_conf_score:
                    # if int(attrs[0]) != a_step:
                    #     print attrs
                    #     print 'Something is Wrong! %d != %d'%(int(attrs[0]), a_step)
                    attrs.append(1)
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(-1)
                    i += 1

            # update the edges
            # print 'T',
            ret = self.a_train_set.getRet()
            for i in xrange(len(self.a_train_set.candidates)):
                a_e, a_vs_index, a_vr_index = self.a_train_set.candidates[i]
                m_e, m_vs_index, m_vr_index = self.m_train_set.candidates[i]
                if a_vs_index != m_vs_index or a_vr_index != m_vr_index:
                    print 'Something is wrong!'
                    print 'a_vs_index = %d, m_vs_index = %d' % (a_vs_index,
                                                                m_vs_index)
                    print 'a_vr_index = %d, m_vr_index = %d' % (a_vr_index,
                                                                m_vr_index)
                    raw_input('Continue?')
                if ret[a_vs_index][a_vr_index] == 1.0:
                    continue
                a_e = a_e.to(self.device).view(1, -1)
                a_v1 = self.a_train_set.getApp(1, a_vs_index)
                a_v2 = self.a_train_set.getApp(0, a_vr_index)
                a_e_ = self.AEphi(a_e, a_v1, a_v2, a_u_)
                self.a_train_set.edges[a_vs_index][
                    a_vr_index] = a_e_.data.view(-1)
                a_tmp = F.softmax(a_e_)
                a_tmp = a_tmp.cpu().data.numpy()[0]

                m_e = m_e.to(self.device).view(1, -1)
                m_v1 = self.m_train_set.getMotion(1, m_vs_index)
                m_v2 = self.m_train_set.getMotion(
                    0, m_vr_index, m_vs_index,
                    line_con[self.cur][m_vs_index][-1])
                m_e_ = self.MEphi(m_e, m_v1, m_v2, m_u_)
                self.m_train_set.edges[m_vs_index][
                    m_vr_index] = m_e_.data.view(-1)
                m_tmp = F.softmax(m_e_)
                m_tmp = m_tmp.cpu().data.numpy()[0]

                ret[a_vs_index][a_vr_index] = float(
                    a_tmp[0]) * self.alpha + float(m_tmp[0]) * (1 - self.alpha)

            # self.a_train_set.showE(outFile)
            # self.m_train_set.showE(outFile)

            # for j in ret:
            #     print j
            results = self.hungarian.compute(ret)

            out = open(outFile, 'a')
            look_up = set(j for j in xrange(a_n))
            for (i, j) in results:
                # print (i,j)
                if ret[i][j] >= tau_threshold:
                    continue
                look_up.remove(j)
                self.m_train_set.updateVelocity(i, j,
                                                line_con[self.cur][i][-1],
                                                False)

                id = id_con[self.cur][i]
                id_con[self.nxt][j] = id
                attr1 = line_con[self.cur][i]
                attr2 = line_con[self.nxt][j]
                attr2[1] = str(id)
                if attr1[-1] > 1:
                    # for the missing detections & side connection
                    self.linearModel(out, attr1, attr2)
                line = ''
                for attr in attr2[:-1]:
                    line += attr + ','
                if show_recovering:
                    line += '0'
                else:
                    line = line[:-1]
                print >> out, line
                self.bbx_counter += 1
                if id == 23:
                    print id_con[self.nxt][j], line_con[self.nxt][j]

            for j in look_up:
                self.m_train_set.updateVelocity(-1, j, tag=False)

            for i in xrange(a_n):
                attrs = line_con[self.nxt][i]
                color = self.color[1]
                state = '_C'
                if id_con[self.nxt][i] == -1:
                    color = self.color[0]
                    state = '_B'
                    id_con[self.nxt][i] = id_step
                    attrs[1] = str(id_step)
                    line = ''
                    for attr in attrs[:-1]:
                        line += attr + ','
                    if show_recovering:
                        line += '0'
                    else:
                        line = line[:-1]
                    print >> out, line
                    self.bbx_counter += 1
                    id_step += 1

                # if i not in look_up:
                #     color = self.color[2]
                #     state = '_M'

                # draw the rectrangle
                x, y = int(float(attrs[2])), int(float(attrs[3]))
                w, h = int(float(attrs[4])), int(float(attrs[5]))
                cv2.rectangle(imgs[self.nxt], (x, y), (x + w, y + h), color, 2)
                cv2.putText(imgs[self.nxt], attrs[1] + state, (x + 3, y + 15),
                            font, 0.6, color, 2, cv2.LINE_AA)

            out.close()

            # visualization
            cv2.imwrite(self.pre_win + '.png', imgs[self.cur])
            cv2.imwrite(self.cur_win + '.png', imgs[self.nxt])
            for i in xrange(a_m):
                if id_con[self.cur][i] == 23:
                    print line_con[self.cur][i]
                    break
            if going_tag == 0:
                id1, id2 = 1, 1
                while id1 != -1:
                    inp = raw_input('Input:')
                    if ',' in inp:
                        nums = inp.split(',')
                        id1, id2 = int(nums[0]), int(nums[1])
                        if id1 != -1:
                            id_tag = int(nums[2])
                            if id_tag:
                                # t -> t-1
                                for i in xrange(a_n):
                                    if id_con[self.nxt][i] == id1:
                                        id1 = i
                                        break
                                for i in xrange(a_m):
                                    if id_con[self.cur][i] == id2:
                                        id2 = i
                                        break
                                print ret[id2][id1]
                            else:
                                # t-1 -> t
                                for i in xrange(a_n):
                                    if id_con[self.cur][i] == id1:
                                        id1 = i
                                        break
                                for i in xrange(a_m):
                                    if id_con[self.nxt][i] == id2:
                                        id2 = i
                                        break
                                print ret[id1][id2]
                        else:
                            going_tag = 1
                            going_f = id2
                    else:
                        id1 = int(inp)
                        if id1 != -1:
                            for i in xrange(a_n):
                                if id_con[self.nxt][i] == id1:
                                    id1 = i
                                    break
                            for i in xrange(a_n):
                                if ret[i][id1] != 1:
                                    print id_con[self.cur][i], ret[i][id1]

            # For missing & Occlusion
            index = 0
            for (i, j) in results:
                while i != index:
                    # if a_step > 80:
                    #     print id_con[self.cur][index], line_con[self.cur][index]
                    attrs = line_con[self.cur][index]
                    # print '*', attrs, '*'
                    if attrs[-1] + a_t_gap <= gap:
                        attrs[-1] += a_t_gap
                        line_con[self.nxt].append(attrs)
                        id_con[self.nxt].append(id_con[self.cur][index])
                        self.a_train_set.moveApp(index)
                        self.m_train_set.moveMotion(index)
                    index += 1

                if ret[i][j] >= tau_threshold:
                    # if a_step > 80:
                    #     print id_con[self.cur][index], line_con[self.cur][index]
                    attrs = line_con[self.cur][index]
                    # print '*', attrs, '*'
                    if attrs[-1] + a_t_gap <= gap:
                        attrs[-1] += a_t_gap
                        line_con[self.nxt].append(attrs)
                        id_con[self.nxt].append(id_con[self.cur][index])
                        self.a_train_set.moveApp(index)
                        self.m_train_set.moveMotion(index)

                index += 1
            while index < a_m:
                if a_step > 80:
                    print id_con[self.cur][index], line_con[self.cur][index]
                attrs = line_con[self.cur][index]
                # print '*', attrs, '*'
                if attrs[-1] + a_t_gap <= gap:
                    attrs[-1] += a_t_gap
                    line_con[self.nxt].append(attrs)
                    id_con[self.nxt].append(id_con[self.cur][index])
                    self.a_train_set.moveApp(index)
                    self.m_train_set.moveMotion(index)
                index += 1

            # con = self.m_train_set.cleanEdge()
            # for i in xrange(len(con)-1, -1, -1):
            #     index = con[i]
            #     del line_con[self.nxt][index]
            #     del id_con[self.nxt][index]

            line_con[self.cur] = []
            id_con[self.cur] = []
            cv2.imwrite('Show/%06d.png' % (a_step - 1), imgs[self.cur])
            imgs[self.cur] = []
            # print head+step, results
            self.a_train_set.swapFC()
            self.m_train_set.swapFC()
            self.swapFC()
        gtIn.close()
        print '     The results:', id_step, self.bbx_counter
Example #52
0
    def allocate(self):
        from debate.models import AdjudicatorAllocation

        # remove trainees
        self.adjudicators = filter(lambda a: a.score >= self.MIN_SCORE,
                                   self.adjudicators)

        # sort adjudicators and debates in descending score/importance
        self.adjudicators_sorted = list(self.adjudicators)
        shuffle(self.adjudicators_sorted)  # randomize equally-ranked judges
        self.adjudicators_sorted.sort(key=lambda a: a.score, reverse=True)
        self.debates_sorted = list(self.debates)
        self.debates_sorted.sort(key=lambda a: a.importance, reverse=True)

        n_adjudicators = len(self.adjudicators)
        n_debates = len(self.debates)

        n_solos = n_debates - (n_adjudicators - n_debates) / 2

        # get adjudicators that can adjudicate solo
        chairs = self.adjudicators_sorted[:n_solos]
        #chairs = [a for a in self.adjudicators_sorted if a.score >
        #          self.CHAIR_CUTOFF]

        # get debates that will be judged by solo adjudicators
        chair_debates = self.debates_sorted[:len(chairs)]

        panel_debates = self.debates_sorted[len(chairs):]
        panellists = [a for a in self.adjudicators_sorted if a not in chairs]

        assert len(panel_debates) * 3 <= len(panellists)

        m = Munkres()
        # TODO I think "chairs" actually means "solos", rename variables if correct
        if len(chairs) > 0:

            print "costing chairs"

            n = len(chairs)

            cost_matrix = [[0] * n for i in range(n)]

            for i, debate in enumerate(chair_debates):
                for j, adj in enumerate(chairs):
                    cost_matrix[i][j] = self.calc_cost(debate, adj)

            print "optimizing"

            indexes = m.compute(cost_matrix)

            total_cost = 0
            for r, c in indexes:
                total_cost += cost_matrix[r][c]

            print 'total cost for solos', total_cost
            print 'number of solo debates', n

            result = ((chair_debates[i], chairs[j]) for i, j in indexes
                      if i < len(chair_debates))
            alloc = [AdjudicatorAllocation(d, c) for d, c in result]

            print[(a.debate, a.chair) for a in alloc]

        else:
            print "No solo adjudicators."
            alloc = []

        # do panels
        n = len(panel_debates)

        npan = len(panellists)

        if npan:
            print "costing panellists"

            # matrix is square, dummy debates have cost 0
            cost_matrix = [[0] * npan for i in range(npan)]
            for i, debate in enumerate(panel_debates):
                for j in range(3):

                    # for the top half of these debates, the final panellist
                    # can be of lower quality than the other 2
                    if i < npan / 2 and j == 2:
                        adjustment = -1.0
                    else:
                        adjustment = 0

                    for k, adj in enumerate(panellists):
                        cost_matrix[3 * i + j][k] = self.calc_cost(
                            debate, adj, adjustment)

            print "optimizing"

            indexes = m.compute(cost_matrix)

            cost = 0
            for r, c in indexes:
                cost += cost_matrix[r][c]

            print 'total cost for panellists', cost

            # transfer the indices to the debates
            # the debate corresponding to row r is floor(r/3) (i.e. r // 3)
            p = [[] for i in range(n)]
            for r, c in indexes[:n * 3]:
                p[r // 3].append(panellists[c])

            # create the corresponding adjudicator allocations, making sure
            # that the chair is the highest-ranked adjudicator in the panel
            for i, d in enumerate(panel_debates):
                a = AdjudicatorAllocation(d)
                p[i].sort(key=lambda a: a.score, reverse=True)
                a.chair = p[i].pop(0)
                a.panel = p[i]
                alloc.append(a)

        print[(a.debate, a.chair, a.panel) for a in alloc[len(chairs):]]

        return alloc
Example #53
0
def main():

    BANNER = '''
    ████████╗██╗  ██╗███████╗                                                  
    ╚══██╔══╝██║  ██║██╔════╝                                                  
       ██║   ███████║█████╗                                                    
       ██║   ██╔══██║██╔══╝                                                    
       ██║   ██║  ██║███████╗                                                  
       ╚═╝   ╚═╝  ╚═╝╚══════╝              -v1.0 by @amirootyet                                   
                                                                               
     █████╗ ██╗     ██╗      ██████╗  ██████╗ █████╗ ████████╗ ██████╗ ██████╗ 
    ██╔══██╗██║     ██║     ██╔═══██╗██╔════╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
    ███████║██║     ██║     ██║   ██║██║     ███████║   ██║   ██║   ██║██████╔╝
    ██╔══██║██║     ██║     ██║   ██║██║     ██╔══██║   ██║   ██║   ██║██╔══██╗
    ██║  ██║███████╗███████╗╚██████╔╝╚██████╗██║  ██║   ██║   ╚██████╔╝██║  ██║
    ╚═╝  ╚═╝╚══════╝╚══════╝ ╚═════╝  ╚═════╝╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝  ╚═                                            
    '''
    print(BANNER)

    ########################################
    # Arguments to the command-line utility
    parser = argparse.ArgumentParser(
        description='A utility to manage CSE 231 TA assignment with the Munkres algorithm.')
    parser.add_argument("-a", "--assign", help='Find optimal (miminum cost) TA assignments.', action='store_true')
    parser.add_argument("-b", "--busybees", help="Find TAs that have a conflict for more than half"
                                                 "of the total work slots.", action='store_true')
    parser.add_argument("-f", "--filename", required=True, help="CSV file containing TA preferences.")
    parser.add_argument("-c", "--costmatrix", help="Build and display the TA cost matrix.", action='store_true')
    args = parser.parse_args()
    #########################################

    fp = open_file(args.filename)  # Attempt to open the CSV file with TA preferences.
    time_slots, preference_dictionary = assistants_and_slots(fp)  # Read time slots and preferences
    assistants = list(preference_dictionary.keys())  # Create a list of available TAs

    # Show the "busy bees"; these TAs make optimal assignment challenging.
    if args.busybees:
        busy_bees = []
        for assistant, costs in preference_dictionary.items():
            conflicts = costs.count(COSTS['Conflict'])  # Count the conflicts for each TA.
            if conflicts > (len(costs)) / 2:  # If the TA has more conflicts than half of the total slots.
                busy_bees.append((assistant, conflicts))
        print("-" * 40)
        print("{:<20} {} (/{})".format('Busy Bee', 'Conflicts', len(costs)))
        print("-" * 40)
        for busy_bee in busy_bees:
            print("{:<20} {}".format(busy_bee[0], busy_bee[1]))

    # Build and show the cost matrix.
    elif args.costmatrix:
        cost_matrix = build_cost_matrix(preference_dictionary)  # Build the cost matrix.
        print_matrix(cost_matrix)  # Display the cost matrix.

    # Assign TAs the time slots / labs.
    elif args.assign:
        cost_matrix = build_cost_matrix(preference_dictionary)
        munkres_obj = Munkres()
        total = 0
        indexes = munkres_obj.compute(cost_matrix)  # This is where the assignment magic happens.
        print('{:<17s} | {:<25s} -> {:<4s}'.format('TAs', 'Assignment', 'Cost'))
        print("-" * 55)
        for row, col in indexes:
            cost = cost_matrix[row][col]
            total += cost  # Calculate total cost of assignment.
            print('{:<17s} | {:<25s} -> {:<4d}'.format(assistants[row], time_slots[col],
                                                       cost))  # Display the assignment result.
        for k, v in COSTS.items():
            print(str(k) + " = " + str(v), end="; ")
        print("\nTimeslots: {}; TAs: {}".format(len(time_slots), len(assistants)))
    else:
        print("Nothing to do. See --help")

    fp.close()  # Close the CSV file before exit.
class PeopleCounting:
    def __init__(self):
        # Array of Gallery Objects - {embeddings(numpy array), timestamp}
        self.identities = []
        self.reid_threshold = 0.7
        self.matcher = Munkres()
        self.timestamp = 0

    def process_frame(self, frame):
        messages = list(frame.messages())
        if len(messages) > 0:
            json_msg = json.loads(messages[0])
            json_msg["count"] = {"people": len(self.identities)}
            self.timestamp = int(json_msg["timestamp"]) / 1000000000
            frame.remove_message(messages[0])
            frame.add_message(json.dumps(json_msg))

        self.get_ids_by_embeddings(frame)
        return True

    @staticmethod
    def compute_reid_distance(test_embedding, reference_embedding):
        xx = np.dot(test_embedding, test_embedding)
        yy = np.dot(reference_embedding, reference_embedding)
        xy = np.dot(test_embedding, reference_embedding)
        norm = math.sqrt(xx * yy) + 1e-6
        return np.float32(1.0) - xy / norm

    def get_ids_by_embeddings(self, frame):
        detected_tensors = []
        detection_ids = []
        detections = [x for x in frame.regions()]
        for i, detection in enumerate(detections):
            if detection.label() == "person":
                for j, tensor in enumerate(detection.tensors()):
                    if tensor.name() == "face_feature" and tensor.format(
                    ) == "cosine_distance":
                        detected_tensors.append(tensor.data())
                        detection_ids.append(i)

        if len(detected_tensors) == 0:
            return
        if len(self.identities) == 0:
            for i in range(len(detected_tensors)):
                self.identities.append({
                    "embedding":
                    copy.deepcopy(detected_tensors[i]),
                    "timestamp":
                    self.timestamp
                })
            return
        distances = np.empty([len(detected_tensors),
                              len(self.identities)],
                             dtype=np.float32)

        for i in range(len(detected_tensors)):
            for j in range(len(self.identities)):
                distances[i][j] = PeopleCounting.compute_reid_distance(
                    detected_tensors[i], self.identities[j]["embedding"])

        matched_indexes = self.matcher.compute(distances.tolist())
        matched_detections = set()

        for match in matched_indexes:
            if distances[match[0]][match[1]] <= self.reid_threshold:
                self.identities[match[1]]["timestamp"] = self.timestamp
                matched_detections.add(match[0])

        for i in range(len(detected_tensors)):
            if i not in matched_detections:
                self.identities.append({
                    "embedding":
                    copy.deepcopy(detected_tensors[i]),
                    "timestamp":
                    self.timestamp
                })

        n = len(self.identities)
        i = n - 1
        while i >= 0:
            # overdue if pass the last 5 seconds
            if int(self.timestamp - int(self.identities[i]["timestamp"])) > 5:
                self.identities[i] = self.identities[n - 1]
                self.identities.pop(n - 1)
                n -= 1
            i -= 1
Example #55
0
def testIndex():
    a = [[random.random() for i in xrange(3)] for j in xrange(2)]

    b = Munkres()
    results = b.compute(a)
    print results