File size: 3,602 Bytes
c138d1f |
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)
|