|
@@ -234,9 +234,10 @@ export class ImageTrackerUtils
|
234
|
234
|
* @param alpha interpolation factor in [0,1]
|
235
|
235
|
* @param beta correction strength for noisy corners (optional)
|
236
|
236
|
* @param tau translation factor (optional)
|
|
237
|
+ * @param omega rotational factor (optional)
|
237
|
238
|
* @returns interpolated homography
|
238
|
239
|
*/
|
239
|
|
- static interpolateHomographies(src: SpeedyMatrix, dest: SpeedyMatrix, alpha: number, beta: number = 0, tau: number = 0): SpeedyPromise<SpeedyMatrix>
|
|
240
|
+ static interpolateHomographies(src: SpeedyMatrix, dest: SpeedyMatrix, alpha: number, beta: number = 0, tau: number = 0, omega: number = 0): SpeedyPromise<SpeedyMatrix>
|
240
|
241
|
{
|
241
|
242
|
const d = new Array<number>(4), q = new Array<number>(8), p = [
|
242
|
243
|
// NDC
|
|
@@ -263,7 +264,7 @@ export class ImageTrackerUtils
|
263
|
264
|
d[i] = dx*dx + dy*dy;
|
264
|
265
|
}
|
265
|
266
|
|
266
|
|
- let tx = 0, ty = 0;
|
|
267
|
+ let tx = 0, ty = 0, sin = 0, cos = 1;
|
267
|
268
|
const max = Math.max(d[0], d[1], d[2], d[3]); // max = Math.max(...d)
|
268
|
269
|
const min = Math.min(d[0], d[1], d[2], d[3]);
|
269
|
270
|
for(let i = 0, j = 0; i < 4; i++, j += 2) {
|
|
@@ -277,24 +278,44 @@ export class ImageTrackerUtils
|
277
|
278
|
const hby = hb[1] * x + hb[4] * y + hb[7];
|
278
|
279
|
const hbz = hb[2] * x + hb[5] * y + hb[8];
|
279
|
280
|
|
280
|
|
- if(d[i] == min) {
|
|
281
|
+ const ax = hax/haz, ay = hay/haz;
|
|
282
|
+ const bx = hbx/hbz, by = hby/hbz;
|
|
283
|
+
|
|
284
|
+ // correct noisy corners, if any
|
|
285
|
+ if(d[i] == min && min <= 0.5 * max) {
|
281
|
286
|
// we take the min for the translation
|
282
|
287
|
// because there may be noisy corners
|
283
|
|
- tx = hbx/hbz - hax/haz;
|
284
|
|
- ty = hby/hbz - hay/haz;
|
|
288
|
+ tx = bx - ax;
|
|
289
|
+ ty = by - ay;
|
|
290
|
+
|
|
291
|
+ const dot = ax * bx + ay * by;
|
|
292
|
+ const signedArea = ax * by - ay * bx;
|
|
293
|
+ const la2 = ax * ax + ay * ay;
|
|
294
|
+ const lb2 = bx * bx + by * by;
|
|
295
|
+ const lalb = Math.sqrt(la2 * lb2);
|
|
296
|
+
|
|
297
|
+ sin = signedArea / lalb;
|
|
298
|
+ cos = dot / lalb;
|
285
|
299
|
}
|
286
|
300
|
|
287
|
301
|
// compute the interpolation factor t = t(alpha, beta)
|
288
|
302
|
// t is (clamped) alpha if beta is zero
|
289
|
303
|
const gamma = alpha * Math.pow(2, -beta);
|
290
|
304
|
const f = 1 - Math.sqrt(d[i] / max); // f is zero when d[i] is max (hence, it minimizes t and contributes to src)
|
291
|
|
- const g = (alpha - gamma) * f + gamma;
|
|
305
|
+ const g = (alpha - gamma) * f + gamma; // gamma when f is zero; alpha when f is one
|
292
|
306
|
const t = Math.max(0, Math.min(g, 1)); // clamp
|
293
|
307
|
const _t = 1 - t;
|
294
|
308
|
|
295
|
309
|
// a (1-t) + b t
|
296
|
|
- q[ j ] = (hax/haz) * _t + (hbx/hbz) * t;
|
297
|
|
- q[j+1] = (hay/haz) * _t + (hby/hbz) * t;
|
|
310
|
+ q[ j ] = ax * _t + bx * t;
|
|
311
|
+ q[j+1] = ay * _t + by * t;
|
|
312
|
+ }
|
|
313
|
+
|
|
314
|
+ const _omega = 1 - omega;
|
|
315
|
+ for(let j = 0; j < 8; j += 2) {
|
|
316
|
+ const x = q[j], y = q[j+1];
|
|
317
|
+ q[ j ] = x * _omega + (x * cos - y * sin) * omega;
|
|
318
|
+ q[j+1] = y * _omega + (x * sin + y * cos) * omega;
|
298
|
319
|
}
|
299
|
320
|
|
300
|
321
|
for(let j = 0; j < 8; j += 2) {
|