|
@@ -32,7 +32,7 @@ import { ReferenceImageWithMedia } from './reference-image';
|
32
|
32
|
import { Utils } from '../../utils/utils';
|
33
|
33
|
import { IllegalOperationError, IllegalArgumentError, NumericalError } from '../../utils/errors';
|
34
|
34
|
import { NIS_SIZE, TRACK_GRID_GRANULARITY } from './settings';
|
35
|
|
-import { find6DoFHomography, solvePlanarPnPRansacOptions } from '../../geometry/pnp';
|
|
35
|
+import { find6DoFHomography, find6DoFHomographyOptions } from '../../geometry/pnp';
|
36
|
36
|
|
37
|
37
|
/*
|
38
|
38
|
|
|
@@ -231,10 +231,10 @@ export class ImageTrackerUtils
|
231
|
231
|
* find a 6 DoF perspective warp (homography) from src to dest in NDC
|
232
|
232
|
* @param cameraIntrinsics 3x3 camera intrinsics
|
233
|
233
|
* @param points compiled pairs of keypoints in NDC
|
234
|
|
- * @param options to be passed to pnp
|
|
234
|
+ * @param options to be passed to find6DofHomography
|
235
|
235
|
* @returns a pair [ 3x3 transformation matrix, quality score ]
|
236
|
236
|
*/
|
237
|
|
- static find6DoFHomographyNDC(cameraIntrinsics: SpeedyMatrix, points: SpeedyMatrix, options: solvePlanarPnPRansacOptions): SpeedyPromise<[SpeedyMatrix,number]>
|
|
237
|
+ static find6DoFHomographyNDC(cameraIntrinsics: SpeedyMatrix, points: SpeedyMatrix, options: find6DoFHomographyOptions): SpeedyPromise<[SpeedyMatrix,number]>
|
238
|
238
|
{
|
239
|
239
|
// too few data points?
|
240
|
240
|
const n = points.columns / 2;
|
|
@@ -247,34 +247,19 @@ export class ImageTrackerUtils
|
247
|
247
|
// compute a homography
|
248
|
248
|
const src = points.block(0, 1, 0, n-1);
|
249
|
249
|
const dest = points.block(0, 1, n, 2*n-1);
|
250
|
|
- const homography = find6DoFHomography(src, dest, cameraIntrinsics, options);
|
251
|
|
- //console.log('homography',homography.toString(), src.toString(), dest.toString());
|
252
|
|
-
|
253
|
|
- // quit without refinement (test)
|
254
|
|
- // we use a coarse estimate of the camera intrinsics
|
255
|
|
- //return Speedy.Promise.resolve([homography, 0]);
|
256
|
|
-
|
257
|
|
- const mask = Speedy.Matrix.Zeros(1, n);
|
258
|
|
- const intermediate = Speedy.Matrix.Zeros(2, n);
|
259
|
|
-
|
260
|
|
- // refine the result of find6DoFHomography() with DLT + RANSAC
|
261
|
|
- return Speedy.Matrix.applyPerspectiveTransform(intermediate, src, homography)
|
262
|
|
- .then(intermediate =>
|
263
|
|
- Speedy.Matrix.findHomography(
|
264
|
|
- Speedy.Matrix.Zeros(3),
|
265
|
|
- intermediate,
|
266
|
|
- dest,
|
267
|
|
- {
|
268
|
|
- method: 'pransac',
|
269
|
|
- numberOfHypotheses: 512, // XXX we can reduce this number without compromising quality
|
270
|
|
- bundleSize: 128, // maybe make it a parameter in case we need an extra performance boost?
|
271
|
|
- reprojectionError: options.reprojectionError,
|
272
|
|
- mask,
|
273
|
|
- }
|
274
|
|
- )
|
275
|
|
- )
|
276
|
|
- .then(adjustment => adjustment.setTo(adjustment.times(homography)))
|
277
|
|
- .then(newHomography => {
|
|
250
|
+ const mask = options.mask || Speedy.Matrix.Zeros(1, n);
|
|
251
|
+
|
|
252
|
+ return find6DoFHomography(
|
|
253
|
+ src,
|
|
254
|
+ dest,
|
|
255
|
+ cameraIntrinsics,
|
|
256
|
+ Object.assign({ mask }, options)
|
|
257
|
+ ).then(homography => {
|
|
258
|
+
|
|
259
|
+ // check if this is a valid homography
|
|
260
|
+ const a00 = homography.at(0,0);
|
|
261
|
+ if(Number.isNaN(a00))
|
|
262
|
+ throw new NumericalError(`Can't compute a perspective warp: bad keypoints`);
|
278
|
263
|
|
279
|
264
|
// count inliers
|
280
|
265
|
let m = 0;
|
|
@@ -282,33 +267,9 @@ export class ImageTrackerUtils
|
282
|
267
|
for(let i = 0; i < n; i++)
|
283
|
268
|
m += inliers[i];
|
284
|
269
|
|
285
|
|
- /*
|
286
|
|
- // count and collect inliers
|
287
|
|
- let m = 0;
|
288
|
|
- const _mask = mask.read(), _src = src.read(), _dest = dest.read();
|
289
|
|
- const _isrc = new Array<number>(2*n), _idest = new Array<number>(2*n);
|
290
|
|
- for(let i = 0; i < n; i++) {
|
291
|
|
- if(_mask[i]) {
|
292
|
|
- const j = m++;
|
293
|
|
- _isrc[2*j] = _src[2*i];
|
294
|
|
- _isrc[2*j+1] = _src[2*i+1];
|
295
|
|
- _idest[2*j] = _dest[2*i];
|
296
|
|
- _idest[2*j+1] = _dest[2*i+1];
|
297
|
|
- }
|
298
|
|
- }
|
299
|
|
- _isrc.length = _idest.length = 2*m;
|
300
|
|
-
|
301
|
|
- // refine homography
|
302
|
|
- if(m > 0) {
|
303
|
|
- const isrc = Speedy.Matrix(2, m, _isrc);
|
304
|
|
- const idest = Speedy.Matrix(2, m, _idest);
|
305
|
|
- newHomography = refineHomography(newHomography, isrc, idest);
|
306
|
|
- }
|
307
|
|
- */
|
308
|
|
-
|
309
|
270
|
// done!
|
310
|
271
|
const score = m / n;
|
311
|
|
- return [newHomography, score];
|
|
272
|
+ return [homography, score];
|
312
|
273
|
|
313
|
274
|
});
|
314
|
275
|
}
|
|
@@ -333,7 +294,7 @@ export class ImageTrackerUtils
|
333
|
294
|
// compute a homography
|
334
|
295
|
const src = points.block(0, 1, 0, n-1);
|
335
|
296
|
const dest = points.block(0, 1, n, 2*n-1);
|
336
|
|
- const mask = Speedy.Matrix.Zeros(1, n);
|
|
297
|
+ const mask = ((options as any).mask as SpeedyMatrix | null | undefined) || Speedy.Matrix.Zeros(1, n);
|
337
|
298
|
|
338
|
299
|
return Speedy.Matrix.findHomography(
|
339
|
300
|
Speedy.Matrix.Zeros(3),
|
|
@@ -347,15 +308,15 @@ export class ImageTrackerUtils
|
347
|
308
|
if(Number.isNaN(a00))
|
348
|
309
|
throw new NumericalError(`Can't compute a perspective warp: bad keypoints`);
|
349
|
310
|
|
350
|
|
- // count the number of inliers
|
|
311
|
+ // count inliers
|
|
312
|
+ let m = 0;
|
351
|
313
|
const inliers = mask.read();
|
352
|
|
- let inlierCount = 0;
|
353
|
|
- for(let i = inliers.length - 1; i >= 0; i--)
|
354
|
|
- inlierCount += inliers[i];
|
355
|
|
- const score = inlierCount / inliers.length;
|
|
314
|
+ for(let i = 0; i < n; i++)
|
|
315
|
+ m += inliers[i];
|
356
|
316
|
|
357
|
317
|
// done!
|
358
|
|
- return [ homography, score ];
|
|
318
|
+ const score = m / n;
|
|
319
|
+ return [homography, score];
|
359
|
320
|
|
360
|
321
|
});
|
361
|
322
|
}
|
|
@@ -382,7 +343,7 @@ export class ImageTrackerUtils
|
382
|
343
|
const model = Speedy.Matrix.Eye(3);
|
383
|
344
|
const src = points.block(0, 1, 0, n-1);
|
384
|
345
|
const dest = points.block(0, 1, n, 2*n-1);
|
385
|
|
- const mask = Speedy.Matrix.Zeros(1, n);
|
|
346
|
+ const mask = ((options as any).mask as SpeedyMatrix | null | undefined) || Speedy.Matrix.Zeros(1, n);
|
386
|
347
|
|
387
|
348
|
return Speedy.Matrix.findAffineTransform(
|
388
|
349
|
model.block(0, 1, 0, 2), // 2x3 submatrix
|
|
@@ -396,15 +357,15 @@ export class ImageTrackerUtils
|
396
|
357
|
if(Number.isNaN(a00))
|
397
|
358
|
throw new NumericalError(`Can't compute an affine warp: bad keypoints`);
|
398
|
359
|
|
399
|
|
- // count the number of inliers
|
|
360
|
+ // count inliers
|
|
361
|
+ let m = 0;
|
400
|
362
|
const inliers = mask.read();
|
401
|
|
- let inlierCount = 0;
|
402
|
|
- for(let i = inliers.length - 1; i >= 0; i--)
|
403
|
|
- inlierCount += inliers[i];
|
404
|
|
- const score = inlierCount / inliers.length;
|
|
363
|
+ for(let i = 0; i < n; i++)
|
|
364
|
+ m += inliers[i];
|
405
|
365
|
|
406
|
366
|
// done!
|
407
|
|
- return [ model, score ];
|
|
367
|
+ const score = m / n;
|
|
368
|
+ return [model, score];
|
408
|
369
|
|
409
|
370
|
});
|
410
|
371
|
}
|