@srsergio/taptapp-ar 1.0.0
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/README.md +62 -0
- package/dist/compiler/aframe.d.ts +1 -0
- package/dist/compiler/aframe.js +275 -0
- package/dist/compiler/compiler-base.d.ts +12 -0
- package/dist/compiler/compiler-base.js +165 -0
- package/dist/compiler/compiler.d.ts +9 -0
- package/dist/compiler/compiler.js +24 -0
- package/dist/compiler/compiler.worker.d.ts +1 -0
- package/dist/compiler/compiler.worker.js +28 -0
- package/dist/compiler/controller.d.ts +101 -0
- package/dist/compiler/controller.js +400 -0
- package/dist/compiler/controller.worker.d.ts +1 -0
- package/dist/compiler/controller.worker.js +61 -0
- package/dist/compiler/detector/crop-detector.d.ts +65 -0
- package/dist/compiler/detector/crop-detector.js +59 -0
- package/dist/compiler/detector/detector.d.ts +98 -0
- package/dist/compiler/detector/detector.js +1049 -0
- package/dist/compiler/detector/freak.d.ts +1 -0
- package/dist/compiler/detector/freak.js +89 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
- package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/index.js +25 -0
- package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
- package/dist/compiler/detector/kernels/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/index.js +2 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
- package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/webgl/index.js +25 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
- package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
- package/dist/compiler/estimation/esimate-experiment.js +267 -0
- package/dist/compiler/estimation/estimate.d.ts +5 -0
- package/dist/compiler/estimation/estimate.js +51 -0
- package/dist/compiler/estimation/estimator.d.ts +13 -0
- package/dist/compiler/estimation/estimator.js +30 -0
- package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
- package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate.js +299 -0
- package/dist/compiler/estimation/utils.d.ts +10 -0
- package/dist/compiler/estimation/utils.js +80 -0
- package/dist/compiler/image-list.d.ts +13 -0
- package/dist/compiler/image-list.js +52 -0
- package/dist/compiler/index.d.ts +3 -0
- package/dist/compiler/index.js +10 -0
- package/dist/compiler/input-loader.d.ts +23 -0
- package/dist/compiler/input-loader.js +88 -0
- package/dist/compiler/matching/hamming-distance.d.ts +1 -0
- package/dist/compiler/matching/hamming-distance.js +20 -0
- package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
- package/dist/compiler/matching/hierarchical-clustering.js +109 -0
- package/dist/compiler/matching/hough.d.ts +1 -0
- package/dist/compiler/matching/hough.js +169 -0
- package/dist/compiler/matching/matcher.d.ts +28 -0
- package/dist/compiler/matching/matcher.js +48 -0
- package/dist/compiler/matching/matching.d.ts +41 -0
- package/dist/compiler/matching/matching.js +197 -0
- package/dist/compiler/matching/ransacHomography.d.ts +1 -0
- package/dist/compiler/matching/ransacHomography.js +136 -0
- package/dist/compiler/offline-compiler.d.ts +10 -0
- package/dist/compiler/offline-compiler.js +450 -0
- package/dist/compiler/tensorflow-setup.d.ts +7 -0
- package/dist/compiler/tensorflow-setup.js +73 -0
- package/dist/compiler/three.d.ts +66 -0
- package/dist/compiler/three.js +310 -0
- package/dist/compiler/tracker/extract-utils.d.ts +1 -0
- package/dist/compiler/tracker/extract-utils.js +29 -0
- package/dist/compiler/tracker/extract.d.ts +4 -0
- package/dist/compiler/tracker/extract.js +349 -0
- package/dist/compiler/tracker/tracker.d.ts +38 -0
- package/dist/compiler/tracker/tracker.js +327 -0
- package/dist/compiler/utils/cumsum.d.ts +5 -0
- package/dist/compiler/utils/cumsum.js +39 -0
- package/dist/compiler/utils/geometry.d.ts +8 -0
- package/dist/compiler/utils/geometry.js +101 -0
- package/dist/compiler/utils/homography.d.ts +1 -0
- package/dist/compiler/utils/homography.js +138 -0
- package/dist/compiler/utils/images.d.ts +24 -0
- package/dist/compiler/utils/images.js +99 -0
- package/dist/compiler/utils/randomizer.d.ts +5 -0
- package/dist/compiler/utils/randomizer.js +25 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/react/AREditor.d.ts +5 -0
- package/dist/react/AREditor.js +159 -0
- package/dist/react/ProgressDialog.d.ts +13 -0
- package/dist/react/ProgressDialog.js +57 -0
- package/dist/react/types.d.ts +22 -0
- package/dist/react/types.js +14 -0
- package/package.json +53 -0
- package/src/astro/ARScene.astro +59 -0
- package/src/astro/ARVideoTrigger.astro +73 -0
- package/src/astro/overlays/ErrorOverlay.astro +40 -0
- package/src/astro/overlays/LoadingOverlay.astro +28 -0
- package/src/astro/overlays/ScanningOverlay.astro +119 -0
- package/src/astro/scripts/ARScripts.astro +118 -0
- package/src/astro/styles/ARStyles.astro +147 -0
- package/src/compiler/aframe.js +343 -0
- package/src/compiler/compiler-base.js +195 -0
- package/src/compiler/compiler.js +25 -0
- package/src/compiler/compiler.worker.js +30 -0
- package/src/compiler/controller.js +473 -0
- package/src/compiler/controller.worker.js +77 -0
- package/src/compiler/detector/crop-detector.js +68 -0
- package/src/compiler/detector/detector.js +1130 -0
- package/src/compiler/detector/freak.js +91 -0
- package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
- package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
- package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
- package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
- package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
- package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
- package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
- package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
- package/src/compiler/detector/kernels/cpu/index.js +26 -0
- package/src/compiler/detector/kernels/cpu/prune.js +114 -0
- package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
- package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
- package/src/compiler/detector/kernels/index.js +2 -0
- package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
- package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
- package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
- package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
- package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
- package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
- package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
- package/src/compiler/detector/kernels/webgl/index.js +26 -0
- package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
- package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
- package/src/compiler/estimation/esimate-experiment.js +316 -0
- package/src/compiler/estimation/estimate.js +67 -0
- package/src/compiler/estimation/estimator.js +34 -0
- package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
- package/src/compiler/estimation/refine-estimate.js +365 -0
- package/src/compiler/estimation/utils.js +97 -0
- package/src/compiler/image-list.js +62 -0
- package/src/compiler/index.js +13 -0
- package/src/compiler/input-loader.js +107 -0
- package/src/compiler/matching/hamming-distance.js +23 -0
- package/src/compiler/matching/hierarchical-clustering.js +131 -0
- package/src/compiler/matching/hough.js +206 -0
- package/src/compiler/matching/matcher.js +59 -0
- package/src/compiler/matching/matching.js +237 -0
- package/src/compiler/matching/ransacHomography.js +192 -0
- package/src/compiler/offline-compiler.js +553 -0
- package/src/compiler/tensorflow-setup.js +88 -0
- package/src/compiler/three.js +368 -0
- package/src/compiler/tracker/extract-utils.js +34 -0
- package/src/compiler/tracker/extract.js +419 -0
- package/src/compiler/tracker/tracker.js +397 -0
- package/src/compiler/utils/cumsum.js +40 -0
- package/src/compiler/utils/geometry.js +114 -0
- package/src/compiler/utils/homography.js +150 -0
- package/src/compiler/utils/images.js +111 -0
- package/src/compiler/utils/randomizer.js +29 -0
- package/src/index.ts +8 -0
- package/src/react/AREditor.tsx +394 -0
- package/src/react/ProgressDialog.tsx +185 -0
- package/src/react/types.ts +35 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trying to do normalization before running ICP
|
|
3
|
+
* i.e. make coodinates centroid at origin and avg distance from origin is sqrt(2)
|
|
4
|
+
*
|
|
5
|
+
* can we get rid of projectionTransform, and just do ICP on modelViewTransform?
|
|
6
|
+
*
|
|
7
|
+
* but couldn't make it work yet. Can someone with theoretical knowledge on ICP reach out to help?, particularly Multiview Levenberg-Marquardt ICP
|
|
8
|
+
* I have problem understanding the jacobian and things like that
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
import { Matrix, inverse } from "ml-matrix";
|
|
12
|
+
import { applyModelViewProjectionTransform, buildModelViewProjectionTransform, computeScreenCoordiate, } from "./utils.js";
|
|
13
|
+
const TRACKING_THRESH = 5.0; // default
|
|
14
|
+
const K2_FACTOR = 4.0; // Question: should it be relative to the size of the screen instead of hardcoded?
|
|
15
|
+
const ICP_MAX_LOOP = 10;
|
|
16
|
+
const ICP_BREAK_LOOP_ERROR_THRESH = 0.1;
|
|
17
|
+
const ICP_BREAK_LOOP_ERROR_RATIO_THRESH = 0.99;
|
|
18
|
+
const ICP_BREAK_LOOP_ERROR_THRESH2 = 4.0;
|
|
19
|
+
// some temporary/intermediate variables used later. Declare them beforehand to reduce new object allocations
|
|
20
|
+
let mat = [[], [], []];
|
|
21
|
+
let J_U_Xc = [[], []]; // 2x3
|
|
22
|
+
let J_Xc_S = [[], [], []]; // 3x6
|
|
23
|
+
const refineEstimate = ({ initialModelViewTransform, projectionTransform, worldCoords: inWorldCoords, screenCoords: inScreenCoords, }) => {
|
|
24
|
+
const { normalizedCoords: worldCoords, param: worldParam } = normalizePoints(inWorldCoords);
|
|
25
|
+
const { normalizedCoords: screenCoords, param: screenParam } = normalizePoints(inScreenCoords);
|
|
26
|
+
const modelViewProjectionTransform = buildModelViewProjectionTransform(projectionTransform, initialModelViewTransform);
|
|
27
|
+
const normModelViewProjectionTransform = _getNormalizedModelViewTransform(modelViewProjectionTransform, worldParam, screenParam);
|
|
28
|
+
/*
|
|
29
|
+
* porjection matrix
|
|
30
|
+
* [k00, 0, k02]
|
|
31
|
+
* K = [ 0, k11, k12]
|
|
32
|
+
* [ 0, 0, 1]
|
|
33
|
+
*
|
|
34
|
+
* [1/k00, 0, -k02/k00]
|
|
35
|
+
* inv(K) = [ 0, 1/k11, -k12/k11]
|
|
36
|
+
* [ 0, 0, 1]
|
|
37
|
+
*
|
|
38
|
+
*
|
|
39
|
+
* denote modelViewProjectionTransform as A,
|
|
40
|
+
* since A = K * M, M = inv(K) * A
|
|
41
|
+
*
|
|
42
|
+
* [a00 / k00 - a20 * k02/k00, a01 / k00 - k02/k00 * a21, a02 / k00 - k02/k00 * a22, a03 / k00 - k02/k00 * a23]
|
|
43
|
+
* M = [a10 / k11 - a20 * k12/k11, a11 / k11 - k12/k11 * a21, a13 / k11 - k12/k11 * a22, a13 / k11 - k12/111 * a23]
|
|
44
|
+
* [ a20 , a21, a22, a23]
|
|
45
|
+
*/
|
|
46
|
+
const a = normModelViewProjectionTransform;
|
|
47
|
+
const k = projectionTransform;
|
|
48
|
+
const normModelViewTransform = [
|
|
49
|
+
[
|
|
50
|
+
a[0][0] / k[0][0] - (a[2][0] * k[0][2]) / k[0][0],
|
|
51
|
+
a[0][1] / k[0][0] - (a[2][1] * k[0][2]) / k[0][0],
|
|
52
|
+
a[0][2] / k[0][0] - (a[2][2] * k[0][2]) / k[0][0],
|
|
53
|
+
a[0][3] / k[0][0] - (a[2][3] * k[0][2]) / k[0][0],
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
a[1][0] / k[1][1] - (a[2][0] * k[1][2]) / k[1][1],
|
|
57
|
+
a[1][1] / k[1][1] - (a[2][1] * k[1][2]) / k[1][1],
|
|
58
|
+
a[1][2] / k[1][1] - (a[2][2] * k[1][2]) / k[1][1],
|
|
59
|
+
a[1][3] / k[1][1] - (a[2][3] * k[1][2]) / k[1][1],
|
|
60
|
+
],
|
|
61
|
+
[a[2][0], a[2][1], a[2][2], a[2][3]],
|
|
62
|
+
];
|
|
63
|
+
const inlierProbs = [1.0, 0.8, 0.6, 0.4, 0.0];
|
|
64
|
+
let updatedModelViewTransform = normModelViewTransform;
|
|
65
|
+
let finalModelViewTransform = null;
|
|
66
|
+
for (let i = 0; i < inlierProbs.length; i++) {
|
|
67
|
+
const ret = _doICP({
|
|
68
|
+
initialModelViewTransform: updatedModelViewTransform,
|
|
69
|
+
projectionTransform,
|
|
70
|
+
worldCoords,
|
|
71
|
+
screenCoords,
|
|
72
|
+
inlierProb: inlierProbs[i],
|
|
73
|
+
});
|
|
74
|
+
updatedModelViewTransform = ret.modelViewTransform;
|
|
75
|
+
if (ret.err < TRACKING_THRESH) {
|
|
76
|
+
finalModelViewTransform = updatedModelViewTransform;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (finalModelViewTransform === null)
|
|
81
|
+
return null;
|
|
82
|
+
const denormModelViewTransform = _getDenormalizedModelViewTransform(finalModelViewTransform, worldParam, screenParam);
|
|
83
|
+
return denormModelViewTransform;
|
|
84
|
+
};
|
|
85
|
+
// ICP iteration
|
|
86
|
+
// Question: can someone provide theoretical reference / mathematical proof for the following computations?
|
|
87
|
+
// I'm unable to derive the Jacobian
|
|
88
|
+
const _doICP = ({ initialModelViewTransform, projectionTransform, worldCoords, screenCoords, inlierProb, }) => {
|
|
89
|
+
const isRobustMode = inlierProb < 1;
|
|
90
|
+
let modelViewTransform = initialModelViewTransform;
|
|
91
|
+
let err0 = 0.0;
|
|
92
|
+
let err1 = 0.0;
|
|
93
|
+
let E = new Array(worldCoords.length);
|
|
94
|
+
let E2 = new Array(worldCoords.length);
|
|
95
|
+
let dxs = new Array(worldCoords.length);
|
|
96
|
+
let dys = new Array(worldCoords.length);
|
|
97
|
+
for (let l = 0; l <= ICP_MAX_LOOP; l++) {
|
|
98
|
+
const modelViewProjectionTransform = buildModelViewProjectionTransform(projectionTransform, modelViewTransform);
|
|
99
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
100
|
+
const u = computeScreenCoordiate(modelViewProjectionTransform, worldCoords[n].x, worldCoords[n].y, worldCoords[n].z);
|
|
101
|
+
const dx = screenCoords[n].x - u.x;
|
|
102
|
+
const dy = screenCoords[n].y - u.y;
|
|
103
|
+
console.log("icp err", worldCoords[n], u, screenCoords[n]);
|
|
104
|
+
dxs[n] = dx;
|
|
105
|
+
dys[n] = dy;
|
|
106
|
+
E[n] = dx * dx + dy * dy;
|
|
107
|
+
}
|
|
108
|
+
let K2; // robust mode only
|
|
109
|
+
err1 = 0.0;
|
|
110
|
+
if (isRobustMode) {
|
|
111
|
+
const inlierNum = Math.max(3, Math.floor(worldCoords.length * inlierProb) - 1);
|
|
112
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
113
|
+
E2[n] = E[n];
|
|
114
|
+
}
|
|
115
|
+
E2.sort((a, b) => {
|
|
116
|
+
return a - b;
|
|
117
|
+
});
|
|
118
|
+
K2 = Math.max(E2[inlierNum] * K2_FACTOR, 16.0);
|
|
119
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
120
|
+
if (E2[n] > K2)
|
|
121
|
+
err1 += K2 / 6;
|
|
122
|
+
else
|
|
123
|
+
err1 += (K2 / 6.0) * (1.0 - (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
128
|
+
err1 += E[n];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
err1 /= worldCoords.length;
|
|
132
|
+
console.log("icp loop", inlierProb, l, err1);
|
|
133
|
+
if (err1 < ICP_BREAK_LOOP_ERROR_THRESH)
|
|
134
|
+
break;
|
|
135
|
+
//if (l > 0 && err1 < ICP_BREAK_LOOP_ERROR_THRESH2 && err1/err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH) break;
|
|
136
|
+
if (l > 0 && err1 / err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH)
|
|
137
|
+
break;
|
|
138
|
+
if (l === ICP_MAX_LOOP)
|
|
139
|
+
break;
|
|
140
|
+
err0 = err1;
|
|
141
|
+
const dU = [];
|
|
142
|
+
const allJ_U_S = [];
|
|
143
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
144
|
+
if (isRobustMode && E[n] > K2) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const J_U_S = _getJ_U_S({
|
|
148
|
+
modelViewProjectionTransform,
|
|
149
|
+
modelViewTransform,
|
|
150
|
+
projectionTransform,
|
|
151
|
+
worldCoord: worldCoords[n],
|
|
152
|
+
});
|
|
153
|
+
if (isRobustMode) {
|
|
154
|
+
const W = (1.0 - E[n] / K2) * (1.0 - E[n] / K2);
|
|
155
|
+
for (let j = 0; j < 2; j++) {
|
|
156
|
+
for (let i = 0; i < 6; i++) {
|
|
157
|
+
J_U_S[j][i] *= W;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
dU.push([dxs[n] * W]);
|
|
161
|
+
dU.push([dys[n] * W]);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
dU.push([dxs[n]]);
|
|
165
|
+
dU.push([dys[n]]);
|
|
166
|
+
}
|
|
167
|
+
for (let i = 0; i < J_U_S.length; i++) {
|
|
168
|
+
allJ_U_S.push(J_U_S[i]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const dS = _getDeltaS({ dU, J_U_S: allJ_U_S });
|
|
172
|
+
if (dS === null)
|
|
173
|
+
break;
|
|
174
|
+
modelViewTransform = _updateModelViewTransform({ modelViewTransform, dS });
|
|
175
|
+
}
|
|
176
|
+
return { modelViewTransform, err: err1 };
|
|
177
|
+
};
|
|
178
|
+
const _updateModelViewTransform = ({ modelViewTransform, dS }) => {
|
|
179
|
+
let ra = dS[0] * dS[0] + dS[1] * dS[1] + dS[2] * dS[2];
|
|
180
|
+
let q0, q1, q2;
|
|
181
|
+
if (ra < 0.000001) {
|
|
182
|
+
q0 = 1.0;
|
|
183
|
+
q1 = 0.0;
|
|
184
|
+
q2 = 0.0;
|
|
185
|
+
ra = 0.0;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
ra = Math.sqrt(ra);
|
|
189
|
+
q0 = dS[0] / ra;
|
|
190
|
+
q1 = dS[1] / ra;
|
|
191
|
+
q2 = dS[2] / ra;
|
|
192
|
+
}
|
|
193
|
+
const cra = Math.cos(ra);
|
|
194
|
+
const sra = Math.sin(ra);
|
|
195
|
+
const one_cra = 1.0 - cra;
|
|
196
|
+
mat[0][0] = q0 * q0 * one_cra + cra;
|
|
197
|
+
mat[0][1] = q0 * q1 * one_cra - q2 * sra;
|
|
198
|
+
mat[0][2] = q0 * q2 * one_cra + q1 * sra;
|
|
199
|
+
mat[0][3] = dS[3];
|
|
200
|
+
mat[1][0] = q1 * q0 * one_cra + q2 * sra;
|
|
201
|
+
mat[1][1] = q1 * q1 * one_cra + cra;
|
|
202
|
+
mat[1][2] = q1 * q2 * one_cra - q0 * sra;
|
|
203
|
+
mat[1][3] = dS[4];
|
|
204
|
+
mat[2][0] = q2 * q0 * one_cra - q1 * sra;
|
|
205
|
+
mat[2][1] = q2 * q1 * one_cra + q0 * sra;
|
|
206
|
+
mat[2][2] = q2 * q2 * one_cra + cra;
|
|
207
|
+
mat[2][3] = dS[5];
|
|
208
|
+
const mat2 = [[], [], []];
|
|
209
|
+
for (let j = 0; j < 3; j++) {
|
|
210
|
+
for (let i = 0; i < 4; i++) {
|
|
211
|
+
mat2[j][i] =
|
|
212
|
+
modelViewTransform[j][0] * mat[0][i] +
|
|
213
|
+
modelViewTransform[j][1] * mat[1][i] +
|
|
214
|
+
modelViewTransform[j][2] * mat[2][i];
|
|
215
|
+
}
|
|
216
|
+
mat2[j][3] += modelViewTransform[j][3];
|
|
217
|
+
}
|
|
218
|
+
return mat2;
|
|
219
|
+
};
|
|
220
|
+
const _getDeltaS = ({ dU, J_U_S }) => {
|
|
221
|
+
const J = new Matrix(J_U_S);
|
|
222
|
+
const U = new Matrix(dU);
|
|
223
|
+
const JT = J.transpose();
|
|
224
|
+
const JTJ = JT.mmul(J);
|
|
225
|
+
const JTU = JT.mmul(U);
|
|
226
|
+
let JTJInv;
|
|
227
|
+
try {
|
|
228
|
+
JTJInv = inverse(JTJ);
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const S = JTJInv.mmul(JTU);
|
|
234
|
+
return S.to1DArray();
|
|
235
|
+
};
|
|
236
|
+
const _getJ_U_S = ({ modelViewProjectionTransform, modelViewTransform, projectionTransform, worldCoord, }) => {
|
|
237
|
+
const T = modelViewTransform;
|
|
238
|
+
const { x, y, z } = worldCoord;
|
|
239
|
+
const u = applyModelViewProjectionTransform(modelViewProjectionTransform, x, y, z);
|
|
240
|
+
const z2 = u.z * u.z;
|
|
241
|
+
J_U_Xc[0][0] = (projectionTransform[0][0] * u.z - projectionTransform[2][0] * u.x) / z2;
|
|
242
|
+
J_U_Xc[0][1] = (projectionTransform[0][1] * u.z - projectionTransform[2][1] * u.x) / z2;
|
|
243
|
+
J_U_Xc[0][2] = (projectionTransform[0][2] * u.z - projectionTransform[2][2] * u.x) / z2;
|
|
244
|
+
J_U_Xc[1][0] = (projectionTransform[1][0] * u.z - projectionTransform[2][0] * u.y) / z2;
|
|
245
|
+
J_U_Xc[1][1] = (projectionTransform[1][1] * u.z - projectionTransform[2][1] * u.y) / z2;
|
|
246
|
+
J_U_Xc[1][2] = (projectionTransform[1][2] * u.z - projectionTransform[2][2] * u.y) / z2;
|
|
247
|
+
J_Xc_S[0][0] = T[0][2] * y;
|
|
248
|
+
J_Xc_S[0][1] = -T[0][2] * x;
|
|
249
|
+
J_Xc_S[0][2] = T[0][1] * x - T[0][0] * y;
|
|
250
|
+
J_Xc_S[0][3] = T[0][0];
|
|
251
|
+
J_Xc_S[0][4] = T[0][1];
|
|
252
|
+
J_Xc_S[0][5] = T[0][2];
|
|
253
|
+
J_Xc_S[1][0] = T[1][2] * y;
|
|
254
|
+
J_Xc_S[1][1] = -T[1][2] * x;
|
|
255
|
+
J_Xc_S[1][2] = T[1][1] * x - T[1][0] * y;
|
|
256
|
+
J_Xc_S[1][3] = T[1][0];
|
|
257
|
+
J_Xc_S[1][4] = T[1][1];
|
|
258
|
+
J_Xc_S[1][5] = T[1][2];
|
|
259
|
+
J_Xc_S[2][0] = T[2][2] * y;
|
|
260
|
+
J_Xc_S[2][1] = -T[2][2] * x;
|
|
261
|
+
J_Xc_S[2][2] = T[2][1] * x - T[2][0] * y;
|
|
262
|
+
J_Xc_S[2][3] = T[2][0];
|
|
263
|
+
J_Xc_S[2][4] = T[2][1];
|
|
264
|
+
J_Xc_S[2][5] = T[2][2];
|
|
265
|
+
const J_U_S = [[], []];
|
|
266
|
+
for (let j = 0; j < 2; j++) {
|
|
267
|
+
for (let i = 0; i < 6; i++) {
|
|
268
|
+
J_U_S[j][i] = 0.0;
|
|
269
|
+
for (let k = 0; k < 3; k++) {
|
|
270
|
+
J_U_S[j][i] += J_U_Xc[j][k] * J_Xc_S[k][i];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return J_U_S;
|
|
275
|
+
};
|
|
276
|
+
const _getNormalizedModelViewTransform = (modelViewTransform, worldParam, screenParam) => {
|
|
277
|
+
/*
|
|
278
|
+
* notations:
|
|
279
|
+
* m: modelViewTransform,
|
|
280
|
+
* [x,y,z,1]: world coordinates
|
|
281
|
+
* [x',y',z',1]: screen coordinates
|
|
282
|
+
*
|
|
283
|
+
* By normalizing coordinates with meanX, meanY and scale s, it means to transform the coordinates to
|
|
284
|
+
* note that z doesn't scale up, otherwise screen point doesn't scale, e.g. x' = x / z
|
|
285
|
+
* [s*(x-meanX)]
|
|
286
|
+
* [s*(y-meanY)]
|
|
287
|
+
* [z ]
|
|
288
|
+
* [1 ]
|
|
289
|
+
*
|
|
290
|
+
* Let's define transformation T, such that
|
|
291
|
+
* `normalizedP = T * P`
|
|
292
|
+
*
|
|
293
|
+
* [s * (x - meanX)] [s, 0, 0, -s*meanX] [x]
|
|
294
|
+
* [s * (y - meanY)] = [0, s, 0, -s*meanY] * [y]
|
|
295
|
+
* [z ] [0, 0, 1, 0] [z]
|
|
296
|
+
* [1 ] [0, 0, 0, 1] [1]
|
|
297
|
+
*
|
|
298
|
+
* and `P = inv(T) * normalizedP`
|
|
299
|
+
*
|
|
300
|
+
* [x] [1/s, 0 , 0, meanX] [s * (x - meanX)]
|
|
301
|
+
* [y] = [0 , 1/s, 0, meanY] * [s * (y - meanY)]
|
|
302
|
+
* [z] [0 , 0 , 1, 0] [z ]
|
|
303
|
+
* [1] [0 , 0 , 0, 1] [1 ]
|
|
304
|
+
*
|
|
305
|
+
*
|
|
306
|
+
* Before normalizating coordinates, the following holds:
|
|
307
|
+
* M * P = P' (P is world coordinate, and P' is screen coordinate)
|
|
308
|
+
*
|
|
309
|
+
* -> M * inv(T) * T * P = inv(T') * T' * P'
|
|
310
|
+
* -> T' * M * inv(T) * T * P = T' * P'
|
|
311
|
+
* here, T * P, and T' * P' are normalized coordaintes for world and screen, so, the modelViewTransform for normalized coordinates would be:
|
|
312
|
+
*
|
|
313
|
+
* Mnorm = T' * M * inv(T) =
|
|
314
|
+
*
|
|
315
|
+
* [s', 0, 0, -s'*meanX'] [m00, m01, m02, m03] [1/s, 0, 0, meanX]
|
|
316
|
+
* [ 0, s', 0, -s'*meanY'] * [m10, m11, m12, m13] * [ 0, 1/s, 0, meanY]
|
|
317
|
+
* [ 0, 0, 1, 0] [m20, m21, m22, m23] [ 0, 0, 1, 0]
|
|
318
|
+
* [ 0, 0, 0, 1] [0, 0, 0, 1] [ 0, 0, 0, 1]
|
|
319
|
+
*
|
|
320
|
+
* =
|
|
321
|
+
*
|
|
322
|
+
* [m00 * s'/s, m01 * s'/s, m02 * s', m00*s'*meanX + m01*s'*meanY + m03*s' - meanX'*s']
|
|
323
|
+
* [m10 * s'/s, m11 * s'/s, m12 * s', m10*s'*meanX + m11*s'*meanY + m13*s' - meanY'*s']
|
|
324
|
+
* [m20 / s , m21 / s , m22 , m20 *meanX + m21 *meanY + m23 ]
|
|
325
|
+
* [ 0, 0, 0, 1]
|
|
326
|
+
*
|
|
327
|
+
*/
|
|
328
|
+
const m = modelViewTransform;
|
|
329
|
+
const ss = screenParam.s / worldParam.s;
|
|
330
|
+
const normModelViewTransform = [
|
|
331
|
+
[
|
|
332
|
+
m[0][0] * ss,
|
|
333
|
+
m[0][1] * ss,
|
|
334
|
+
m[0][2] * screenParam.s,
|
|
335
|
+
(m[0][0] * worldParam.meanX + m[0][1] * worldParam.meanY + m[0][3] - screenParam.meanX) *
|
|
336
|
+
screenParam.s,
|
|
337
|
+
],
|
|
338
|
+
[
|
|
339
|
+
m[1][0] * ss,
|
|
340
|
+
m[1][1] * ss,
|
|
341
|
+
m[1][2] * screenParam.s,
|
|
342
|
+
(m[1][0] * worldParam.meanX + m[1][1] * worldParam.meanY + m[1][3] - screenParam.meanY) *
|
|
343
|
+
screenParam.s,
|
|
344
|
+
],
|
|
345
|
+
[
|
|
346
|
+
m[2][0] / worldParam.s,
|
|
347
|
+
m[2][1] / worldParam.s,
|
|
348
|
+
m[2][2],
|
|
349
|
+
m[2][0] * worldParam.meanX + m[2][1] * worldParam.meanY + m[2][3],
|
|
350
|
+
],
|
|
351
|
+
];
|
|
352
|
+
return normModelViewTransform;
|
|
353
|
+
};
|
|
354
|
+
const _getDenormalizedModelViewTransform = (modelViewTransform, worldParam, screenParam) => {
|
|
355
|
+
/*
|
|
356
|
+
* Refer to _getNormalizedModelViewTransform, we have
|
|
357
|
+
*
|
|
358
|
+
* Mnorm = T' * M * inv(T)
|
|
359
|
+
*
|
|
360
|
+
* Therefore,
|
|
361
|
+
*
|
|
362
|
+
* M = inv(T') * Mnorm * T
|
|
363
|
+
*
|
|
364
|
+
* [1/s', 0, 0, meanX'] [m00, m01, m02, m03] [s, 0, 0, -s*meanX]
|
|
365
|
+
* [0 , 1/s', 0, meanY'] * [m10, m11, m12, m13] * [0, s, 0, -s*meanY]
|
|
366
|
+
* [0 , 0 , 1, 0] [m20, m21, m22, m23] [0, 0, 1, 0]
|
|
367
|
+
* [0 , 0 , 0, 1] [0, 0, 0, 1] [0, 0, 0, 1]
|
|
368
|
+
*
|
|
369
|
+
* =
|
|
370
|
+
*
|
|
371
|
+
* [m00*s/s', m01*s/s', m02/s', (-m00*s*meanX -m01*s*meanY+m03)/s' + meanX'],
|
|
372
|
+
* [m10*s/s', m11*s/s', m12/s', (-m10*s*meanX -m11*s*meanY+m13)/s' + meanY'],
|
|
373
|
+
* [m20*s ', m21*s ', m22 , -m20*s*meanX -m21*s*meanY+m23) ],
|
|
374
|
+
* [0 , 0, 0, 1]
|
|
375
|
+
*
|
|
376
|
+
*/
|
|
377
|
+
const m = modelViewTransform;
|
|
378
|
+
const ss = worldParam.s / screenParam.s;
|
|
379
|
+
const sMeanX = worldParam.s * worldParam.meanX;
|
|
380
|
+
const sMeanY = worldParam.s * worldParam.meanY;
|
|
381
|
+
const denormModelViewTransform = [
|
|
382
|
+
[
|
|
383
|
+
m[0][0] * ss,
|
|
384
|
+
m[0][1] * ss,
|
|
385
|
+
m[0][2] / screenParam.s,
|
|
386
|
+
(-m[0][0] * sMeanX - m[0][1] * sMeanY + m[0][3]) / screenParam.s + screenParam.meanX,
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
m[1][0] * ss,
|
|
390
|
+
m[1][1] * ss,
|
|
391
|
+
m[1][2] / screenParam.s,
|
|
392
|
+
(-m[1][0] * sMeanX - m[1][1] * sMeanY + m[1][3]) / screenParam.s + screenParam.meanY,
|
|
393
|
+
],
|
|
394
|
+
[
|
|
395
|
+
m[2][0] * worldParam.s,
|
|
396
|
+
m[2][1] * worldParam.s,
|
|
397
|
+
m[2][2],
|
|
398
|
+
-m[2][0] * sMeanX - m[2][1] * sMeanY + m[2][3],
|
|
399
|
+
],
|
|
400
|
+
];
|
|
401
|
+
return denormModelViewTransform;
|
|
402
|
+
};
|
|
403
|
+
// centroid at origin and avg distance from origin is sqrt(2)
|
|
404
|
+
const normalizePoints = (coords) => {
|
|
405
|
+
let sumX = 0;
|
|
406
|
+
let sumY = 0;
|
|
407
|
+
for (let i = 0; i < coords.length; i++) {
|
|
408
|
+
sumX += coords[i].x;
|
|
409
|
+
sumY += coords[i].y;
|
|
410
|
+
}
|
|
411
|
+
let meanX = sumX / coords.length;
|
|
412
|
+
let meanY = sumY / coords.length;
|
|
413
|
+
let sumDiff = 0;
|
|
414
|
+
for (let i = 0; i < coords.length; i++) {
|
|
415
|
+
const diffX = coords[i].x - meanX;
|
|
416
|
+
const diffY = coords[i].y - meanY;
|
|
417
|
+
sumDiff += Math.sqrt(diffX * diffX + diffY * diffY);
|
|
418
|
+
}
|
|
419
|
+
let s = (Math.sqrt(2) * coords.length) / sumDiff;
|
|
420
|
+
const normalizedCoords = [];
|
|
421
|
+
for (let i = 0; i < coords.length; i++) {
|
|
422
|
+
normalizedCoords.push({
|
|
423
|
+
x: (coords[i].x - meanX) * s,
|
|
424
|
+
y: (coords[i].y - meanY) * s,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
return { normalizedCoords, param: { meanX, meanY, s } };
|
|
428
|
+
};
|
|
429
|
+
export { refineEstimate };
|