@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.
Files changed (207) hide show
  1. package/README.md +62 -0
  2. package/dist/compiler/aframe.d.ts +1 -0
  3. package/dist/compiler/aframe.js +275 -0
  4. package/dist/compiler/compiler-base.d.ts +12 -0
  5. package/dist/compiler/compiler-base.js +165 -0
  6. package/dist/compiler/compiler.d.ts +9 -0
  7. package/dist/compiler/compiler.js +24 -0
  8. package/dist/compiler/compiler.worker.d.ts +1 -0
  9. package/dist/compiler/compiler.worker.js +28 -0
  10. package/dist/compiler/controller.d.ts +101 -0
  11. package/dist/compiler/controller.js +400 -0
  12. package/dist/compiler/controller.worker.d.ts +1 -0
  13. package/dist/compiler/controller.worker.js +61 -0
  14. package/dist/compiler/detector/crop-detector.d.ts +65 -0
  15. package/dist/compiler/detector/crop-detector.js +59 -0
  16. package/dist/compiler/detector/detector.d.ts +98 -0
  17. package/dist/compiler/detector/detector.js +1049 -0
  18. package/dist/compiler/detector/freak.d.ts +1 -0
  19. package/dist/compiler/detector/freak.js +89 -0
  20. package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
  21. package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
  22. package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
  23. package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
  24. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
  25. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
  26. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
  27. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
  28. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
  29. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
  30. package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
  31. package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
  32. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
  33. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
  34. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
  35. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
  36. package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
  37. package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
  38. package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
  39. package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
  40. package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
  41. package/dist/compiler/detector/kernels/cpu/index.js +25 -0
  42. package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
  43. package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
  44. package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
  45. package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
  46. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
  47. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
  48. package/dist/compiler/detector/kernels/index.d.ts +1 -0
  49. package/dist/compiler/detector/kernels/index.js +2 -0
  50. package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
  51. package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
  52. package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
  53. package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
  54. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
  55. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
  56. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
  57. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
  58. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
  59. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
  60. package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
  61. package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
  62. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
  63. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
  64. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
  65. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
  66. package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
  67. package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
  68. package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
  69. package/dist/compiler/detector/kernels/webgl/index.js +25 -0
  70. package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
  71. package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
  72. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
  73. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
  74. package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
  75. package/dist/compiler/estimation/esimate-experiment.js +267 -0
  76. package/dist/compiler/estimation/estimate.d.ts +5 -0
  77. package/dist/compiler/estimation/estimate.js +51 -0
  78. package/dist/compiler/estimation/estimator.d.ts +13 -0
  79. package/dist/compiler/estimation/estimator.js +30 -0
  80. package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
  81. package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
  82. package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
  83. package/dist/compiler/estimation/refine-estimate.js +299 -0
  84. package/dist/compiler/estimation/utils.d.ts +10 -0
  85. package/dist/compiler/estimation/utils.js +80 -0
  86. package/dist/compiler/image-list.d.ts +13 -0
  87. package/dist/compiler/image-list.js +52 -0
  88. package/dist/compiler/index.d.ts +3 -0
  89. package/dist/compiler/index.js +10 -0
  90. package/dist/compiler/input-loader.d.ts +23 -0
  91. package/dist/compiler/input-loader.js +88 -0
  92. package/dist/compiler/matching/hamming-distance.d.ts +1 -0
  93. package/dist/compiler/matching/hamming-distance.js +20 -0
  94. package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
  95. package/dist/compiler/matching/hierarchical-clustering.js +109 -0
  96. package/dist/compiler/matching/hough.d.ts +1 -0
  97. package/dist/compiler/matching/hough.js +169 -0
  98. package/dist/compiler/matching/matcher.d.ts +28 -0
  99. package/dist/compiler/matching/matcher.js +48 -0
  100. package/dist/compiler/matching/matching.d.ts +41 -0
  101. package/dist/compiler/matching/matching.js +197 -0
  102. package/dist/compiler/matching/ransacHomography.d.ts +1 -0
  103. package/dist/compiler/matching/ransacHomography.js +136 -0
  104. package/dist/compiler/offline-compiler.d.ts +10 -0
  105. package/dist/compiler/offline-compiler.js +450 -0
  106. package/dist/compiler/tensorflow-setup.d.ts +7 -0
  107. package/dist/compiler/tensorflow-setup.js +73 -0
  108. package/dist/compiler/three.d.ts +66 -0
  109. package/dist/compiler/three.js +310 -0
  110. package/dist/compiler/tracker/extract-utils.d.ts +1 -0
  111. package/dist/compiler/tracker/extract-utils.js +29 -0
  112. package/dist/compiler/tracker/extract.d.ts +4 -0
  113. package/dist/compiler/tracker/extract.js +349 -0
  114. package/dist/compiler/tracker/tracker.d.ts +38 -0
  115. package/dist/compiler/tracker/tracker.js +327 -0
  116. package/dist/compiler/utils/cumsum.d.ts +5 -0
  117. package/dist/compiler/utils/cumsum.js +39 -0
  118. package/dist/compiler/utils/geometry.d.ts +8 -0
  119. package/dist/compiler/utils/geometry.js +101 -0
  120. package/dist/compiler/utils/homography.d.ts +1 -0
  121. package/dist/compiler/utils/homography.js +138 -0
  122. package/dist/compiler/utils/images.d.ts +24 -0
  123. package/dist/compiler/utils/images.js +99 -0
  124. package/dist/compiler/utils/randomizer.d.ts +5 -0
  125. package/dist/compiler/utils/randomizer.js +25 -0
  126. package/dist/index.d.ts +6 -0
  127. package/dist/index.js +7 -0
  128. package/dist/react/AREditor.d.ts +5 -0
  129. package/dist/react/AREditor.js +159 -0
  130. package/dist/react/ProgressDialog.d.ts +13 -0
  131. package/dist/react/ProgressDialog.js +57 -0
  132. package/dist/react/types.d.ts +22 -0
  133. package/dist/react/types.js +14 -0
  134. package/package.json +53 -0
  135. package/src/astro/ARScene.astro +59 -0
  136. package/src/astro/ARVideoTrigger.astro +73 -0
  137. package/src/astro/overlays/ErrorOverlay.astro +40 -0
  138. package/src/astro/overlays/LoadingOverlay.astro +28 -0
  139. package/src/astro/overlays/ScanningOverlay.astro +119 -0
  140. package/src/astro/scripts/ARScripts.astro +118 -0
  141. package/src/astro/styles/ARStyles.astro +147 -0
  142. package/src/compiler/aframe.js +343 -0
  143. package/src/compiler/compiler-base.js +195 -0
  144. package/src/compiler/compiler.js +25 -0
  145. package/src/compiler/compiler.worker.js +30 -0
  146. package/src/compiler/controller.js +473 -0
  147. package/src/compiler/controller.worker.js +77 -0
  148. package/src/compiler/detector/crop-detector.js +68 -0
  149. package/src/compiler/detector/detector.js +1130 -0
  150. package/src/compiler/detector/freak.js +91 -0
  151. package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
  152. package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
  153. package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
  154. package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
  155. package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
  156. package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
  157. package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
  158. package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
  159. package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
  160. package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
  161. package/src/compiler/detector/kernels/cpu/index.js +26 -0
  162. package/src/compiler/detector/kernels/cpu/prune.js +114 -0
  163. package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
  164. package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
  165. package/src/compiler/detector/kernels/index.js +2 -0
  166. package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
  167. package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
  168. package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
  169. package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
  170. package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
  171. package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
  172. package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
  173. package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
  174. package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
  175. package/src/compiler/detector/kernels/webgl/index.js +26 -0
  176. package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
  177. package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
  178. package/src/compiler/estimation/esimate-experiment.js +316 -0
  179. package/src/compiler/estimation/estimate.js +67 -0
  180. package/src/compiler/estimation/estimator.js +34 -0
  181. package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
  182. package/src/compiler/estimation/refine-estimate.js +365 -0
  183. package/src/compiler/estimation/utils.js +97 -0
  184. package/src/compiler/image-list.js +62 -0
  185. package/src/compiler/index.js +13 -0
  186. package/src/compiler/input-loader.js +107 -0
  187. package/src/compiler/matching/hamming-distance.js +23 -0
  188. package/src/compiler/matching/hierarchical-clustering.js +131 -0
  189. package/src/compiler/matching/hough.js +206 -0
  190. package/src/compiler/matching/matcher.js +59 -0
  191. package/src/compiler/matching/matching.js +237 -0
  192. package/src/compiler/matching/ransacHomography.js +192 -0
  193. package/src/compiler/offline-compiler.js +553 -0
  194. package/src/compiler/tensorflow-setup.js +88 -0
  195. package/src/compiler/three.js +368 -0
  196. package/src/compiler/tracker/extract-utils.js +34 -0
  197. package/src/compiler/tracker/extract.js +419 -0
  198. package/src/compiler/tracker/tracker.js +397 -0
  199. package/src/compiler/utils/cumsum.js +40 -0
  200. package/src/compiler/utils/geometry.js +114 -0
  201. package/src/compiler/utils/homography.js +150 -0
  202. package/src/compiler/utils/images.js +111 -0
  203. package/src/compiler/utils/randomizer.js +29 -0
  204. package/src/index.ts +8 -0
  205. package/src/react/AREditor.tsx +394 -0
  206. package/src/react/ProgressDialog.tsx +185 -0
  207. package/src/react/types.ts +35 -0
