|
@@ -29,6 +29,7 @@ import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
|
29
|
29
|
import { SpeedyPipeline, SpeedyPipelineOutput } from 'speedy-vision/types/core/pipeline/pipeline';
|
30
|
30
|
import { SpeedyPipelineNodeImageSource } from 'speedy-vision/types/core/pipeline/nodes/images/source';
|
31
|
31
|
import { SpeedyPipelineNodeImageMultiplexer } from 'speedy-vision/types/core/pipeline/nodes/images/multiplexer';
|
|
32
|
+import { SpeedyPipelineNodeImageBuffer } from 'speedy-vision/types/core/pipeline/nodes/images/buffer';
|
32
|
33
|
import { SpeedyPipelineNodeImagePortalSource, SpeedyPipelineNodeImagePortalSink } from 'speedy-vision/types/core/pipeline/nodes/images/portal';
|
33
|
34
|
import { SpeedyPipelineNodeKeypointPortalSource, SpeedyPipelineNodeKeypointPortalSink } from 'speedy-vision/types/core/pipeline/nodes/keypoints/portal';
|
34
|
35
|
import { SpeedyPipelineNodeResize } from 'speedy-vision/types/core/pipeline/nodes/transforms/resize';
|
|
@@ -48,7 +49,8 @@ import {
|
48
|
49
|
ORB_GAUSSIAN_KSIZE, ORB_GAUSSIAN_SIGMA,
|
49
|
50
|
TRACK_HARRIS_QUALITY, TRACK_DETECTOR_CAPACITY, TRACK_MAX_KEYPOINTS,
|
50
|
51
|
SUBPIXEL_GAUSSIAN_KSIZE, SUBPIXEL_GAUSSIAN_SIGMA,
|
51
|
|
- PRE_TRACK_MIN_MATCHES, TRACK_MATCH_RATIO, TRACK_RANSAC_REPROJECTIONERROR_NDC,
|
|
52
|
+ PRE_TRACK_MIN_MATCHES, PRE_TRACK_MAX_ITERATIONS,
|
|
53
|
+ TRACK_MATCH_RATIO, PRE_TRACK_RANSAC_REPROJECTIONERROR_NDC,
|
52
|
54
|
NIGHTVISION_QUALITY,
|
53
|
55
|
SUBPIXEL_METHOD,
|
54
|
56
|
} from '../settings';
|
|
@@ -75,6 +77,9 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
75
|
77
|
/** portal with keypoints from Pre-Tracking A */
|
76
|
78
|
private _referenceKeypointPortalSink: Nullable<SpeedyPipelineNodeKeypointPortalSink>;
|
77
|
79
|
|
|
80
|
+ /** number of iterations */
|
|
81
|
+ private _iterations: number;
|
|
82
|
+
|
78
|
83
|
|
79
|
84
|
|
80
|
85
|
|
|
@@ -92,6 +97,7 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
92
|
97
|
this._referenceImage = null;
|
93
|
98
|
this._snapshot = null;
|
94
|
99
|
this._referenceKeypointPortalSink = null;
|
|
100
|
+ this._iterations = 0;
|
95
|
101
|
}
|
96
|
102
|
|
97
|
103
|
/**
|
|
@@ -104,12 +110,19 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
104
|
110
|
const referenceImage = settings.referenceImage as ReferenceImageWithMedia;
|
105
|
111
|
const snapshot = settings.snapshot as SpeedyPipelineNodeImagePortalSink;
|
106
|
112
|
const referenceKeypointPortalSink = settings.referenceKeypointPortalSink as SpeedyPipelineNodeKeypointPortalSink;
|
|
113
|
+ const sourceMux = this._pipeline.node('sourceMux') as SpeedyPipelineNodeImageMultiplexer;
|
|
114
|
+ const sourceBuffer = this._pipeline.node('sourceBuffer') as SpeedyPipelineNodeImageBuffer;
|
107
|
115
|
|
108
|
116
|
// set attributes
|
109
|
117
|
this._homography = homography;
|
110
|
118
|
this._referenceImage = referenceImage;
|
111
|
119
|
this._snapshot = snapshot;
|
112
|
120
|
this._referenceKeypointPortalSink = referenceKeypointPortalSink;
|
|
121
|
+ this._iterations = 0;
|
|
122
|
+
|
|
123
|
+ // reset nodes
|
|
124
|
+ sourceMux.port = 0;
|
|
125
|
+ sourceBuffer.frozen = false;
|
113
|
126
|
}
|
114
|
127
|
|
115
|
128
|
/**
|
|
@@ -166,6 +179,8 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
166
|
179
|
const keypoints = result.keypoints as SpeedyMatchedKeypoint[]; // from Pre-Tracking B
|
167
|
180
|
const image = result.image as SpeedyMedia | undefined;
|
168
|
181
|
const keypointPortalSink = this._pipeline.node('keypointPortalSink') as SpeedyPipelineNodeKeypointPortalSink;
|
|
182
|
+ const sourceMux = this._pipeline.node('sourceMux') as SpeedyPipelineNodeImageMultiplexer;
|
|
183
|
+ const sourceBuffer = this._pipeline.node('sourceBuffer') as SpeedyPipelineNodeImageBuffer;
|
169
|
184
|
|
170
|
185
|
// tracker output
|
171
|
186
|
const trackerOutput: ImageTrackerOutput = {
|
|
@@ -184,22 +199,25 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
184
|
199
|
|
185
|
200
|
// find a warp
|
186
|
201
|
const points = ImageTrackerUtils.compilePairsOfKeypointsNDC(pairs);
|
187
|
|
- return this._findAffineMotionNDC(points);
|
|
202
|
+ return this._findMotionNDC(points);
|
188
|
203
|
|
189
|
204
|
})
|
190
|
205
|
.then(warp => {
|
191
|
206
|
|
|
207
|
+ // get the camera image in the next iteration
|
|
208
|
+ // the warped snapshot from the scanning state is occasionally very blurry
|
|
209
|
+ sourceMux.port = 1;
|
|
210
|
+ sourceBuffer.frozen = true;
|
|
211
|
+
|
192
|
212
|
// refine the homography
|
193
|
213
|
return this._homography.setTo(warp.times(this._homography));
|
194
|
214
|
|
195
|
215
|
})
|
196
|
216
|
.then(_ => ({
|
197
|
|
- nextState: 'tracking',
|
198
|
|
- //nextState: 'pre-tracking-b',
|
|
217
|
+ nextState: (++this._iterations < PRE_TRACK_MAX_ITERATIONS) ? 'pre-tracking-b' : 'tracking',
|
199
|
218
|
trackerOutput: trackerOutput,
|
200
|
219
|
nextStateSettings: {
|
201
|
220
|
// we export keypoints obtained in Pre-Tracking B, not in A.
|
202
|
|
- // lighting conditions match, but what if the snapshot is too blurry?
|
203
|
221
|
templateKeypoints: keypoints,
|
204
|
222
|
templateKeypointPortalSink: keypointPortalSink,
|
205
|
223
|
referenceImage: this._referenceImage,
|
|
@@ -217,17 +235,18 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
217
|
235
|
}
|
218
|
236
|
|
219
|
237
|
/**
|
220
|
|
- * Find an affine motion model in NDC between pairs of keypoints in NDC
|
|
238
|
+ * Find a motion model in NDC between pairs of keypoints in NDC
|
221
|
239
|
* given as a 2 x 2n [ src | dest ] matrix
|
222
|
240
|
* @param points compiled pairs of keypoints in NDC
|
223
|
241
|
* @returns a promise that resolves to a 3x3 warp in NDC that maps source to destination
|
224
|
242
|
*/
|
225
|
|
- private _findAffineMotionNDC(points: SpeedyMatrix): SpeedyPromise<SpeedyMatrixExpr>
|
|
243
|
+ private _findMotionNDC(points: SpeedyMatrix): SpeedyPromise<SpeedyMatrixExpr>
|
226
|
244
|
{
|
227
|
|
- return ImageTrackerUtils.findAffineWarpNDC(points, {
|
|
245
|
+ //return ImageTrackerUtils.findAffineWarpNDC(points, {
|
|
246
|
+ return ImageTrackerUtils.findPerspectiveWarpNDC(points, {
|
228
|
247
|
method: 'pransac',
|
229
|
|
- reprojectionError: TRACK_RANSAC_REPROJECTIONERROR_NDC,
|
230
|
|
- numberOfHypotheses: 512*4,
|
|
248
|
+ reprojectionError: PRE_TRACK_RANSAC_REPROJECTIONERROR_NDC,
|
|
249
|
+ numberOfHypotheses: 512*8, // we want a really good homography
|
231
|
250
|
bundleSize: 128,
|
232
|
251
|
mask: undefined // score is not needed
|
233
|
252
|
}).then(([ warp, score ]) => {
|
|
@@ -290,6 +309,8 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
290
|
309
|
|
291
|
310
|
const source = Speedy.Image.Source('source');
|
292
|
311
|
const imagePortalSource = Speedy.Image.Portal.Source('imagePortalSource');
|
|
312
|
+ const sourceMux = Speedy.Image.Multiplexer('sourceMux');
|
|
313
|
+ const sourceBuffer = Speedy.Image.Buffer('sourceBuffer');
|
293
|
314
|
const referenceKeypointPortalSource = Speedy.Keypoint.Portal.Source('referenceKeypointPortalSource');
|
294
|
315
|
const screen = Speedy.Transform.Resize('screen');
|
295
|
316
|
const greyscale = Speedy.Filter.Greyscale();
|
|
@@ -312,6 +333,8 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
312
|
333
|
|
313
|
334
|
source.media = null;
|
314
|
335
|
imagePortalSource.source = null;
|
|
336
|
+ sourceMux.port = 0; // 0 = portal; 1 = source
|
|
337
|
+ sourceBuffer.frozen = false;
|
315
|
338
|
referenceKeypointPortalSource.source = null;
|
316
|
339
|
imageRectifier.transform = Speedy.Matrix.Eye(3);
|
317
|
340
|
screen.size = Speedy.Size(0,0);
|
|
@@ -335,8 +358,10 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
335
|
358
|
keypointSink.turbo = false;
|
336
|
359
|
|
337
|
360
|
// prepare input
|
338
|
|
- //source.output(); // ignore, but keep it in the pipeline
|
339
|
|
- imagePortalSource.output().connectTo(screen.input());
|
|
361
|
+ source.output().connectTo(sourceBuffer.input());
|
|
362
|
+ imagePortalSource.output().connectTo(sourceMux.input('in0'));
|
|
363
|
+ sourceBuffer.output().connectTo(sourceMux.input('in1'));
|
|
364
|
+ sourceMux.output().connectTo(screen.input());
|
340
|
365
|
screen.output().connectTo(greyscale.input());
|
341
|
366
|
|
342
|
367
|
// preprocess images
|
|
@@ -374,7 +399,7 @@ export class ImageTrackerPreTrackingBState extends ImageTrackerState
|
374
|
399
|
|
375
|
400
|
// done!
|
376
|
401
|
pipeline.init(
|
377
|
|
- source, screen, imagePortalSource,
|
|
402
|
+ source, imagePortalSource, sourceBuffer, sourceMux, screen,
|
378
|
403
|
referenceKeypointPortalSource,
|
379
|
404
|
greyscale, imageRectifier,
|
380
|
405
|
nightvision, nightvisionMux,
|