File size: 3,602 Bytes
a56642d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 20 15:18:20 2022

@author: dinesh
"""

# 0 - Import related libraries

import urllib
import zipfile
import os
import scipy.io
import math
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from scipy.spatial.distance import directed_hausdorff
from sklearn.cluster import DBSCAN
from sklearn.metrics.pairwise import pairwise_distances
import scipy.spatial.distance

from .kmedoid import kMedoids # kMedoids code is adapted from https://github.com/letiantian/kmedoids

# Some visualization stuff, not so important
# sns.set()
plt.rcParams['figure.figsize'] = (12, 12)

# Utility Functions

color_lst = plt.rcParams['axes.prop_cycle'].by_key()['color']
color_lst.extend(['firebrick', 'olive', 'indigo', 'khaki', 'teal', 'saddlebrown',
                  'skyblue', 'coral', 'darkorange', 'lime', 'darkorchid', 'dimgray'])


def plot_cluster(image, traj_lst, cluster_lst):
    '''
    Plots given trajectories with a color that is specific for every trajectory's own cluster index.
    Outlier trajectories which are specified with -1 in `cluster_lst` are plotted dashed with black color
    '''
    cluster_count = np.max(cluster_lst) + 1

    for traj, cluster in zip(traj_lst, cluster_lst):

        # if cluster == -1:
        #     # Means it it a noisy trajectory, paint it black
        #     plt.plot(traj[:, 0], traj[:, 1], c='k', linestyle='dashed')
        #
        # else:
        plt.plot(traj[:, 0], traj[:, 1], c=color_lst[cluster % len(color_lst)])

    plt.imshow(image)
    # plt.show()
    plt.axis('off')
    plt.savefig('trajectory.png', bbox_inches='tight')
    plt.show()


# 3 - Distance matrix

def hausdorff( u, v):
    d = max(directed_hausdorff(u, v)[0], directed_hausdorff(v, u)[0])
    return d


def build_distance_matrix(traj_lst):
    # 2 - Trajectory segmentation

    print('Running trajectory segmentation...')
    degree_threshold = 5

    for traj_index, traj in enumerate(traj_lst):

        hold_index_lst = []
        previous_azimuth = 1000

        for point_index, point in enumerate(traj[:-1]):
            next_point = traj[point_index + 1]
            diff_vector = next_point - point
            azimuth = (math.degrees(math.atan2(*diff_vector)) + 360) % 360

            if abs(azimuth - previous_azimuth) > degree_threshold:
                hold_index_lst.append(point_index)
                previous_azimuth = azimuth
        hold_index_lst.append(traj.shape[0] - 1)  # Last point of trajectory is always added

        traj_lst[traj_index] = traj[hold_index_lst, :]

    print('Building distance matrix...')
    traj_count = len(traj_lst)
    D = np.zeros((traj_count, traj_count))

    # This may take a while
    for i in range(traj_count):
        if i % 20 == 0:
            print(i)
        for j in range(i + 1, traj_count):
            distance = hausdorff(traj_lst[i], traj_lst[j])
            D[i, j] = distance
            D[j, i] = distance

    return D


def run_kmedoids(image, traj_lst, D):
    # 4 - Different clustering methods

    # 4.1 - kmedoids

    traj_count = len(traj_lst)

    k = 3  # The number of clusters
    medoid_center_lst, cluster2index_lst = kMedoids(D, k)

    cluster_lst = np.empty((traj_count,), dtype=int)

    for cluster in cluster2index_lst:
        cluster_lst[cluster2index_lst[cluster]] = cluster

    plot_cluster(image, traj_lst, cluster_lst)


def run_dbscan(image, traj_lst, D):
    mdl = DBSCAN(eps=400, min_samples=10)
    cluster_lst = mdl.fit_predict(D)

    plot_cluster(image, traj_lst, cluster_lst)