@@ -0,0 +1,365 @@
1
+ import { Matrix, inverse } from "ml-matrix";
2
+ import {
3
+ applyModelViewProjectionTransform,
4
+ buildModelViewProjectionTransform,
5
+ computeScreenCoordiate,
6
+ } from "./utils.js";
7
+
8
+ const TRACKING_THRESH = 5.0; // default
9
+ const K2_FACTOR = 4.0; // Question: should it be relative to the size of the screen instead of hardcoded?
10
+ const ICP_MAX_LOOP = 10;
11
+ const ICP_BREAK_LOOP_ERROR_THRESH = 0.1;
12
+ const ICP_BREAK_LOOP_ERROR_RATIO_THRESH = 0.99;
13
+ const ICP_BREAK_LOOP_ERROR_THRESH2 = 4.0;
14
+
15
+ // some temporary/intermediate variables used later. Declare them beforehand to reduce new object allocations
16
+ let mat = [[], [], []];
17
+ let J_U_Xc = [[], []]; // 2x3
18
+ let J_Xc_S = [[], [], []]; // 3x6
19
+
20
+ const refineEstimate = ({
21
+ initialModelViewTransform,
22
+ projectionTransform,
23
+ worldCoords,
24
+ screenCoords,
25
+ }) => {
26
+ // Question: shall we normlize the screen coords as well?
27
+ // Question: do we need to normlize the scale as well, i.e. make coords from -1 to 1
28
+ //
29
+ // normalize world coords - reposition them to center of mass
30
+ // assume z coordinate is always zero (in our case, the image target is planar with z = 0
31
+ let dx = 0;
32
+ let dy = 0;
33
+ for (let i = 0; i < worldCoords.length; i++) {
34
+ dx += worldCoords[i].x;
35
+ dy += worldCoords[i].y;
36
+ }
37
+ dx /= worldCoords.length;
38
+ dy /= worldCoords.length;
39
+
40
+ const normalizedWorldCoords = [];
41
+ for (let i = 0; i < worldCoords.length; i++) {
42
+ normalizedWorldCoords.push({
43
+ x: worldCoords[i].x - dx,
44
+ y: worldCoords[i].y - dy,
45
+ z: worldCoords[i].z,
46
+ });
47
+ }
48
+
49
+ const diffModelViewTransform = [[], [], []];
50
+ for (let j = 0; j < 3; j++) {
51
+ for (let i = 0; i < 3; i++) {
52
+ diffModelViewTransform[j][i] = initialModelViewTransform[j][i];
53
+ }
54
+ }
55
+ diffModelViewTransform[0][3] =
56
+ initialModelViewTransform[0][0] * dx +
57
+ initialModelViewTransform[0][1] * dy +
58
+ initialModelViewTransform[0][3];
59
+ diffModelViewTransform[1][3] =
60
+ initialModelViewTransform[1][0] * dx +
61
+ initialModelViewTransform[1][1] * dy +
62
+ initialModelViewTransform[1][3];
63
+ diffModelViewTransform[2][3] =
64
+ initialModelViewTransform[2][0] * dx +
65
+ initialModelViewTransform[2][1] * dy +
66
+ initialModelViewTransform[2][3];
67
+
68
+ // use iterative closest point algorithm to refine the modelViewTransform
69
+ const inlierProbs = [1.0, 0.8, 0.6, 0.4, 0.0];
70
+ let updatedModelViewTransform = diffModelViewTransform; // iteratively update this transform
71
+ let finalModelViewTransform = null;
72
+ for (let i = 0; i < inlierProbs.length; i++) {
73
+ const ret = _doICP({
74
+ initialModelViewTransform: updatedModelViewTransform,
75
+ projectionTransform,
76
+ worldCoords: normalizedWorldCoords,
77
+ screenCoords,
78
+ inlierProb: inlierProbs[i],
79
+ });
80
+
81
+ updatedModelViewTransform = ret.modelViewTransform;
82
+
83
+ //console.log("err", ret.err);
84
+
85
+ if (ret.err < TRACKING_THRESH) {
86
+ finalModelViewTransform = updatedModelViewTransform;
87
+ break;
88
+ }
89
+ }
90
+
91
+ if (finalModelViewTransform === null) return null;
92
+
93
+ // de-normalize
94
+ finalModelViewTransform[0][3] =
95
+ finalModelViewTransform[0][3] -
96
+ finalModelViewTransform[0][0] * dx -
97
+ finalModelViewTransform[0][1] * dy;
98
+ finalModelViewTransform[1][3] =
99
+ finalModelViewTransform[1][3] -
100
+ finalModelViewTransform[1][0] * dx -
101
+ finalModelViewTransform[1][1] * dy;
102
+ finalModelViewTransform[2][3] =
103
+ finalModelViewTransform[2][3] -
104
+ finalModelViewTransform[2][0] * dx -
105
+ finalModelViewTransform[2][1] * dy;
106
+
107
+ return finalModelViewTransform;
108
+ };
109
+
110
+ // ICP iteration
111
+ // Question: can someone provide theoretical reference / mathematical proof for the following computations?
112
+ const _doICP = ({
113
+ initialModelViewTransform,
114
+ projectionTransform,
115
+ worldCoords,
116
+ screenCoords,
117
+ inlierProb,
118
+ }) => {
119
+ const isRobustMode = inlierProb < 1;
120
+
121
+ let modelViewTransform = initialModelViewTransform;
122
+
123
+ let err0 = 0.0;
124
+ let err1 = 0.0;
125
+
126
+ let E = new Array(worldCoords.length);
127
+ let E2 = new Array(worldCoords.length);
128
+ let dxs = new Array(worldCoords.length);
129
+ let dys = new Array(worldCoords.length);
130
+
131
+ for (let l = 0; l <= ICP_MAX_LOOP; l++) {
132
+ const modelViewProjectionTransform = buildModelViewProjectionTransform(
133
+ projectionTransform,
134
+ modelViewTransform,
135
+ );
136
+
137
+ for (let n = 0; n < worldCoords.length; n++) {
138
+ const u = computeScreenCoordiate(
139
+ modelViewProjectionTransform,
140
+ worldCoords[n].x,
141
+ worldCoords[n].y,
142
+ worldCoords[n].z,
143
+ );
144
+ const dx = screenCoords[n].x - u.x;
145
+ const dy = screenCoords[n].y - u.y;
146
+
147
+ dxs[n] = dx;
148
+ dys[n] = dy;
149
+ E[n] = dx * dx + dy * dy;
150
+ }
151
+
152
+ let K2; // robust mode only
153
+ err1 = 0.0;
154
+ if (isRobustMode) {
155
+ const inlierNum = Math.max(3, Math.floor(worldCoords.length * inlierProb) - 1);
156
+ for (let n = 0; n < worldCoords.length; n++) {
157
+ E2[n] = E[n];
158
+ }
159
+ E2.sort((a, b) => {
160
+ return a - b;
161
+ });
162
+
163
+ K2 = Math.max(E2[inlierNum] * K2_FACTOR, 16.0);
164
+ for (let n = 0; n < worldCoords.length; n++) {
165
+ if (E2[n] > K2) err1 += K2 / 6;
166
+ else
167
+ err1 += (K2 / 6.0) * (1.0 - (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2));
168
+ }
169
+ } else {
170
+ for (let n = 0; n < worldCoords.length; n++) {
171
+ err1 += E[n];
172
+ }
173
+ }
174
+ err1 /= worldCoords.length;
175
+
176
+ //console.log("icp loop", inlierProb, l, err1);
177
+
178
+ if (err1 < ICP_BREAK_LOOP_ERROR_THRESH) break;
179
+ //if (l > 0 && err1 < ICP_BREAK_LOOP_ERROR_THRESH2 && err1/err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH) break;
180
+ if (l > 0 && err1 / err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH) break;
181
+ if (l === ICP_MAX_LOOP) break;
182
+
183
+ err0 = err1;
184
+
185
+ const dU = [];
186
+ const allJ_U_S = [];
187
+ for (let n = 0; n < worldCoords.length; n++) {
188
+ if (isRobustMode && E[n] > K2) {
189
+ continue;
190
+ }
191
+
192
+ const J_U_S = _getJ_U_S({
193
+ modelViewProjectionTransform,
194
+ modelViewTransform,
195
+ projectionTransform,
196
+ worldCoord: worldCoords[n],
197
+ });
198
+
199
+ if (isRobustMode) {
200
+ const W = (1.0 - E[n] / K2) * (1.0 - E[n] / K2);
201
+
202
+ for (let j = 0; j < 2; j++) {
203
+ for (let i = 0; i < 6; i++) {
204
+ J_U_S[j][i] *= W;
205
+ }
206
+ }
207
+ dU.push([dxs[n] * W]);
208
+ dU.push([dys[n] * W]);
209
+ } else {
210
+ dU.push([dxs[n]]);
211
+ dU.push([dys[n]]);
212
+ }
213
+
214
+ for (let i = 0; i < J_U_S.length; i++) {
215
+ allJ_U_S.push(J_U_S[i]);
216
+ }
217
+ }
218
+
219
+ const dS = _getDeltaS({ dU, J_U_S: allJ_U_S });
220
+ if (dS === null) break;
221
+
222
+ modelViewTransform = _updateModelViewTransform({ modelViewTransform, dS });
223
+ }
224
+ return { modelViewTransform, err: err1 };
225
+ };
226
+
227
+ const _updateModelViewTransform = ({ modelViewTransform, dS }) => {
228
+ /**
229
+ * dS has 6 paragrams, first half is rotation, second half is translation
230
+ * rotation is expressed in angle-axis,
231
+ * [S[0], S[1] ,S[2]] is the axis of rotation, and the magnitude is the angle
232
+ */
233
+ let ra = dS[0] * dS[0] + dS[1] * dS[1] + dS[2] * dS[2];
234
+ let q0, q1, q2;
235
+ if (ra < 0.000001) {
236
+ q0 = 1.0;
237
+ q1 = 0.0;
238
+ q2 = 0.0;
239
+ ra = 0.0;
240
+ } else {
241
+ ra = Math.sqrt(ra);
242
+ q0 = dS[0] / ra;
243
+ q1 = dS[1] / ra;
244
+ q2 = dS[2] / ra;
245
+ }
246
+
247
+ const cra = Math.cos(ra);
248
+ const sra = Math.sin(ra);
249
+ const one_cra = 1.0 - cra;
250
+
251
+ // mat is [R|t], 3D rotation and translation
252
+ mat[0][0] = q0 * q0 * one_cra + cra;
253
+ mat[0][1] = q0 * q1 * one_cra - q2 * sra;
254
+ mat[0][2] = q0 * q2 * one_cra + q1 * sra;
255
+ mat[0][3] = dS[3];
256
+ mat[1][0] = q1 * q0 * one_cra + q2 * sra;
257
+ mat[1][1] = q1 * q1 * one_cra + cra;
258
+ mat[1][2] = q1 * q2 * one_cra - q0 * sra;
259
+ mat[1][3] = dS[4];
260
+ mat[2][0] = q2 * q0 * one_cra - q1 * sra;
261
+ mat[2][1] = q2 * q1 * one_cra + q0 * sra;
262
+ mat[2][2] = q2 * q2 * one_cra + cra;
263
+ mat[2][3] = dS[5];
264
+
265
+ // the updated transform is the original transform x delta transform
266
+ const mat2 = [[], [], []];
267
+ for (let j = 0; j < 3; j++) {
268
+ for (let i = 0; i < 4; i++) {
269
+ mat2[j][i] =
270
+ modelViewTransform[j][0] * mat[0][i] +
271
+ modelViewTransform[j][1] * mat[1][i] +
272
+ modelViewTransform[j][2] * mat[2][i];
273
+ }
274
+ mat2[j][3] += modelViewTransform[j][3];
275
+ }
276
+ return mat2;
277
+ };
278
+
279
+ const _getDeltaS = ({ dU, J_U_S }) => {
280
+ const J = new Matrix(J_U_S);
281
+ const U = new Matrix(dU);
282
+
283
+ const JT = J.transpose();
284
+ const JTJ = JT.mmul(J);
285
+ const JTU = JT.mmul(U);
286
+
287
+ let JTJInv;
288
+ try {
289
+ JTJInv = inverse(JTJ);
290
+ } catch (e) {
291
+ return null;
292
+ }
293
+
294
+ const S = JTJInv.mmul(JTU);
295
+ return S.to1DArray();
296
+ };
297
+
298
+ const _getJ_U_S = ({
299
+ modelViewProjectionTransform,
300
+ modelViewTransform,
301
+ projectionTransform,
302
+ worldCoord,
303
+ }) => {
304
+ const T = modelViewTransform;
305
+ const { x, y, z } = worldCoord;
306
+
307
+ const u = applyModelViewProjectionTransform(modelViewProjectionTransform, x, y, z);
308
+
309
+ const z2 = u.z * u.z;
310
+ // Question: This is the most confusing matrix to me. I've no idea how to derive this.
311
+ //J_U_Xc[0][0] = (projectionTransform[0][0] * u.z - projectionTransform[2][0] * u.x) / z2;
312
+ //J_U_Xc[0][1] = (projectionTransform[0][1] * u.z - projectionTransform[2][1] * u.x) / z2;
313
+ //J_U_Xc[0][2] = (projectionTransform[0][2] * u.z - projectionTransform[2][2] * u.x) / z2;
314
+ //J_U_Xc[1][0] = (projectionTransform[1][0] * u.z - projectionTransform[2][0] * u.y) / z2;
315
+ //J_U_Xc[1][1] = (projectionTransform[1][1] * u.z - projectionTransform[2][1] * u.y) / z2;
316
+ //J_U_Xc[1][2] = (projectionTransform[1][2] * u.z - projectionTransform[2][2] * u.y) / z2;
317
+
318
+ // The above is the original implementation, but simplify to below becuase projetionTransform[2][0] and [2][1] are zero
319
+ J_U_Xc[0][0] = (projectionTransform[0][0] * u.z) / z2;
320
+ J_U_Xc[0][1] = (projectionTransform[0][1] * u.z) / z2;
321
+ J_U_Xc[0][2] = (projectionTransform[0][2] * u.z - projectionTransform[2][2] * u.x) / z2;
322
+ J_U_Xc[1][0] = (projectionTransform[1][0] * u.z) / z2;
323
+ J_U_Xc[1][1] = (projectionTransform[1][1] * u.z) / z2;
324
+ J_U_Xc[1][2] = (projectionTransform[1][2] * u.z - projectionTransform[2][2] * u.y) / z2;
325
+
326
+ /*
327
+ J_Xc_S should be like this, but z is zero, so we can simplify
328
+ [T[0][2] * y - T[0][1] * z, T[0][0] * z - T[0][2] * x, T[0][1] * x - T[0][0] * y, T[0][0], T[0][1], T[0][2]],
329
+ [T[1][2] * y - T[1][1] * z, T[1][0] * z - T[1][2] * x, T[1][1] * x - T[1][0] * y, T[1][0], T[1][1], T[1][2]],
330
+ [T[2][2] * y - T[2][1] * z, T[2][0] * z - T[2][2] * x, T[2][1] * x - T[2][0] * y, T[2][0], T[2][1], T[2][2]],
331
+ */
332
+ J_Xc_S[0][0] = T[0][2] * y;
333
+ J_Xc_S[0][1] = -T[0][2] * x;
334
+ J_Xc_S[0][2] = T[0][1] * x - T[0][0] * y;
335
+ J_Xc_S[0][3] = T[0][0];
336
+ J_Xc_S[0][4] = T[0][1];
337
+ J_Xc_S[0][5] = T[0][2];
338
+
339
+ J_Xc_S[1][0] = T[1][2] * y;
340
+ J_Xc_S[1][1] = -T[1][2] * x;
341
+ J_Xc_S[1][2] = T[1][1] * x - T[1][0] * y;
342
+ J_Xc_S[1][3] = T[1][0];
343
+ J_Xc_S[1][4] = T[1][1];
344
+ J_Xc_S[1][5] = T[1][2];
345
+
346
+ J_Xc_S[2][0] = T[2][2] * y;
347
+ J_Xc_S[2][1] = -T[2][2] * x;
348
+ J_Xc_S[2][2] = T[2][1] * x - T[2][0] * y;
349
+ J_Xc_S[2][3] = T[2][0];
350
+ J_Xc_S[2][4] = T[2][1];
351
+ J_Xc_S[2][5] = T[2][2];
352
+
353
+ const J_U_S = [[], []];
354
+ for (let j = 0; j < 2; j++) {
355
+ for (let i = 0; i < 6; i++) {
356
+ J_U_S[j][i] = 0.0;
357
+ for (let k = 0; k < 3; k++) {
358
+ J_U_S[j][i] += J_U_Xc[j][k] * J_Xc_S[k][i];
359
+ }
360
+ }
361
+ }
362
+ return J_U_S;
363
+ };
364
+
365
+ export { refineEstimate };
@@ -0,0 +1,97 @@
1
+ const buildModelViewProjectionTransform = (projectionTransform, modelViewTransform) => {
2
+ // assume the projectTransform has the following format:
3
+ // [[fx, 0, cx],
4
+ // [0, fy, cy]
5
+ // [0, 0, 1]]
6
+ const modelViewProjectionTransform = [
7
+ [
8
+ projectionTransform[0][0] * modelViewTransform[0][0] +
9
+ projectionTransform[0][2] * modelViewTransform[2][0],
10
+ projectionTransform[0][0] * modelViewTransform[0][1] +
11
+ projectionTransform[0][2] * modelViewTransform[2][1],
12
+ projectionTransform[0][0] * modelViewTransform[0][2] +
13
+ projectionTransform[0][2] * modelViewTransform[2][2],
14
+ projectionTransform[0][0] * modelViewTransform[0][3] +
15
+ projectionTransform[0][2] * modelViewTransform[2][3],
16
+ ],
17
+ [
18
+ projectionTransform[1][1] * modelViewTransform[1][0] +
19
+ projectionTransform[1][2] * modelViewTransform[2][0],
20
+ projectionTransform[1][1] * modelViewTransform[1][1] +
21
+ projectionTransform[1][2] * modelViewTransform[2][1],
22
+ projectionTransform[1][1] * modelViewTransform[1][2] +
23
+ projectionTransform[1][2] * modelViewTransform[2][2],
24
+ projectionTransform[1][1] * modelViewTransform[1][3] +
25
+ projectionTransform[1][2] * modelViewTransform[2][3],
26
+ ],
27
+ [
28
+ modelViewTransform[2][0],
29
+ modelViewTransform[2][1],
30
+ modelViewTransform[2][2],
31
+ modelViewTransform[2][3],
32
+ ],
33
+ ];
34
+ return modelViewProjectionTransform;
35
+
36
+ /*
37
+ // this is the full computation if the projectTransform does not look like the expected format, but more computations
38
+ //
39
+ const modelViewProjectionTransform = [[],[],[]];
40
+ for (let j = 0; j < 3; j++ ) {
41
+ for (let i = 0; i < 4; i++) {
42
+ modelViewProjectionTransform[j][i] = projectionTransform[j][0] * modelViewTransform[0][i]
43
+ + projectionTransform[j][1] * modelViewTransform[1][i]
44
+ + projectionTransform[j][2] * modelViewTransform[2][i];
45
+ }
46
+ }
47
+ return modelViewProjectionTransform;
48
+ */
49
+ };
50
+
51
+ const applyModelViewProjectionTransform = (modelViewProjectionTransform, x, y, z) => {
52
+ // assume z is zero
53
+ const ux =
54
+ modelViewProjectionTransform[0][0] * x +
55
+ modelViewProjectionTransform[0][1] * y +
56
+ modelViewProjectionTransform[0][3];
57
+ const uy =
58
+ modelViewProjectionTransform[1][0] * x +
59
+ modelViewProjectionTransform[1][1] * y +
60
+ modelViewProjectionTransform[1][3];
61
+ const uz =
62
+ modelViewProjectionTransform[2][0] * x +
63
+ modelViewProjectionTransform[2][1] * y +
64
+ modelViewProjectionTransform[2][3];
65
+ return { x: ux, y: uy, z: uz };
66
+ };
67
+
68
+ const computeScreenCoordiate = (modelViewProjectionTransform, x, y, z) => {
69
+ const {
70
+ x: ux,
71
+ y: uy,
72
+ z: uz,
73
+ } = applyModelViewProjectionTransform(modelViewProjectionTransform, x, y, z);
74
+ //if( Math.abs(uz) < 0.000001 ) return null;
75
+ return { x: ux / uz, y: uy / uz };
76
+ };
77
+
78
+ const screenToMarkerCoordinate = (modelViewProjectionTransform, sx, sy) => {
79
+ const c11 = modelViewProjectionTransform[2][0] * sx - modelViewProjectionTransform[0][0];
80
+ const c12 = modelViewProjectionTransform[2][1] * sx - modelViewProjectionTransform[0][1];
81
+ const c21 = modelViewProjectionTransform[2][0] * sy - modelViewProjectionTransform[1][0];
82
+ const c22 = modelViewProjectionTransform[2][1] * sy - modelViewProjectionTransform[1][1];
83
+ const b1 = modelViewProjectionTransform[0][3] - modelViewProjectionTransform[2][3] * sx;
84
+ const b2 = modelViewProjectionTransform[1][3] - modelViewProjectionTransform[2][3] * sy;
85
+
86
+ const m = c11 * c22 - c12 * c21;
87
+ return {
88
+ x: (c22 * b1 - c12 * b2) / m,
89
+ y: (c11 * b2 - c21 * b1) / m,
90
+ };
91
+ };
92
+
93
+ export {
94
+ buildModelViewProjectionTransform,
95
+ applyModelViewProjectionTransform,
96
+ computeScreenCoordiate,
97
+ };
@@ -0,0 +1,62 @@
1
+ import { resize } from "./utils/images.js";
2
+
3
+ /**
4
+ * Tamaño mínimo de píxeles para el procesamiento de imágenes
5
+ * Un valor más bajo permite detectar imágenes más pequeñas pero aumenta el tiempo de procesamiento
6
+ * @constant {number}
7
+ */
8
+ const MIN_IMAGE_PIXEL_SIZE = 100;
9
+
10
+ /**
11
+ * Construye una lista de imágenes con diferentes escalas para detección de características
12
+ * @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
13
+ * @returns {Array<Object>} Lista de imágenes escaladas con propiedades data, width, height y scale
14
+ */
15
+ const buildImageList = (inputImage) => {
16
+ const minScale = MIN_IMAGE_PIXEL_SIZE / Math.min(inputImage.width, inputImage.height);
17
+
18
+ const scaleList = [];
19
+ let c = minScale;
20
+ while (true) {
21
+ scaleList.push(c);
22
+ c *= Math.pow(2.0, 1.0 / 3.0);
23
+ if (c >= 0.95) {
24
+ c = 1;
25
+ break;
26
+ }
27
+ }
28
+ scaleList.push(c);
29
+ scaleList.reverse();
30
+
31
+ const imageList = [];
32
+ for (let i = 0; i < scaleList.length; i++) {
33
+ const w = inputImage.width * scaleList[i];
34
+ const h = inputImage.height * scaleList[i];
35
+ imageList.push(
36
+ Object.assign(resize({ image: inputImage, ratio: scaleList[i] }), { scale: scaleList[i] }),
37
+ );
38
+ }
39
+ return imageList;
40
+ };
41
+
42
+ /**
43
+ * Construye una lista optimizada de imágenes para tracking
44
+ * Genera dos versiones escaladas (256px y 128px) para tracking eficiente
45
+ * @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
46
+ * @returns {Array<Object>} Lista de imágenes escaladas para tracking
47
+ */
48
+ const buildTrackingImageList = (inputImage) => {
49
+ const minDimension = Math.min(inputImage.width, inputImage.height);
50
+ const scaleList = [];
51
+ const imageList = [];
52
+ scaleList.push(256.0 / minDimension);
53
+ scaleList.push(128.0 / minDimension);
54
+ for (let i = 0; i < scaleList.length; i++) {
55
+ imageList.push(
56
+ Object.assign(resize({ image: inputImage, ratio: scaleList[i] }), { scale: scaleList[i] }),
57
+ );
58
+ }
59
+ return imageList;
60
+ };
61
+
62
+ export { buildImageList, buildTrackingImageList };
@@ -0,0 +1,13 @@
1
+ import { Controller } from "./controller.js";
2
+ import { Compiler } from "./compiler.js";
3
+
4
+ export { Controller, Compiler };
5
+
6
+ if (!window.MINDAR) {
7
+ window.MINDAR = {};
8
+ }
9
+
10
+ window.MINDAR.IMAGE = {
11
+ Controller,
12
+ Compiler,
13
+ };
@@ -0,0 +1,107 @@
1
+ import * as tf from "@tensorflow/tfjs";
2
+
3
+ // More efficient implementation for tf.browser.fromPixels
4
+ // original implementation: /node_modules/@tensorflow/tfjs-backend-webgl/src/kernels/FromPixels.ts
5
+ //
6
+ // This implementation return grey scale instead of RGBA in the orignal implementation
7
+
8
+ class InputLoader {
9
+ constructor(width, height) {
10
+ this.width = width;
11
+ this.height = height;
12
+ this.texShape = [height, width];
13
+
14
+ const context = document.createElement("canvas").getContext("2d");
15
+ context.canvas.width = width;
16
+ context.canvas.height = height;
17
+ this.context = context;
18
+
19
+ this.program = this.buildProgram(width, height);
20
+
21
+ const backend = tf.backend();
22
+ //this.tempPixelHandle = backend.makeTensorInfo(this.texShape, 'int32');
23
+ this.tempPixelHandle = backend.makeTensorInfo(this.texShape, "float32");
24
+ // warning!!!
25
+ // usage type should be TextureUsage.PIXELS, but tfjs didn't export this enum type, so we hard-coded 2 here
26
+ // i.e. backend.texData.get(tempPixelHandle.dataId).usage = TextureUsage.PIXELS;
27
+ backend.texData.get(this.tempPixelHandle.dataId).usage = 2;
28
+ }
29
+
30
+ // old method
31
+ _loadInput(input) {
32
+ return tf.tidy(() => {
33
+ let inputImage = tf.browser.fromPixels(input);
34
+ inputImage = inputImage.mean(2);
35
+ return inputImage;
36
+ });
37
+ }
38
+
39
+ // input is instance of HTMLVideoElement or HTMLImageElement
40
+ loadInput(input) {
41
+ const context = this.context;
42
+ context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
43
+
44
+ const isInputRotated = input.width === this.height && input.height === this.width;
45
+ if (isInputRotated) {
46
+ // rotate 90 degree and draw
47
+ let x = this.context.canvas.width / 2;
48
+ let y = this.context.canvas.height / 2;
49
+ let angleInDegrees = 90;
50
+
51
+ context.save(); // save the current context state
52
+ context.translate(x, y); // move the context origin to the center of the image
53
+ context.rotate((angleInDegrees * Math.PI) / 180); // rotate the context
54
+
55
+ // draw the image with its center at the origin
56
+ context.drawImage(input, -input.width / 2, -input.height / 2);
57
+ context.restore(); // restore the context to its original state
58
+ } else {
59
+ this.context.drawImage(input, 0, 0, input.width, input.height);
60
+ }
61
+
62
+ const backend = tf.backend();
63
+ backend.gpgpu.uploadPixelDataToTexture(
64
+ backend.getTexture(this.tempPixelHandle.dataId),
65
+ this.context.canvas,
66
+ );
67
+
68
+ //const res = backend.compileAndRun(this.program, [this.tempPixelHandle]);
69
+ const res = this._compileAndRun(this.program, [this.tempPixelHandle]);
70
+ //const res = this._runWebGLProgram(this.program, [this.tempPixelHandle], 'float32');
71
+ //backend.disposeData(tempPixelHandle.dataId);
72
+ return res;
73
+ }
74
+
75
+ buildProgram(width, height) {
76
+ const textureMethod = tf.env().getNumber("WEBGL_VERSION") === 2 ? "texture" : "texture2D";
77
+
78
+ const program = {
79
+ variableNames: ["A"],
80
+ outputShape: this.texShape,
81
+ userCode: `
82
+ void main() {
83
+ ivec2 coords = getOutputCoords();
84
+ int texR = coords[0];
85
+ int texC = coords[1];
86
+ vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${width}.0, ${height}.0);
87
+
88
+ vec4 values = ${textureMethod}(A, uv);
89
+ setOutput((0.299 * values.r + 0.587 * values.g + 0.114 * values.b) * 255.0);
90
+ }
91
+ `,
92
+ };
93
+ return program;
94
+ }
95
+
96
+ _compileAndRun(program, inputs) {
97
+ const outInfo = tf.backend().compileAndRun(program, inputs);
98
+ return tf.engine().makeTensorFromDataId(outInfo.dataId, outInfo.shape, outInfo.dtype);
99
+ }
100
+
101
+ _runWebGLProgram(program, inputs, outputType) {
102
+ const outInfo = tf.backend().runWebGLProgram(program, inputs, outputType);
103
+ return tf.engine().makeTensorFromDataId(outInfo.dataId, outInfo.shape, outInfo.dtype);
104
+ }
105
+ }
106
+
107
+ export { InputLoader };
@@ -0,0 +1,23 @@
1
+ // Fast computation on number of bit sets
2
+ // Ref: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
3
+ const compute = (options) => {
4
+ const { v1, v2 } = options;
5
+ let d = 0;
6
+
7
+ for (let i = 0; i < v1.length; i++) {
8
+ let x = (v1[i] ^ v2[i]) >>> 0;
9
+ d += bitCount(x);
10
+ }
11
+ return d;
12
+ };
13
+
14
+ const bitCount = (v) => {
15
+ var c = v - ((v >> 1) & 0x55555555);
16
+ c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
17
+ c = ((c >> 4) + c) & 0x0f0f0f0f;
18
+ c = ((c >> 8) + c) & 0x00ff00ff;
19
+ c = ((c >> 16) + c) & 0x0000ffff;
20
+ return c;
21
+ };
22
+
23
+ export { compute };