@srsergio/taptapp-ar 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler/controller.d.ts +15 -22
- package/dist/compiler/controller.js +73 -92
- package/dist/compiler/detector/crop-detector.d.ts +20 -51
- package/dist/compiler/detector/crop-detector.js +21 -15
- package/dist/compiler/input-loader.d.ts +15 -17
- package/dist/compiler/input-loader.js +58 -76
- package/dist/compiler/matching/hamming-distance.js +4 -4
- package/dist/compiler/matching/matcher.js +2 -2
- package/dist/compiler/matching/matching.d.ts +2 -16
- package/dist/compiler/matching/matching.js +72 -60
- package/dist/compiler/offline-compiler.d.ts +14 -65
- package/dist/compiler/offline-compiler.js +86 -55
- package/dist/compiler/three.js +0 -4
- package/dist/compiler/tracker/tracker.d.ts +26 -12
- package/dist/compiler/tracker/tracker.js +158 -259
- package/dist/compiler/utils/worker-pool.d.ts +2 -1
- package/dist/compiler/utils/worker-pool.js +4 -8
- package/package.json +1 -1
- package/src/compiler/controller.js +71 -93
- package/src/compiler/detector/crop-detector.js +26 -15
- package/src/compiler/input-loader.js +62 -88
- package/src/compiler/matching/hamming-distance.js +4 -4
- package/src/compiler/matching/hough.js +1 -1
- package/src/compiler/matching/matcher.js +2 -2
- package/src/compiler/matching/matching.js +80 -72
- package/src/compiler/offline-compiler.js +92 -58
- package/src/compiler/three.js +0 -4
- package/src/compiler/tracker/tracker.js +183 -283
- package/src/compiler/utils/worker-pool.js +4 -8
- package/dist/compiler/compiler-base.d.ts +0 -8
- package/dist/compiler/compiler-base.js +0 -179
- package/dist/compiler/compiler.d.ts +0 -9
- package/dist/compiler/compiler.js +0 -24
- package/dist/compiler/compiler.worker.d.ts +0 -1
- package/dist/compiler/compiler.worker.js +0 -28
- package/dist/compiler/detector/detector.d.ts +0 -97
- package/dist/compiler/detector/detector.js +0 -1042
- package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/binomialFilter.js +0 -50
- package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/buildExtremas.js +0 -89
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +0 -7
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -79
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -68
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -57
- package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeLocalization.js +0 -50
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -100
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -29
- package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/extremaReduction.js +0 -50
- package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +0 -20
- package/dist/compiler/detector/kernels/cpu/fakeShader.js +0 -80
- package/dist/compiler/detector/kernels/cpu/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/cpu/index.js +0 -25
- package/dist/compiler/detector/kernels/cpu/prune.d.ts +0 -7
- package/dist/compiler/detector/kernels/cpu/prune.js +0 -62
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +0 -47
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -43
- package/dist/compiler/detector/kernels/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/index.js +0 -2
- package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/binomialFilter.js +0 -67
- package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/buildExtremas.js +0 -101
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -78
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -86
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -52
- package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeLocalization.js +0 -58
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -116
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -46
- package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/extremaReduction.js +0 -48
- package/dist/compiler/detector/kernels/webgl/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/webgl/index.js +0 -25
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +0 -49
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -56
- package/dist/compiler/tensorflow-setup.d.ts +0 -6
- package/dist/compiler/tensorflow-setup.js +0 -99
- package/src/compiler/compiler-base.js +0 -210
- package/src/compiler/compiler.js +0 -25
- package/src/compiler/compiler.worker.js +0 -30
- package/src/compiler/detector/detector.js +0 -1119
- package/src/compiler/detector/kernels/cpu/binomialFilter.js +0 -58
- package/src/compiler/detector/kernels/cpu/buildExtremas.js +0 -108
- package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -91
- package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -92
- package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -68
- package/src/compiler/detector/kernels/cpu/computeLocalization.js +0 -67
- package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -124
- package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -33
- package/src/compiler/detector/kernels/cpu/extremaReduction.js +0 -53
- package/src/compiler/detector/kernels/cpu/fakeShader.js +0 -88
- package/src/compiler/detector/kernels/cpu/index.js +0 -26
- package/src/compiler/detector/kernels/cpu/prune.js +0 -78
- package/src/compiler/detector/kernels/cpu/smoothHistograms.js +0 -57
- package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -51
- package/src/compiler/detector/kernels/index.js +0 -2
- package/src/compiler/detector/kernels/webgl/binomialFilter.js +0 -72
- package/src/compiler/detector/kernels/webgl/buildExtremas.js +0 -109
- package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -82
- package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -105
- package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -56
- package/src/compiler/detector/kernels/webgl/computeLocalization.js +0 -70
- package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -129
- package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -50
- package/src/compiler/detector/kernels/webgl/extremaReduction.js +0 -50
- package/src/compiler/detector/kernels/webgl/index.js +0 -26
- package/src/compiler/detector/kernels/webgl/smoothHistograms.js +0 -53
- package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -62
- package/src/compiler/tensorflow-setup.js +0 -116
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export class Controller {
|
|
2
|
-
constructor({ inputWidth, inputHeight, onUpdate, debugMode, maxTrack, warmupTolerance, missTolerance, filterMinCF, filterBeta, }: {
|
|
2
|
+
constructor({ inputWidth, inputHeight, onUpdate, debugMode, maxTrack, warmupTolerance, missTolerance, filterMinCF, filterBeta, worker, }: {
|
|
3
3
|
inputWidth: any;
|
|
4
4
|
inputHeight: any;
|
|
5
5
|
onUpdate?: null | undefined;
|
|
@@ -9,6 +9,7 @@ export class Controller {
|
|
|
9
9
|
missTolerance?: null | undefined;
|
|
10
10
|
filterMinCF?: null | undefined;
|
|
11
11
|
filterBeta?: null | undefined;
|
|
12
|
+
worker?: null | undefined;
|
|
12
13
|
});
|
|
13
14
|
inputWidth: any;
|
|
14
15
|
inputHeight: any;
|
|
@@ -25,12 +26,11 @@ export class Controller {
|
|
|
25
26
|
processingVideo: boolean;
|
|
26
27
|
interestedTargetIndex: number;
|
|
27
28
|
trackingStates: any[];
|
|
29
|
+
worker: any;
|
|
28
30
|
projectionTransform: number[][];
|
|
29
31
|
projectionMatrix: number[];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
workerTrackDone: ((data: any) => void) | null;
|
|
33
|
-
showTFStats(): void;
|
|
32
|
+
_setupWorkerListener(): void;
|
|
33
|
+
_ensureWorker(): void;
|
|
34
34
|
addImageTargets(fileURL: any): Promise<any>;
|
|
35
35
|
addImageTargetsFromBuffer(buffer: any): {
|
|
36
36
|
dimensions: any[][];
|
|
@@ -43,32 +43,23 @@ export class Controller {
|
|
|
43
43
|
getProjectionMatrix(): number[];
|
|
44
44
|
getRotatedZ90Matrix(m: any): any[];
|
|
45
45
|
getWorldMatrix(modelViewTransform: any, targetIndex: any): any[];
|
|
46
|
-
_detectAndMatch(
|
|
46
|
+
_detectAndMatch(inputData: any, targetIndexes: any): Promise<{
|
|
47
47
|
targetIndex: any;
|
|
48
48
|
modelViewTransform: any;
|
|
49
49
|
}>;
|
|
50
|
-
_trackAndUpdate(
|
|
50
|
+
_trackAndUpdate(inputData: any, lastModelViewTransform: any, targetIndex: any): Promise<any>;
|
|
51
51
|
processVideo(input: any): void;
|
|
52
52
|
stopProcessVideo(): void;
|
|
53
53
|
detect(input: any): Promise<{
|
|
54
|
-
featurePoints:
|
|
55
|
-
maxima: boolean;
|
|
56
|
-
x: number;
|
|
57
|
-
y: number;
|
|
58
|
-
scale: number;
|
|
59
|
-
angle: any;
|
|
60
|
-
descriptors: any[];
|
|
61
|
-
}[];
|
|
54
|
+
featurePoints: any[];
|
|
62
55
|
debugExtra: {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
prunedExtremas: number[][];
|
|
68
|
-
localizedExtremas: any;
|
|
69
|
-
} | null;
|
|
56
|
+
projectedImage: number[];
|
|
57
|
+
} | {
|
|
58
|
+
projectedImage?: undefined;
|
|
59
|
+
};
|
|
70
60
|
}>;
|
|
71
61
|
match(featurePoints: any, targetIndex: any): Promise<{
|
|
62
|
+
targetIndex: any;
|
|
72
63
|
modelViewTransform: any;
|
|
73
64
|
debugExtra: any;
|
|
74
65
|
}>;
|
|
@@ -86,7 +77,9 @@ export class Controller {
|
|
|
86
77
|
}>;
|
|
87
78
|
trackUpdate(modelViewTransform: any, trackFeatures: any): Promise<any>;
|
|
88
79
|
_workerMatch(featurePoints: any, targetIndexes: any): Promise<any>;
|
|
80
|
+
workerMatchDone: ((data: any) => void) | undefined;
|
|
89
81
|
_workerTrackUpdate(modelViewTransform: any, trackingFeatures: any): Promise<any>;
|
|
82
|
+
workerTrackDone: ((data: any) => void) | undefined;
|
|
90
83
|
_glModelViewMatrix(modelViewTransform: any, targetIndex: any): any[];
|
|
91
84
|
_glProjectionMatrix({ projectionTransform, width, height, near, far }: {
|
|
92
85
|
projectionTransform: any;
|
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { memory, nextFrame } from "@tensorflow/tfjs";
|
|
2
|
-
const tf = { memory, nextFrame };
|
|
3
|
-
import ControllerWorker from "./controller.worker.js?worker&inline";
|
|
4
1
|
import { Tracker } from "./tracker/tracker.js";
|
|
5
2
|
import { CropDetector } from "./detector/crop-detector.js";
|
|
6
|
-
import { Compiler } from "./compiler.js";
|
|
3
|
+
import { OfflineCompiler as Compiler } from "./offline-compiler.js";
|
|
7
4
|
import { InputLoader } from "./input-loader.js";
|
|
8
5
|
import { OneEuroFilter } from "../libs/one-euro-filter.js";
|
|
6
|
+
let ControllerWorker;
|
|
7
|
+
// Conditional import for worker to avoid crash in non-vite environments
|
|
8
|
+
try {
|
|
9
|
+
const workerModule = await import("./controller.worker.js?worker&inline");
|
|
10
|
+
ControllerWorker = workerModule.default;
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
// Fallback for tests or other environments
|
|
14
|
+
ControllerWorker = null;
|
|
15
|
+
}
|
|
9
16
|
const DEFAULT_FILTER_CUTOFF = 0.001; // 1Hz. time period in milliseconds
|
|
10
17
|
const DEFAULT_FILTER_BETA = 1000;
|
|
11
18
|
const DEFAULT_WARMUP_TOLERANCE = 5;
|
|
12
19
|
const DEFAULT_MISS_TOLERANCE = 5;
|
|
13
20
|
class Controller {
|
|
14
|
-
constructor({ inputWidth, inputHeight, onUpdate = null, debugMode = false, maxTrack = 1, warmupTolerance = null, missTolerance = null, filterMinCF = null, filterBeta = null,
|
|
21
|
+
constructor({ inputWidth, inputHeight, onUpdate = null, debugMode = false, maxTrack = 1, warmupTolerance = null, missTolerance = null, filterMinCF = null, filterBeta = null, worker = null, // Allow custom worker injection
|
|
22
|
+
}) {
|
|
15
23
|
this.inputWidth = inputWidth;
|
|
16
24
|
this.inputHeight = inputHeight;
|
|
17
25
|
this.maxTrack = maxTrack;
|
|
@@ -27,13 +35,13 @@ class Controller {
|
|
|
27
35
|
this.processingVideo = false;
|
|
28
36
|
this.interestedTargetIndex = -1;
|
|
29
37
|
this.trackingStates = [];
|
|
38
|
+
this.worker = worker;
|
|
39
|
+
if (this.worker)
|
|
40
|
+
this._setupWorkerListener();
|
|
30
41
|
const near = 10;
|
|
31
42
|
const far = 100000;
|
|
32
|
-
const fovy = (45.0 * Math.PI) / 180;
|
|
43
|
+
const fovy = (45.0 * Math.PI) / 180;
|
|
33
44
|
const f = this.inputHeight / 2 / Math.tan(fovy / 2);
|
|
34
|
-
// [fx s cx]
|
|
35
|
-
// K = [ 0 fx cy]
|
|
36
|
-
// [ 0 0 1]
|
|
37
45
|
this.projectionTransform = [
|
|
38
46
|
[f, 0, this.inputWidth / 2],
|
|
39
47
|
[0, f, this.inputHeight / 2],
|
|
@@ -46,9 +54,10 @@ class Controller {
|
|
|
46
54
|
near: near,
|
|
47
55
|
far: far,
|
|
48
56
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.
|
|
57
|
+
}
|
|
58
|
+
_setupWorkerListener() {
|
|
59
|
+
if (!this.worker)
|
|
60
|
+
return;
|
|
52
61
|
this.worker.onmessage = (e) => {
|
|
53
62
|
if (e.data.type === "matchDone" && this.workerMatchDone !== null) {
|
|
54
63
|
this.workerMatchDone(e.data);
|
|
@@ -58,9 +67,13 @@ class Controller {
|
|
|
58
67
|
}
|
|
59
68
|
};
|
|
60
69
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
_ensureWorker() {
|
|
71
|
+
if (this.worker)
|
|
72
|
+
return;
|
|
73
|
+
if (ControllerWorker) {
|
|
74
|
+
this.worker = new ControllerWorker();
|
|
75
|
+
this._setupWorkerListener();
|
|
76
|
+
}
|
|
64
77
|
}
|
|
65
78
|
addImageTargets(fileURL) {
|
|
66
79
|
return new Promise(async (resolve) => {
|
|
@@ -77,34 +90,37 @@ class Controller {
|
|
|
77
90
|
const matchingDataList = [];
|
|
78
91
|
const dimensions = [];
|
|
79
92
|
for (let i = 0; i < dataList.length; i++) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
const item = dataList[i];
|
|
94
|
+
matchingDataList.push(item.matchingData);
|
|
95
|
+
trackingDataList.push(item.trackingData);
|
|
96
|
+
dimensions.push([item.targetImage.width, item.targetImage.height]);
|
|
83
97
|
}
|
|
84
98
|
this.tracker = new Tracker(dimensions, trackingDataList, this.projectionTransform, this.inputWidth, this.inputHeight, this.debugMode);
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
this._ensureWorker();
|
|
100
|
+
if (this.worker) {
|
|
101
|
+
this.worker.postMessage({
|
|
102
|
+
type: "setup",
|
|
103
|
+
inputWidth: this.inputWidth,
|
|
104
|
+
inputHeight: this.inputHeight,
|
|
105
|
+
projectionTransform: this.projectionTransform,
|
|
106
|
+
debugMode: this.debugMode,
|
|
107
|
+
matchingDataList,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
93
110
|
this.markerDimensions = dimensions;
|
|
94
|
-
return { dimensions
|
|
111
|
+
return { dimensions, matchingDataList, trackingDataList };
|
|
95
112
|
}
|
|
96
113
|
dispose() {
|
|
97
114
|
this.stopProcessVideo();
|
|
98
|
-
this.worker
|
|
99
|
-
type: "dispose"
|
|
100
|
-
|
|
115
|
+
if (this.worker) {
|
|
116
|
+
this.worker.postMessage({ type: "dispose" });
|
|
117
|
+
this.worker = null;
|
|
118
|
+
}
|
|
101
119
|
}
|
|
102
|
-
// warm up gpu - build kernels is slow
|
|
103
120
|
dummyRun(input) {
|
|
104
|
-
const
|
|
105
|
-
this.cropDetector.detect(
|
|
106
|
-
this.tracker.dummyRun(
|
|
107
|
-
inputT.dispose();
|
|
121
|
+
const inputData = this.inputLoader.loadInput(input);
|
|
122
|
+
this.cropDetector.detect(inputData);
|
|
123
|
+
this.tracker.dummyRun(inputData);
|
|
108
124
|
}
|
|
109
125
|
getProjectionMatrix() {
|
|
110
126
|
return this.projectionMatrix;
|
|
@@ -139,13 +155,13 @@ class Controller {
|
|
|
139
155
|
getWorldMatrix(modelViewTransform, targetIndex) {
|
|
140
156
|
return this._glModelViewMatrix(modelViewTransform, targetIndex);
|
|
141
157
|
}
|
|
142
|
-
async _detectAndMatch(
|
|
143
|
-
const { featurePoints } = this.cropDetector.detectMoving(
|
|
158
|
+
async _detectAndMatch(inputData, targetIndexes) {
|
|
159
|
+
const { featurePoints } = this.cropDetector.detectMoving(inputData);
|
|
144
160
|
const { targetIndex: matchedTargetIndex, modelViewTransform } = await this._workerMatch(featurePoints, targetIndexes);
|
|
145
161
|
return { targetIndex: matchedTargetIndex, modelViewTransform };
|
|
146
162
|
}
|
|
147
|
-
async _trackAndUpdate(
|
|
148
|
-
const { worldCoords, screenCoords } = this.tracker.track(
|
|
163
|
+
async _trackAndUpdate(inputData, lastModelViewTransform, targetIndex) {
|
|
164
|
+
const { worldCoords, screenCoords } = this.tracker.track(inputData, lastModelViewTransform, targetIndex);
|
|
149
165
|
if (worldCoords.length < 4)
|
|
150
166
|
return null;
|
|
151
167
|
const modelViewTransform = await this._workerTrackUpdate(lastModelViewTransform, {
|
|
@@ -168,13 +184,12 @@ class Controller {
|
|
|
168
184
|
trackMiss: 0,
|
|
169
185
|
filter: new OneEuroFilter({ minCutOff: this.filterMinCF, beta: this.filterBeta }),
|
|
170
186
|
});
|
|
171
|
-
//console.log("filterMinCF", this.filterMinCF, this.filterBeta);
|
|
172
187
|
}
|
|
173
188
|
const startProcessing = async () => {
|
|
174
189
|
while (true) {
|
|
175
190
|
if (!this.processingVideo)
|
|
176
191
|
break;
|
|
177
|
-
const
|
|
192
|
+
const inputData = this.inputLoader.loadInput(input);
|
|
178
193
|
const nTracking = this.trackingStates.reduce((acc, s) => {
|
|
179
194
|
return acc + (!!s.isTracking ? 1 : 0);
|
|
180
195
|
}, 0);
|
|
@@ -189,7 +204,7 @@ class Controller {
|
|
|
189
204
|
continue;
|
|
190
205
|
matchingIndexes.push(i);
|
|
191
206
|
}
|
|
192
|
-
const { targetIndex: matchedTargetIndex, modelViewTransform } = await this._detectAndMatch(
|
|
207
|
+
const { targetIndex: matchedTargetIndex, modelViewTransform } = await this._detectAndMatch(inputData, matchingIndexes);
|
|
193
208
|
if (matchedTargetIndex !== -1) {
|
|
194
209
|
this.trackingStates[matchedTargetIndex].isTracking = true;
|
|
195
210
|
this.trackingStates[matchedTargetIndex].currentModelViewTransform = modelViewTransform;
|
|
@@ -199,7 +214,7 @@ class Controller {
|
|
|
199
214
|
for (let i = 0; i < this.trackingStates.length; i++) {
|
|
200
215
|
const trackingState = this.trackingStates[i];
|
|
201
216
|
if (trackingState.isTracking) {
|
|
202
|
-
let modelViewTransform = await this._trackAndUpdate(
|
|
217
|
+
let modelViewTransform = await this._trackAndUpdate(inputData, trackingState.currentModelViewTransform, i);
|
|
203
218
|
if (modelViewTransform === null) {
|
|
204
219
|
trackingState.isTracking = false;
|
|
205
220
|
}
|
|
@@ -251,9 +266,14 @@ class Controller {
|
|
|
251
266
|
this.onUpdate({ type: "updateMatrix", targetIndex: i, worldMatrix: clone });
|
|
252
267
|
}
|
|
253
268
|
}
|
|
254
|
-
inputT.dispose();
|
|
255
269
|
this.onUpdate && this.onUpdate({ type: "processDone" });
|
|
256
|
-
|
|
270
|
+
// Use requestAnimationFrame if available, otherwise just wait briefly
|
|
271
|
+
if (typeof requestAnimationFrame !== "undefined") {
|
|
272
|
+
await new Promise(requestAnimationFrame);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
await new Promise(resolve => setTimeout(resolve, 16));
|
|
276
|
+
}
|
|
257
277
|
}
|
|
258
278
|
};
|
|
259
279
|
startProcessing();
|
|
@@ -262,21 +282,19 @@ class Controller {
|
|
|
262
282
|
this.processingVideo = false;
|
|
263
283
|
}
|
|
264
284
|
async detect(input) {
|
|
265
|
-
const
|
|
266
|
-
const { featurePoints, debugExtra } = this.cropDetector.detect(
|
|
267
|
-
inputT.dispose();
|
|
285
|
+
const inputData = this.inputLoader.loadInput(input);
|
|
286
|
+
const { featurePoints, debugExtra } = this.cropDetector.detect(inputData);
|
|
268
287
|
return { featurePoints, debugExtra };
|
|
269
288
|
}
|
|
270
289
|
async match(featurePoints, targetIndex) {
|
|
271
|
-
const { modelViewTransform, debugExtra } = await this._workerMatch(featurePoints, [
|
|
290
|
+
const { targetIndex: matchedTargetIndex, modelViewTransform, debugExtra } = await this._workerMatch(featurePoints, [
|
|
272
291
|
targetIndex,
|
|
273
292
|
]);
|
|
274
|
-
return { modelViewTransform, debugExtra };
|
|
293
|
+
return { targetIndex: matchedTargetIndex, modelViewTransform, debugExtra };
|
|
275
294
|
}
|
|
276
295
|
async track(input, modelViewTransform, targetIndex) {
|
|
277
|
-
const
|
|
278
|
-
const result = this.tracker.track(
|
|
279
|
-
inputT.dispose();
|
|
296
|
+
const inputData = this.inputLoader.loadInput(input);
|
|
297
|
+
const result = this.tracker.track(inputData, modelViewTransform, targetIndex);
|
|
280
298
|
return result;
|
|
281
299
|
}
|
|
282
300
|
async trackUpdate(modelViewTransform, trackFeatures) {
|
|
@@ -294,7 +312,7 @@ class Controller {
|
|
|
294
312
|
debugExtra: data.debugExtra,
|
|
295
313
|
});
|
|
296
314
|
};
|
|
297
|
-
this.worker.postMessage({ type: "match", featurePoints: featurePoints, targetIndexes });
|
|
315
|
+
this.worker && this.worker.postMessage({ type: "match", featurePoints: featurePoints, targetIndexes });
|
|
298
316
|
});
|
|
299
317
|
}
|
|
300
318
|
_workerTrackUpdate(modelViewTransform, trackingFeatures) {
|
|
@@ -303,7 +321,7 @@ class Controller {
|
|
|
303
321
|
resolve(data.modelViewTransform);
|
|
304
322
|
};
|
|
305
323
|
const { worldCoords, screenCoords } = trackingFeatures;
|
|
306
|
-
this.worker.postMessage({
|
|
324
|
+
this.worker && this.worker.postMessage({
|
|
307
325
|
type: "trackUpdate",
|
|
308
326
|
modelViewTransform,
|
|
309
327
|
worldCoords,
|
|
@@ -313,41 +331,6 @@ class Controller {
|
|
|
313
331
|
}
|
|
314
332
|
_glModelViewMatrix(modelViewTransform, targetIndex) {
|
|
315
333
|
const height = this.markerDimensions[targetIndex][1];
|
|
316
|
-
// Question: can someone verify this interpreation is correct?
|
|
317
|
-
// I'm not very convinced, but more like trial and error and works......
|
|
318
|
-
//
|
|
319
|
-
// First, opengl has y coordinate system go from bottom to top, while the marker corrdinate goes from top to bottom,
|
|
320
|
-
// since the modelViewTransform is estimated in marker coordinate, we need to apply this transform before modelViewTransform
|
|
321
|
-
// I can see why y = h - y*, but why z = z* ? should we intepret it as rotate 90 deg along x-axis and then translate y by h?
|
|
322
|
-
//
|
|
323
|
-
// [1 0 0 0]
|
|
324
|
-
// [0 -1 0 h]
|
|
325
|
-
// [0 0 -1 0]
|
|
326
|
-
// [0 0 0 1]
|
|
327
|
-
//
|
|
328
|
-
// This is tested that if we reverse marker coordinate from bottom to top and estimate the modelViewTransform,
|
|
329
|
-
// then the above matrix is not necessary.
|
|
330
|
-
//
|
|
331
|
-
// Second, in opengl, positive z is away from camera, so we rotate 90 deg along x-axis after transform to fix the axis mismatch
|
|
332
|
-
// [1 1 0 0]
|
|
333
|
-
// [0 -1 0 0]
|
|
334
|
-
// [0 0 -1 0]
|
|
335
|
-
// [0 0 0 1]
|
|
336
|
-
//
|
|
337
|
-
// all together, the combined matrix is
|
|
338
|
-
//
|
|
339
|
-
// [1 1 0 0] [m00, m01, m02, m03] [1 0 0 0]
|
|
340
|
-
// [0 -1 0 0] [m10, m11, m12, m13] [0 -1 0 h]
|
|
341
|
-
// [0 0 -1 0] [m20, m21, m22, m23] [0 0 -1 0]
|
|
342
|
-
// [0 0 0 1] [ 0 0 0 1] [0 0 0 1]
|
|
343
|
-
//
|
|
344
|
-
// [ m00, -m01, -m02, (m01 * h + m03) ]
|
|
345
|
-
// [-m10, m11, m12, -(m11 * h + m13) ]
|
|
346
|
-
// = [-m20, m21, m22, -(m21 * h + m23) ]
|
|
347
|
-
// [ 0, 0, 0, 1 ]
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
// Finally, in threejs, matrix is represented in col by row, so we transpose it, and get below:
|
|
351
334
|
const openGLWorldMatrix = [
|
|
352
335
|
modelViewTransform[0][0],
|
|
353
336
|
-modelViewTransform[1][0],
|
|
@@ -368,8 +351,6 @@ class Controller {
|
|
|
368
351
|
];
|
|
369
352
|
return openGLWorldMatrix;
|
|
370
353
|
}
|
|
371
|
-
// build openGL projection matrix
|
|
372
|
-
// ref: https://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
|
|
373
354
|
_glProjectionMatrix({ projectionTransform, width, height, near, far }) {
|
|
374
355
|
const proj = [
|
|
375
356
|
[
|
|
@@ -4,62 +4,31 @@ export class CropDetector {
|
|
|
4
4
|
width: any;
|
|
5
5
|
height: any;
|
|
6
6
|
cropSize: number;
|
|
7
|
-
detector:
|
|
8
|
-
kernelCaches: {};
|
|
7
|
+
detector: DetectorLite;
|
|
9
8
|
lastRandomIndex: number;
|
|
10
|
-
detect(
|
|
11
|
-
featurePoints:
|
|
12
|
-
maxima: boolean;
|
|
13
|
-
x: number;
|
|
14
|
-
y: number;
|
|
15
|
-
scale: number;
|
|
16
|
-
angle: any;
|
|
17
|
-
descriptors: any[];
|
|
18
|
-
}[];
|
|
9
|
+
detect(input: any): {
|
|
10
|
+
featurePoints: any[];
|
|
19
11
|
debugExtra: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
prunedExtremas: number[][];
|
|
25
|
-
localizedExtremas: any;
|
|
26
|
-
} | null;
|
|
12
|
+
projectedImage: number[];
|
|
13
|
+
} | {
|
|
14
|
+
projectedImage?: undefined;
|
|
15
|
+
};
|
|
27
16
|
};
|
|
28
|
-
detectMoving(
|
|
29
|
-
featurePoints:
|
|
30
|
-
maxima: boolean;
|
|
31
|
-
x: number;
|
|
32
|
-
y: number;
|
|
33
|
-
scale: number;
|
|
34
|
-
angle: any;
|
|
35
|
-
descriptors: any[];
|
|
36
|
-
}[];
|
|
17
|
+
detectMoving(input: any): {
|
|
18
|
+
featurePoints: any[];
|
|
37
19
|
debugExtra: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
prunedExtremas: number[][];
|
|
43
|
-
localizedExtremas: any;
|
|
44
|
-
} | null;
|
|
20
|
+
projectedImage: number[];
|
|
21
|
+
} | {
|
|
22
|
+
projectedImage?: undefined;
|
|
23
|
+
};
|
|
45
24
|
};
|
|
46
|
-
_detect(
|
|
47
|
-
featurePoints:
|
|
48
|
-
maxima: boolean;
|
|
49
|
-
x: number;
|
|
50
|
-
y: number;
|
|
51
|
-
scale: number;
|
|
52
|
-
angle: any;
|
|
53
|
-
descriptors: any[];
|
|
54
|
-
}[];
|
|
25
|
+
_detect(imageData: any, startX: any, startY: any): {
|
|
26
|
+
featurePoints: any[];
|
|
55
27
|
debugExtra: {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
prunedExtremas: number[][];
|
|
61
|
-
localizedExtremas: any;
|
|
62
|
-
} | null;
|
|
28
|
+
projectedImage: number[];
|
|
29
|
+
} | {
|
|
30
|
+
projectedImage?: undefined;
|
|
31
|
+
};
|
|
63
32
|
};
|
|
64
33
|
}
|
|
65
|
-
import {
|
|
34
|
+
import { DetectorLite } from "./detector-lite.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DetectorLite } from "./detector-lite.js";
|
|
2
2
|
class CropDetector {
|
|
3
3
|
constructor(width, height, debugMode = false) {
|
|
4
4
|
this.debugMode = debugMode;
|
|
@@ -8,21 +8,22 @@ class CropDetector {
|
|
|
8
8
|
let minDimension = Math.min(width, height) / 2;
|
|
9
9
|
let cropSize = Math.pow(2, Math.round(Math.log(minDimension) / Math.log(2)));
|
|
10
10
|
this.cropSize = cropSize;
|
|
11
|
-
this.detector = new
|
|
12
|
-
this.kernelCaches = {};
|
|
11
|
+
this.detector = new DetectorLite(cropSize, cropSize);
|
|
13
12
|
this.lastRandomIndex = 4;
|
|
14
13
|
}
|
|
15
|
-
detect(
|
|
14
|
+
detect(input) {
|
|
15
|
+
const imageData = input;
|
|
16
16
|
// crop center
|
|
17
17
|
const startY = Math.floor(this.height / 2 - this.cropSize / 2);
|
|
18
18
|
const startX = Math.floor(this.width / 2 - this.cropSize / 2);
|
|
19
|
-
const result = this._detect(
|
|
19
|
+
const result = this._detect(imageData, startX, startY);
|
|
20
20
|
if (this.debugMode) {
|
|
21
21
|
result.debugExtra.crop = { startX, startY, cropSize: this.cropSize };
|
|
22
22
|
}
|
|
23
23
|
return result;
|
|
24
24
|
}
|
|
25
|
-
detectMoving(
|
|
25
|
+
detectMoving(input) {
|
|
26
|
+
const imageData = input;
|
|
26
27
|
// loop a few locations around center
|
|
27
28
|
const dx = this.lastRandomIndex % 3;
|
|
28
29
|
const dy = Math.floor(this.lastRandomIndex / 3);
|
|
@@ -37,21 +38,26 @@ class CropDetector {
|
|
|
37
38
|
if (startY >= this.height - this.cropSize)
|
|
38
39
|
startY = this.height - this.cropSize - 1;
|
|
39
40
|
this.lastRandomIndex = (this.lastRandomIndex + 1) % 9;
|
|
40
|
-
const result = this._detect(
|
|
41
|
+
const result = this._detect(imageData, startX, startY);
|
|
41
42
|
return result;
|
|
42
43
|
}
|
|
43
|
-
_detect(
|
|
44
|
-
|
|
45
|
-
const
|
|
44
|
+
_detect(imageData, startX, startY) {
|
|
45
|
+
// Crop manually since imageData is now a flat array (width * height)
|
|
46
|
+
const croppedData = new Float32Array(this.cropSize * this.cropSize);
|
|
47
|
+
for (let y = 0; y < this.cropSize; y++) {
|
|
48
|
+
for (let x = 0; x < this.cropSize; x++) {
|
|
49
|
+
croppedData[y * this.cropSize + x] = imageData[(startY + y) * this.width + (startX + x)];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const { featurePoints } = this.detector.detect(croppedData);
|
|
46
53
|
featurePoints.forEach((p) => {
|
|
47
54
|
p.x += startX;
|
|
48
55
|
p.y += startY;
|
|
49
56
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return { featurePoints: featurePoints, debugExtra };
|
|
57
|
+
return {
|
|
58
|
+
featurePoints,
|
|
59
|
+
debugExtra: this.debugMode ? { projectedImage: Array.from(croppedData) } : {}
|
|
60
|
+
};
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
63
|
export { CropDetector };
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InputLoader - Maneja la carga de imágenes y video sin TensorFlow
|
|
3
|
+
*/
|
|
1
4
|
export class InputLoader {
|
|
2
5
|
constructor(width: any, height: any);
|
|
3
6
|
width: any;
|
|
4
7
|
height: any;
|
|
5
|
-
|
|
6
|
-
context: CanvasRenderingContext2D | null;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
outputShape: any[];
|
|
18
|
-
userCode: string;
|
|
19
|
-
};
|
|
20
|
-
_compileAndRun(program: any, inputs: any): any;
|
|
21
|
-
_runWebGLProgram(program: any, inputs: any, outputType: any): any;
|
|
8
|
+
grayscaleBuffer: Uint8Array<ArrayBuffer>;
|
|
9
|
+
context: CanvasRenderingContext2D | null | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Carga una imagen o video y devuelve los datos en escala de grises
|
|
12
|
+
* @param {HTMLVideoElement|HTMLImageElement|ImageData|Uint8Array} input - La fuente de entrada
|
|
13
|
+
* @returns {Uint8Array} Datos de imagen en escala de grises (width * height)
|
|
14
|
+
*/
|
|
15
|
+
loadInput(input: HTMLVideoElement | HTMLImageElement | ImageData | Uint8Array): Uint8Array;
|
|
16
|
+
/**
|
|
17
|
+
* Convierte datos RGBA a escala de grises optimizada (reutilizando buffer)
|
|
18
|
+
*/
|
|
19
|
+
_convertToGrayscale(rgbaData: any, width: any, height: any): void;
|
|
22
20
|
}
|