This repository has been archived by the owner on Aug 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDTW.pde
168 lines (150 loc) · 3.83 KB
/
DTW.pde
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
* DTW.java
* @author Cheol-Woo Jung ([email protected])
* @version 1.0
*/
public class DTW {
protected Float[] seq1;
protected Float[] seq2;
protected int[][] warpingPath;
protected int n;
protected int m;
protected int K;
protected double warpingDistance;
/**
* Constructor
*
* @param query
* @param templete
*/
public DTW(Float[] sample, Float[] templete) {
seq1 = sample;
seq2 = templete;
n = seq1.length;
m = seq2.length;
K = 1;
warpingPath = new int[n + m][2]; // max(n, m) <= K < n + m
warpingDistance = 0.0;
this.compute();
}
public void compute() {
double accumulatedDistance = 0.0;
double[][] d = new double[n][m]; // local distances
double[][] D = new double[n][m]; // global distances
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
d[i][j] = distanceBetween(seq1[i], seq2[j]);
}
}
D[0][0] = d[0][0];
for (int i = 1; i < n; i++) {
D[i][0] = d[i][0] + D[i - 1][0];
}
for (int j = 1; j < m; j++) {
D[0][j] = d[0][j] + D[0][j - 1];
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
accumulatedDistance = Math.min(Math.min(D[i-1][j], D[i-1][j-1]), D[i][j-1]);
accumulatedDistance += d[i][j];
D[i][j] = accumulatedDistance;
}
}
accumulatedDistance = D[n - 1][m - 1];
int i = n - 1;
int j = m - 1;
int minIndex = 1;
warpingPath[K - 1][0] = i;
warpingPath[K - 1][1] = j;
while ( (i + j) != 0) {
if (i == 0) {
j -= 1;
}
else if (j == 0) {
i -= 1;
}
else { // i != 0 && j != 0
double[] array = {
D[i - 1][j], D[i][j - 1], D[i - 1][j - 1]
};
minIndex = this.getIndexOfMinimum(array);
if (minIndex == 0) {
i -= 1;
}
else if (minIndex == 1) {
j -= 1;
}
else if (minIndex == 2) {
i -= 1;
j -= 1;
}
} // end else
K++;
warpingPath[K - 1][0] = i;
warpingPath[K - 1][1] = j;
} // end while
warpingDistance = accumulatedDistance / K;
this.reversePath(warpingPath);
}
/**
* Changes the order of the warping path (increasing order)
*
* @param path the warping path in reverse order
*/
protected void reversePath(int[][] path) {
int[][] newPath = new int[K][2];
for (int i = 0; i < K; i++) {
for (int j = 0; j < 2; j++) {
newPath[i][j] = path[K - i - 1][j];
}
}
warpingPath = newPath;
}
/**
* Returns the warping distance
*
* @return
*/
public double getDistance() {
return warpingDistance;
}
/**
* Computes a distance between two points
*
* @param p1 the point 1
* @param p2 the point 2
* @return the distance between two points
*/
protected double distanceBetween(double p1, double p2) {
return (p1 - p2) * (p1 - p2);
}
/**
* Finds the index of the minimum element from the given array
*
* @param array the array containing numeric values
* @return the min value among elements
*/
protected int getIndexOfMinimum(double[] array) {
int index = 0;
double val = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < val) {
val = array[i];
index = i;
}
}
return index;
}
/**
* Returns a string that displays the warping distance and path
*/
public String toString() {
String retVal = "Warping Distance: " + warpingDistance + "\n";
retVal += "Warping Path: {";
for (int i = 0; i < K; i++) {
retVal += "(" + warpingPath[i][0] + ", " +warpingPath[i][1] + ")";
retVal += (i == K - 1) ? "}" : ", ";
}
return retVal;
}
}