Mercurial > hg > match-vamp
comparison src/Finder.cpp @ 75:e1a5f3095ba6 cheap_diagonals
Merge from branch refactors
author | Chris Cannam |
---|---|
date | Wed, 19 Nov 2014 12:13:28 +0000 |
parents | 7aa1ab3db7c9 7e3c1bc0984a |
children | eb3392bf6150 |
comparison
equal
deleted
inserted
replaced
68:7aa1ab3db7c9 | 75:e1a5f3095ba6 |
---|---|
18 | 18 |
19 #include "Path.h" | 19 #include "Path.h" |
20 | 20 |
21 #include <algorithm> | 21 #include <algorithm> |
22 | 22 |
23 | 23 using namespace std; |
24 Finder::Finder(Matcher *p1, Matcher *p2) | 24 |
25 { | 25 Finder::Finder(Matcher *pm) |
26 if (!p1->m_firstPM) | 26 { |
27 std::cerr << "Warning: wrong args in Finder()" << std::endl; | 27 m_m = pm; |
28 pm1 = p1; | 28 m_duration1 = -1; |
29 pm2 = p2; | 29 m_duration2 = -1; |
30 index1 = 0; | |
31 index2 = 0; | |
32 rowRange = new int[2]; | |
33 colRange = new int[2]; | |
34 duration1 = -1; | |
35 duration2 = -1; | |
36 } // constructor | 30 } // constructor |
37 | 31 |
38 Finder::~Finder() | 32 Finder::~Finder() |
39 { | 33 { |
40 delete[] rowRange; | |
41 delete[] colRange; | |
42 } | 34 } |
43 | 35 |
44 void | 36 void |
45 Finder::setDurations(int d1, int d2) | 37 Finder::setDurations(int d1, int d2) |
46 { | 38 { |
47 duration1 = d1; | 39 m_duration1 = d1; |
48 duration2 = d2; | 40 m_duration2 = d2; |
49 } | 41 } |
50 | |
51 bool | |
52 Finder::find(int i1, int i2) | |
53 { | |
54 if (i1 >= 0) { | |
55 index1 = i1; | |
56 index2 = i2 - pm1->m_first[i1]; | |
57 } | |
58 return (i1 >= 0) && (i2 >= pm1->m_first[i1]) && (i2 < pm1->m_last[i1]); | |
59 } // find() | |
60 | |
61 void | |
62 Finder::getColRange(int row, int *range) | |
63 { | |
64 range[0] = pm1->m_first[row]; | |
65 range[1] = pm1->m_last[row]; | |
66 } // getColRange() | |
67 | |
68 void | |
69 Finder::getRowRange(int col, int *range) | |
70 { | |
71 range[0] = pm2->m_first[col]; | |
72 range[1] = pm2->m_last[col]; | |
73 } // getRowRange() | |
74 | 42 |
75 Matcher::Advance | 43 Matcher::Advance |
76 Finder::getExpandDirection(int row, int col) | 44 Finder::getExpandDirection(int row, int col) |
77 { | 45 { |
78 return getExpandDirection(row, col, false); | 46 return getExpandDirection(row, col, false); |
79 } // getExpandDirection() | 47 } // getExpandDirection() |
80 | 48 |
81 Matcher::Advance | 49 Matcher::Advance |
82 Finder::getExpandDirection(int row, int col, bool check) | 50 Finder::getExpandDirection(int row, int col, bool check) |
83 { | 51 { |
84 double min = getPathCost(row, col); | 52 double min = m_m->getPathCost(row, col); |
85 bestRow = row; | 53 |
86 bestCol = col; | 54 int bestRow = row; |
87 getRowRange(col, rowRange); | 55 int bestCol = col; |
88 if (rowRange[1] > row+1) | 56 |
89 rowRange[1] = row+1; // don't cheat by looking at future :) | 57 pair<int, int> rowRange = m_m->getRowRange(col); |
90 for (int index = rowRange[0]; index < rowRange[1]; index++) { | 58 if (rowRange.second > row+1) { |
91 double tmp = getPathCost(index, col); | 59 rowRange.second = row+1; // don't cheat by looking at future :) |
60 } | |
61 for (int index = rowRange.first; index < rowRange.second; index++) { | |
62 double tmp = m_m->getPathCost(index, col); | |
92 if (tmp < min) { | 63 if (tmp < min) { |
93 min = tmp; | 64 min = tmp; |
94 bestRow = index; | 65 bestRow = index; |
95 } | 66 } |
96 } | 67 } |
97 getColRange(row, colRange); | 68 |
98 if (colRange[1] > col+1) | 69 pair<int, int> colRange = m_m->getColRange(row); |
99 colRange[1] = col+1; // don't cheat by looking at future :) | 70 if (colRange.second > col+1) { |
100 for (int index = colRange[0]; index < colRange[1]; index++) { | 71 colRange.second = col+1; // don't cheat by looking at future :) |
101 double tmp = getPathCost(row, index); | 72 } |
73 for (int index = colRange.first; index < colRange.second; index++) { | |
74 double tmp = m_m->getPathCost(row, index); | |
102 if (tmp < min) { | 75 if (tmp < min) { |
103 min = tmp; | 76 min = tmp; |
104 bestCol = index; | 77 bestCol = index; |
105 bestRow = row; | 78 bestRow = row; |
106 } | |
107 } | |
108 // System.err.print(" BEST: " + bestRow + " " + bestCol + " " + check); | |
109 // System.err.println(" " + pm1->frameCount + " " + pm2->frameCount); | |
110 if (check) { | |
111 // System.err.println(find(row+1, col) + " " + find(row, col+1)); | |
112 if (!find(row, col+1)) { | |
113 return Matcher::AdvanceThis; | |
114 } else if (!find(row+1, col)) { | |
115 return Matcher::AdvanceOther; | |
116 } | 79 } |
117 } | 80 } |
118 | 81 |
119 if (bestRow == row) { | 82 if (bestRow == row) { |
120 if (bestCol == col) { | 83 if (bestCol == col) { |
126 return Matcher::AdvanceOther; | 89 return Matcher::AdvanceOther; |
127 } else { | 90 } else { |
128 return Matcher::AdvanceNone; | 91 return Matcher::AdvanceNone; |
129 } | 92 } |
130 | 93 |
131 } // getExpandDirection() | 94 } |
132 | |
133 float | |
134 Finder::getDistance(int row, int col) | |
135 { | |
136 if (find(row, col)) { | |
137 return pm1->m_distance[row][col - pm1->m_first[row]]; | |
138 } | |
139 std::cerr << "getDistance(" << row << "," << col << "): out of bounds" << std::endl; | |
140 throw "getDistance index out of bounds"; | |
141 } // getDistance()/2 | |
142 | |
143 void | |
144 Finder::setDistance(int row, int col, float b) | |
145 { | |
146 if (find(row, col)) { | |
147 pm1->m_distance[row][col - pm1->m_first[row]] = b; | |
148 return; | |
149 } | |
150 std::cerr << "setDistance(" << row << "," << col << "," << b << "): out of bounds" << std::endl; | |
151 throw "setDistance index out of bounds"; | |
152 } // setDistance() | |
153 | |
154 double | |
155 Finder::getPathCost(int row, int col) | |
156 { | |
157 if (find(row, col)) // "1" avoids div by 0 below | |
158 return pm1->m_bestPathCost[row][col - pm1->m_first[row]] / float(1+row+col); | |
159 std::cerr << "getPathCost(" << row << "," << col << "): out of bounds" << std::endl; | |
160 throw "getPathCost index out of bounds"; | |
161 } // getPathCost() | |
162 | |
163 double | |
164 Finder::getRawPathCost(int row, int col) | |
165 { | |
166 if (find(row, col)) | |
167 return pm1->m_bestPathCost[row][col - pm1->m_first[row]]; | |
168 std::cerr << "getRawPathCost(" << row << "," << col << "): out of bounds" << std::endl; | |
169 throw "getRawPathCost index out of bounds"; | |
170 } // getRawPathCost() | |
171 | |
172 void | |
173 Finder::setPathCost(int row, int col, double cost) | |
174 { | |
175 if (find(row, col)) { | |
176 pm1->m_bestPathCost[row][col - pm1->m_first[row]] = cost; | |
177 return; | |
178 } | |
179 std::cerr << "setPathCost(" << row << "," << col << "," << cost << "): out of bounds" << std::endl; | |
180 throw "setPathCost index out of bounds"; | |
181 } // setPathCost() | |
182 | |
183 Matcher::Advance | |
184 Finder::getAdvance() | |
185 { | |
186 return pm1->m_advance[index1][index2]; | |
187 } | |
188 | |
189 void | |
190 Finder::setAdvance(Matcher::Advance a) | |
191 { | |
192 pm1->m_advance[index1][index2] = a; | |
193 } | |
194 | |
195 float | |
196 Finder::getDistance() | |
197 { | |
198 return pm1->m_distance[index1][index2]; | |
199 } // getDistance()/0 | |
200 | |
201 void | |
202 Finder::setDistance(float b) | |
203 { | |
204 pm1->m_distance[index1][index2] = b; | |
205 } // setDistance() | |
206 | |
207 double | |
208 Finder::getPathCost() | |
209 { | |
210 return pm1->m_bestPathCost[index1][index2]; | |
211 } // getPathCost() | |
212 | |
213 void | |
214 Finder::setPathCost(double cost) | |
215 { | |
216 pm1->m_bestPathCost[index1][index2] = cost; | |
217 } // setPathCost() | |
218 | 95 |
219 void | 96 void |
220 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2) | 97 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2) |
221 { | 98 { |
222 float diagonalWeight = sqrtf(2.f); | 99 float diagonalWeight = sqrtf(2.f); |
223 | 100 |
224 if (!find(r1,c1)) { | |
225 std::cerr << "recalculatePathCostMatrix(" << r1 << "," << c1 << "): out of bounds" << std::endl; | |
226 throw "recalculatePathCostMatrix index out of bounds"; | |
227 } | |
228 int thisRowStart, c; | |
229 int prevRowStart = 0, prevRowStop = 0; | 101 int prevRowStart = 0, prevRowStop = 0; |
102 | |
230 for (int r = r1; r <= r2; r++) { | 103 for (int r = r1; r <= r2; r++) { |
231 thisRowStart = pm1->m_first[r]; | 104 |
232 if (thisRowStart < c1) | 105 pair<int, int> colRange = m_m->getColRange(r); |
233 thisRowStart = c1; | 106 |
234 for (c = thisRowStart; c <= c2; c++) { | 107 int rowStart = max(c1, colRange.first); |
235 if (find(r,c)) { | 108 int rowStop = min(c2 + 1, colRange.second); |
236 int i2 = index2; | 109 |
237 float newCost = pm1->m_distance[r][i2]; | 110 for (int c = rowStart; c < rowStop; c++) { |
238 Matcher::Advance dir = Matcher::AdvanceNone; | 111 |
239 if (r > r1) { // not first row | 112 float newCost = m_m->getDistance(r, c); |
240 double min = -1; | 113 Matcher::Advance dir = Matcher::AdvanceNone; |
241 if ((c > prevRowStart) && (c <= prevRowStop)) { | 114 |
242 // diagonal from (r-1,c-1) | 115 if (r > r1) { // not first row |
243 min = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]-1] + | 116 double min = -1; |
244 newCost * diagonalWeight; | 117 if ((c > prevRowStart) && (c <= prevRowStop)) { |
245 dir = Matcher::AdvanceBoth; | 118 // diagonal from (r-1,c-1) |
119 min = m_m->getPathCost(r-1, c-1) + newCost * diagonalWeight; | |
120 dir = Matcher::AdvanceBoth; | |
121 } | |
122 if ((c >= prevRowStart) && (c < prevRowStop)) { | |
123 // vertical from (r-1,c) | |
124 double cost = m_m->getPathCost(r-1, c) + newCost; | |
125 if ((min < 0) || (cost < min)) { | |
126 min = cost; | |
127 dir = Matcher::AdvanceThis; | |
246 } | 128 } |
247 if ((c >= prevRowStart) && (c < prevRowStop)) { | 129 } |
248 // vertical from (r-1,c) | 130 if (c > rowStart) { |
249 double cost = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]] + | 131 // horizontal from (r,c-1) |
250 newCost; | 132 double cost = m_m->getPathCost(r, c-1) + newCost; |
251 if ((min == -1) || (cost < min)) { | 133 if ((min < 0) || (cost < min)) { |
252 min = cost; | 134 min = cost; |
253 dir = Matcher::AdvanceThis; | 135 dir = Matcher::AdvanceOther; |
254 } | |
255 } | 136 } |
256 if (c > thisRowStart) { | |
257 // horizontal from (r,c-1) | |
258 double cost =pm1->m_bestPathCost[r][i2-1]+newCost; | |
259 if ((min == -1) || (cost < min)) { | |
260 min = cost; | |
261 dir = Matcher::AdvanceOther; | |
262 } | |
263 } | |
264 pm1->m_bestPathCost[r][i2] = min; | |
265 } else if (c > thisRowStart) { // first row | |
266 // horizontal from (r,c-1) | |
267 pm1->m_bestPathCost[r][i2] = pm1->m_bestPathCost[r][i2-1] + | |
268 newCost; | |
269 dir = Matcher::AdvanceOther; | |
270 } | 137 } |
271 pm1->m_advance[r][i2] = dir; | 138 |
272 } else | 139 m_m->setPathCost(r, c, dir, min); |
273 break; // end of row | 140 |
274 } | 141 } else if (c > rowStart) { // first row |
275 prevRowStart = thisRowStart; | 142 // horizontal from (r,c-1) |
276 prevRowStop = c; | 143 m_m->setPathCost(r, c, Matcher::AdvanceOther, |
277 } | 144 m_m->getPathCost(r, c-1) + newCost); |
278 } // recalculatePathCostMatrix() | 145 } |
146 } | |
147 | |
148 prevRowStart = rowStart; | |
149 prevRowStop = rowStop; | |
150 } | |
151 } | |
279 | 152 |
280 int | 153 int |
281 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy) | 154 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy) |
282 { | 155 { |
283 int ex = pm2->getFrameCount() - 1; | 156 pathx.clear(); |
284 int ey = pm1->getFrameCount() - 1; | 157 pathy.clear(); |
158 | |
159 int ex = m_m->getOtherFrameCount() - 1; | |
160 int ey = m_m->getFrameCount() - 1; | |
161 | |
162 if (ex < 0 || ey < 0) { | |
163 return 0; | |
164 } | |
285 | 165 |
286 int x = ex; | 166 int x = ex; |
287 int y = ey; | 167 int y = ey; |
288 | 168 |
289 // cerr << "before: x = " << x << ", y = " << y << endl; | 169 // cerr << "before: x = " << x << ", y = " << y << endl; |
290 | 170 |
291 if (duration2 > 0 && duration2 < pm2->getFrameCount()) { | 171 if (m_duration2 > 0 && m_duration2 < m_m->getOtherFrameCount()) { |
292 x = duration2 - 1; | 172 x = m_duration2 - 1; |
293 } | 173 } |
294 if (duration1 > 0 && duration1 < pm1->getFrameCount()) { | 174 if (m_duration1 > 0 && m_duration1 < m_m->getFrameCount()) { |
295 y = duration1 - 1; | 175 y = m_duration1 - 1; |
296 } | 176 } |
297 | 177 |
298 if (!find(y, x)) { | 178 if (!m_m->isAvailable(y, x)) { |
299 // Path did not pass through the expected end point -- | 179 // Path did not pass through the expected end point -- |
300 // probably means the pieces are substantially different in | 180 // probably means the pieces are substantially different in |
301 // the later bits. Reset the expected end point to the end of | 181 // the later bits. Reset the expected end point to the end of |
302 // both files including any trailing silence. | 182 // both files including any trailing silence. |
303 cerr << "NOTE: Path did not pass through expected end point, inputs are probably significantly different" << endl; | 183 cerr << "NOTE: Path did not pass through expected end point, inputs are probably significantly different" << endl; |
305 y = ey; | 185 y = ey; |
306 } | 186 } |
307 | 187 |
308 recalculatePathCostMatrix(0, 0, y, x); | 188 recalculatePathCostMatrix(0, 0, y, x); |
309 | 189 |
310 pathx.clear(); | |
311 pathy.clear(); | |
312 | |
313 // cerr << "start: x = " << x << ", y = " << y << endl; | 190 // cerr << "start: x = " << x << ", y = " << y << endl; |
314 | 191 |
315 while (find(y, x) && ((x > 0) || (y > 0))) { | 192 while (m_m->isAvailable(y, x) && (x > 0 || y > 0)) { |
316 | 193 |
317 // cerr << "x = " << x << ", y = " << y; | 194 // cerr << "x = " << x << ", y = " << y; |
318 | 195 |
319 pathx.push_back(x); | 196 pathx.push_back(x); |
320 pathy.push_back(y); | 197 pathy.push_back(y); |
321 | 198 |
322 switch (getAdvance()) { | 199 switch (m_m->getAdvance(y, x)) { |
323 case Matcher::AdvanceThis: | 200 case Matcher::AdvanceThis: |
324 // cerr << ", going down (dist = " << (int)getDistance() << ")" << endl; | 201 // cerr << ", going down (dist = " << getDistance() << ")" << endl; |
325 y--; | 202 y--; |
326 break; | 203 break; |
327 case Matcher::AdvanceOther: | 204 case Matcher::AdvanceOther: |
328 // cerr << ", going left (dist = " << (int)getDistance() << ")" << endl; | 205 // cerr << ", going left (dist = " << getDistance() << ")" << endl; |
329 x--; | 206 x--; |
330 break; | 207 break; |
331 case Matcher::AdvanceBoth: | 208 case Matcher::AdvanceBoth: |
332 // cerr << ", going diag (dist = " << (int)getDistance() << ")" << endl; | 209 // cerr << ", going diag (dist = " << getDistance() << ")" << endl; |
333 x--; | 210 x--; |
334 y--; | 211 y--; |
335 break; | 212 break; |
336 case Matcher::AdvanceNone: // this would indicate a bug, but we wouldn't want to hang | 213 case Matcher::AdvanceNone: // this would indicate a bug, but we wouldn't want to hang |
337 // cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl; | 214 cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl; |
338 if (x > y) { | 215 if (x > y) { |
339 x--; | 216 x--; |
340 } else { | 217 } else { |
341 y--; | 218 y--; |
342 } | 219 } |
343 break; | 220 break; |
344 } | 221 } |
345 } | 222 } |
346 | 223 |
347 std::reverse(pathx.begin(), pathx.end()); | 224 if (x > 0 || y > 0) { |
348 std::reverse(pathy.begin(), pathy.end()); | 225 cerr << "WARNING: Ran out of available path at (" << y << "," << x |
226 << ")!" << endl; | |
227 } | |
228 | |
229 reverse(pathx.begin(), pathx.end()); | |
230 reverse(pathy.begin(), pathy.end()); | |
349 | 231 |
350 if (smooth) { | 232 if (smooth) { |
351 int smoothedLen = Path().smooth(pathx, pathy, pathx.size()); | 233 int smoothedLen = Path().smooth(pathx, pathy, pathx.size()); |
352 return smoothedLen; | 234 return smoothedLen; |
353 } else { | 235 } else { |