|
@@ -67,6 +67,9 @@ const USE_TURBO = true;
|
67
|
67
|
/** Number of PBOs; meaningful only when using turbo */
|
68
|
68
|
const NUMBER_OF_PBOS = 2;
|
69
|
69
|
|
|
70
|
+/** Motion model */
|
|
71
|
+const NO_MOTION = Speedy.Matrix.Eye(3);
|
|
72
|
+
|
70
|
73
|
|
71
|
74
|
|
72
|
75
|
/**
|
|
@@ -298,22 +301,25 @@ export class ImageTrackerTrackingState extends ImageTrackerState
|
298
|
301
|
// find motion models
|
299
|
302
|
const points = ImageTrackerUtils.compilePairsOfKeypointsNDC(pairs);
|
300
|
303
|
return Speedy.Promise.all<SpeedyMatrixExpr>([
|
301
|
|
- this._findAffineMotionNDC(points),
|
302
|
|
- this._findPerspectiveMotionNDC(points)
|
|
304
|
+ //this._findAffineMotionNDC(points),
|
|
305
|
+ //this._findPerspectiveMotionNDC(points),
|
|
306
|
+ this._find6DoFPerspectiveMotionNDC(points),
|
|
307
|
+ Speedy.Promise.resolve(NO_MOTION),
|
303
|
308
|
]);
|
304
|
309
|
|
305
|
310
|
})
|
306
|
|
- .then(([affineMotion, perspectiveMotion]) => {
|
|
311
|
+ .then(([warpMotion, poseMotion]) => {
|
307
|
312
|
|
308
|
313
|
const lowPower = (Settings.powerPreference == 'low-power');
|
309
|
314
|
const delay = NUMBER_OF_PBOS * (!lowPower ? 2 : 1);
|
310
|
315
|
|
311
|
316
|
// update warp homography
|
312
|
317
|
if(!USE_TURBO || this._counter % delay == 1) // skip the first frame (PBOs)
|
313
|
|
- this._warpHomography.setToSync(affineMotion.times(this._warpHomography));
|
|
318
|
+ this._warpHomography.setToSync(warpMotion.times(this._warpHomography));
|
314
|
319
|
|
315
|
320
|
// update pose homography
|
316
|
|
- this._poseHomography.setToSync(perspectiveMotion.times(this._warpHomography));
|
|
321
|
+ //poseMotion = warpMotion; // commented: reduce jitter, increase delay
|
|
322
|
+ this._poseHomography.setToSync(poseMotion.times(this._warpHomography));
|
317
|
323
|
if(Number.isNaN(this._poseHomography.at(0,0)))
|
318
|
324
|
throw new NumericalError('Bad homography'); // normalize? 1 / h33
|
319
|
325
|
|
|
@@ -324,8 +330,8 @@ export class ImageTrackerTrackingState extends ImageTrackerState
|
324
|
330
|
// test
|
325
|
331
|
console.log("POSE ", this._poseHomography.toString());
|
326
|
332
|
console.log("WARP ", this._warpHomography.toString());
|
327
|
|
- console.log("AMOT ", Speedy.Matrix(affineMotion).toString());
|
328
|
|
- console.log("PMOT ", Speedy.Matrix(perspectiveMotion).toString());
|
|
333
|
+ console.log("AMOT ", Speedy.Matrix(warpMotion).toString());
|
|
334
|
+ console.log("PMOT ", Speedy.Matrix(poseMotion).toString());
|
329
|
335
|
*/
|
330
|
336
|
|
331
|
337
|
// We transform the keypoints of the reference image to NDC as a
|
|
@@ -455,6 +461,8 @@ export class ImageTrackerTrackingState extends ImageTrackerState
|
455
|
461
|
|
456
|
462
|
Note: work with a 6 DoF perspective transform instead of 8.
|
457
|
463
|
|
|
464
|
+ Edit: now we have find6DoFHomography()
|
|
465
|
+
|
458
|
466
|
*/
|
459
|
467
|
|
460
|
468
|
return ImageTrackerUtils.findAffineWarpNDC(points, {
|
|
@@ -498,7 +506,8 @@ export class ImageTrackerTrackingState extends ImageTrackerState
|
498
|
506
|
numberOfHypotheses: 512*2,
|
499
|
507
|
bundleSize: 128,//128*4,
|
500
|
508
|
mask: undefined // score is not needed
|
501
|
|
- }).then(([ warp, score ]) => {
|
|
509
|
+ })
|
|
510
|
+ .then(([ warp, score ]) => {
|
502
|
511
|
|
503
|
512
|
const scale = TRACK_RECTIFIED_SCALE;
|
504
|
513
|
const aspectRatio = ImageTrackerUtils.bestFitAspectRatioNDC(this.screenSize, this._referenceImage!);
|
|
@@ -520,6 +529,43 @@ export class ImageTrackerTrackingState extends ImageTrackerState
|
520
|
529
|
}
|
521
|
530
|
|
522
|
531
|
/**
|
|
532
|
+ * Find a 6 DoF perspective motion model in NDC between pairs of keypoints in NDC
|
|
533
|
+ * given as a 2 x 2n [ src | dest ] matrix
|
|
534
|
+ * @param points compiled pairs of keypoints in NDC
|
|
535
|
+ * @returns a promise that resolves to a 3x3 warp in NDC that maps source to destination
|
|
536
|
+ */
|
|
537
|
+ private _find6DoFPerspectiveMotionNDC(points: SpeedyMatrix): SpeedyPromise<SpeedyMatrixExpr>
|
|
538
|
+ {
|
|
539
|
+ const K = this._camera.intrinsicsMatrix();
|
|
540
|
+
|
|
541
|
+ return ImageTrackerUtils.find6DoFHomographyNDC(K, points, {
|
|
542
|
+ reprojectionError: TRACK_RANSAC_REPROJECTIONERROR_NDC,
|
|
543
|
+ numberOfHypotheses: 100,
|
|
544
|
+ //mask: undefined // score is not needed
|
|
545
|
+ })
|
|
546
|
+ .then(([ warp, score ]) => {
|
|
547
|
+
|
|
548
|
+ const scale = TRACK_RECTIFIED_SCALE;
|
|
549
|
+ const aspectRatio = ImageTrackerUtils.bestFitAspectRatioNDC(this.screenSize, this._referenceImage!);
|
|
550
|
+ const shrink = ImageTrackerUtils.bestFitScaleNDC(aspectRatio, scale);
|
|
551
|
+ const grow = ImageTrackerUtils.inverseBestFitScaleNDC(aspectRatio, scale);
|
|
552
|
+ const scaledWarp = grow.times(warp).times(shrink);
|
|
553
|
+
|
|
554
|
+ //const distort = this._poseHomography;
|
|
555
|
+ const distort = this._warpHomography;
|
|
556
|
+ const undistort = distort.inverse();
|
|
557
|
+ const correctedWarp = distort.times(scaledWarp).times(undistort);
|
|
558
|
+
|
|
559
|
+ return correctedWarp;
|
|
560
|
+
|
|
561
|
+ }).catch(err => {
|
|
562
|
+
|
|
563
|
+ throw new TrackingError(`Can't find a perspective motion`, err);
|
|
564
|
+
|
|
565
|
+ });
|
|
566
|
+ }
|
|
567
|
+
|
|
568
|
+ /**
|
523
|
569
|
* Find matching pairs of two sets of keypoints matched via brute force
|
524
|
570
|
* @param srcKeypoints source (database)
|
525
|
571
|
* @param destKeypoints destination
|