@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,419 @@
1
+ import { Cumsum } from "../utils/cumsum.js";
2
+
3
+ const SEARCH_SIZE1 = 10;
4
+ const SEARCH_SIZE2 = 2;
5
+
6
+ //const TEMPLATE_SIZE = 22 // DEFAULT
7
+ const TEMPLATE_SIZE = 6;
8
+ const TEMPLATE_SD_THRESH = 5.0;
9
+ const MAX_SIM_THRESH = 0.95;
10
+
11
+ const MAX_THRESH = 0.9;
12
+ //const MIN_THRESH = 0.55;
13
+ const MIN_THRESH = 0.2;
14
+ const SD_THRESH = 8.0;
15
+ const OCCUPANCY_SIZE = (24 * 2) / 3;
16
+
17
+ /*
18
+ * Input image is in grey format. the imageData array size is width * height. value range from 0-255
19
+ * pixel value at row r and c = imageData[r * width + c]
20
+ *
21
+ * @param {Uint8Array} options.imageData
22
+ * @param {int} options.width image width
23
+ * @param {int} options.height image height
24
+ */
25
+ const extract = (image) => {
26
+ const { data: imageData, width, height, scale } = image;
27
+
28
+ // Step 1 - filter out interesting points. Interesting points have strong pixel value changed across neighbours
29
+ const isPixelSelected = [width * height];
30
+ for (let i = 0; i < isPixelSelected.length; i++) isPixelSelected[i] = false;
31
+
32
+ // Step 1.1 consider a pixel at position (x, y). compute:
33
+ // dx = ((data[x+1, y-1] - data[x-1, y-1]) + (data[x+1, y] - data[x-1, y]) + (data[x+1, y+1] - data[x-1, y-1])) / 256 / 3
34
+ // dy = ((data[x+1, y+1] - data[x+1, y-1]) + (data[x, y+1] - data[x, y-1]) + (data[x-1, y+1] - data[x-1, y-1])) / 256 / 3
35
+ // dValue = sqrt(dx^2 + dy^2) / 2;
36
+ const dValue = new Float32Array(imageData.length);
37
+ for (let i = 0; i < width; i++) {
38
+ dValue[i] = -1;
39
+ dValue[width * (height - 1) + i] = -1;
40
+ }
41
+ for (let j = 0; j < height; j++) {
42
+ dValue[j * width] = -1;
43
+ dValue[j * width + width - 1] = -1;
44
+ }
45
+
46
+ for (let i = 1; i < width - 1; i++) {
47
+ for (let j = 1; j < height - 1; j++) {
48
+ let pos = i + width * j;
49
+
50
+ let dx = 0.0;
51
+ let dy = 0.0;
52
+ for (let k = -1; k <= 1; k++) {
53
+ dx += imageData[pos + width * k + 1] - imageData[pos + width * k - 1];
54
+ dy += imageData[pos + width + k] - imageData[pos - width + k];
55
+ }
56
+ dx /= 3 * 256;
57
+ dy /= 3 * 256;
58
+ dValue[pos] = Math.sqrt((dx * dx + dy * dy) / 2);
59
+ }
60
+ }
61
+
62
+ // Step 1.2 - select all pixel which is dValue largest than all its neighbour as "potential" candidate
63
+ // the number of selected points is still too many, so we use the value to further filter (e.g. largest the dValue, the better)
64
+ const dValueHist = new Uint32Array(1000); // histogram of dvalue scaled to [0, 1000)
65
+ for (let i = 0; i < 1000; i++) dValueHist[i] = 0;
66
+ const neighbourOffsets = [-1, 1, -width, width];
67
+ let allCount = 0;
68
+ for (let i = 1; i < width - 1; i++) {
69
+ for (let j = 1; j < height - 1; j++) {
70
+ let pos = i + width * j;
71
+ let isMax = true;
72
+ for (let d = 0; d < neighbourOffsets.length; d++) {
73
+ if (dValue[pos] <= dValue[pos + neighbourOffsets[d]]) {
74
+ isMax = false;
75
+ break;
76
+ }
77
+ }
78
+ if (isMax) {
79
+ let k = Math.floor(dValue[pos] * 1000);
80
+ if (k > 999) k = 999; // k>999 should not happen if computaiton is correction
81
+ if (k < 0) k = 0; // k<0 should not happen if computaiton is correction
82
+ dValueHist[k] += 1;
83
+ allCount += 1;
84
+ isPixelSelected[pos] = true;
85
+ }
86
+ }
87
+ }
88
+
89
+ // reduce number of points according to dValue.
90
+ // actually, the whole Step 1. might be better to just sort the dvalues and pick the top (0.02 * width * height) points
91
+ const maxPoints = 0.02 * width * height;
92
+ let k = 999;
93
+ let filteredCount = 0;
94
+ while (k >= 0) {
95
+ filteredCount += dValueHist[k];
96
+ if (filteredCount > maxPoints) break;
97
+ k--;
98
+ }
99
+
100
+ //console.log("image size: ", width * height);
101
+ //console.log("extracted featues: ", allCount);
102
+ //console.log("filtered featues: ", filteredCount);
103
+
104
+ for (let i = 0; i < isPixelSelected.length; i++) {
105
+ if (isPixelSelected[i]) {
106
+ if (dValue[i] * 1000 < k) isPixelSelected[i] = false;
107
+ }
108
+ }
109
+
110
+ //console.log("selected count: ", isPixelSelected.reduce((a, b) => {return a + (b?1:0);}, 0));
111
+
112
+ // Step 2
113
+ // prebuild cumulative sum matrix for fast computation
114
+ const imageDataSqr = [];
115
+ for (let i = 0; i < imageData.length; i++) {
116
+ imageDataSqr[i] = imageData[i] * imageData[i];
117
+ }
118
+ const imageDataCumsum = new Cumsum(imageData, width, height);
119
+ const imageDataSqrCumsum = new Cumsum(imageDataSqr, width, height);
120
+
121
+ // holds the max similariliy value computed within SEARCH area of each pixel
122
+ // idea: if there is high simliarity with another pixel in nearby area, then it's not a good feature point
123
+ // next step is to find pixel with low similarity
124
+ const featureMap = new Float32Array(imageData.length);
125
+
126
+ for (let i = 0; i < width; i++) {
127
+ for (let j = 0; j < height; j++) {
128
+ const pos = j * width + i;
129
+ if (!isPixelSelected[pos]) {
130
+ featureMap[pos] = 1.0;
131
+ continue;
132
+ }
133
+
134
+ const vlen = _templateVar({
135
+ image,
136
+ cx: i,
137
+ cy: j,
138
+ sdThresh: TEMPLATE_SD_THRESH,
139
+ imageDataCumsum,
140
+ imageDataSqrCumsum,
141
+ });
142
+ if (vlen === null) {
143
+ featureMap[pos] = 1.0;
144
+ continue;
145
+ }
146
+
147
+ let max = -1.0;
148
+ for (let jj = -SEARCH_SIZE1; jj <= SEARCH_SIZE1; jj++) {
149
+ for (let ii = -SEARCH_SIZE1; ii <= SEARCH_SIZE1; ii++) {
150
+ if (ii * ii + jj * jj <= SEARCH_SIZE2 * SEARCH_SIZE2) continue;
151
+ const sim = _getSimilarity({
152
+ image,
153
+ cx: i + ii,
154
+ cy: j + jj,
155
+ vlen: vlen,
156
+ tx: i,
157
+ ty: j,
158
+ imageDataCumsum,
159
+ imageDataSqrCumsum,
160
+ });
161
+
162
+ if (sim === null) continue;
163
+
164
+ if (sim > max) {
165
+ max = sim;
166
+ if (max > MAX_SIM_THRESH) break;
167
+ }
168
+ }
169
+ if (max > MAX_SIM_THRESH) break;
170
+ }
171
+ featureMap[pos] = max;
172
+ }
173
+ }
174
+
175
+ // Step 2.2 select feature
176
+ const coords = _selectFeature({
177
+ image,
178
+ featureMap,
179
+ templateSize: TEMPLATE_SIZE,
180
+ searchSize: SEARCH_SIZE2,
181
+ occSize: OCCUPANCY_SIZE,
182
+ maxSimThresh: MAX_THRESH,
183
+ minSimThresh: MIN_THRESH,
184
+ sdThresh: SD_THRESH,
185
+ imageDataCumsum,
186
+ imageDataSqrCumsum,
187
+ });
188
+
189
+ return coords;
190
+ };
191
+
192
+ const _selectFeature = (options) => {
193
+ let {
194
+ image,
195
+ featureMap,
196
+ templateSize,
197
+ searchSize,
198
+ occSize,
199
+ maxSimThresh,
200
+ minSimThresh,
201
+ sdThresh,
202
+ imageDataCumsum,
203
+ imageDataSqrCumsum,
204
+ } = options;
205
+ const { data: imageData, width, height, scale } = image;
206
+
207
+ //console.log("params: ", templateSize, templateSize, occSize, maxSimThresh, minSimThresh, sdThresh);
208
+
209
+ //occSize *= 2;
210
+ occSize = Math.floor(Math.min(image.width, image.height) / 10);
211
+
212
+ const divSize = (templateSize * 2 + 1) * 3;
213
+ const xDiv = Math.floor(width / divSize);
214
+ const yDiv = Math.floor(height / divSize);
215
+
216
+ let maxFeatureNum = Math.floor(width / occSize) * Math.floor(height / occSize) + xDiv * yDiv;
217
+ //console.log("max feature num: ", maxFeatureNum);
218
+
219
+ const coords = [];
220
+ const image2 = new Float32Array(imageData.length);
221
+ for (let i = 0; i < image2.length; i++) {
222
+ image2[i] = featureMap[i];
223
+ }
224
+
225
+ let num = 0;
226
+ while (num < maxFeatureNum) {
227
+ let minSim = maxSimThresh;
228
+ let cx = -1;
229
+ let cy = -1;
230
+ for (let j = 0; j < height; j++) {
231
+ for (let i = 0; i < width; i++) {
232
+ if (image2[j * width + i] < minSim) {
233
+ minSim = image2[j * width + i];
234
+ cx = i;
235
+ cy = j;
236
+ }
237
+ }
238
+ }
239
+ if (cx === -1) break;
240
+
241
+ const vlen = _templateVar({
242
+ image,
243
+ cx: cx,
244
+ cy: cy,
245
+ sdThresh: 0,
246
+ imageDataCumsum,
247
+ imageDataSqrCumsum,
248
+ });
249
+ if (vlen === null) {
250
+ image2[cy * width + cx] = 1.0;
251
+ continue;
252
+ }
253
+ if (vlen / (templateSize * 2 + 1) < sdThresh) {
254
+ image2[cy * width + cx] = 1.0;
255
+ continue;
256
+ }
257
+
258
+ let min = 1.0;
259
+ let max = -1.0;
260
+
261
+ for (let j = -searchSize; j <= searchSize; j++) {
262
+ for (let i = -searchSize; i <= searchSize; i++) {
263
+ if (i * i + j * j > searchSize * searchSize) continue;
264
+ if (i === 0 && j === 0) continue;
265
+
266
+ const sim = _getSimilarity({
267
+ image,
268
+ vlen,
269
+ cx: cx + i,
270
+ cy: cy + j,
271
+ tx: cx,
272
+ ty: cy,
273
+ imageDataCumsum,
274
+ imageDataSqrCumsum,
275
+ });
276
+ if (sim === null) continue;
277
+
278
+ if (sim < min) {
279
+ min = sim;
280
+ if (min < minSimThresh && min < minSim) break;
281
+ }
282
+ if (sim > max) {
283
+ max = sim;
284
+ if (max > 0.99) break;
285
+ }
286
+ }
287
+ if ((min < minSimThresh && min < minSim) || max > 0.99) break;
288
+ }
289
+
290
+ if ((min < minSimThresh && min < minSim) || max > 0.99) {
291
+ image2[cy * width + cx] = 1.0;
292
+ continue;
293
+ }
294
+
295
+ coords.push({ x: cx, y: cy });
296
+ //coords.push({
297
+ //mx: 1.0 * cx / scale,
298
+ //my: 1.0 * (height - cy) / scale,
299
+ //})
300
+
301
+ num += 1;
302
+ //console.log(num, '(', cx, ',', cy, ')', minSim, 'min = ', min, 'max = ', max, 'sd = ', vlen/(templateSize*2+1));
303
+
304
+ // no other feature points within occSize square
305
+ for (let j = -occSize; j <= occSize; j++) {
306
+ for (let i = -occSize; i <= occSize; i++) {
307
+ if (cy + j < 0 || cy + j >= height || cx + i < 0 || cx + i >= width) continue;
308
+ image2[(cy + j) * width + (cx + i)] = 1.0;
309
+ }
310
+ }
311
+ }
312
+ return coords;
313
+ };
314
+
315
+ // compute variances of the pixels, centered at (cx, cy)
316
+ const _templateVar = ({ image, cx, cy, sdThresh, imageDataCumsum, imageDataSqrCumsum }) => {
317
+ if (cx - TEMPLATE_SIZE < 0 || cx + TEMPLATE_SIZE >= image.width) return null;
318
+ if (cy - TEMPLATE_SIZE < 0 || cy + TEMPLATE_SIZE >= image.height) return null;
319
+
320
+ const templateWidth = 2 * TEMPLATE_SIZE + 1;
321
+ const nPixels = templateWidth * templateWidth;
322
+
323
+ let average = imageDataCumsum.query(
324
+ cx - TEMPLATE_SIZE,
325
+ cy - TEMPLATE_SIZE,
326
+ cx + TEMPLATE_SIZE,
327
+ cy + TEMPLATE_SIZE,
328
+ );
329
+ average /= nPixels;
330
+
331
+ //v = sum((pixel_i - avg)^2) for all pixel i within the template
332
+ // = sum(pixel_i^2) - sum(2 * avg * pixel_i) + sum(avg^avg)
333
+
334
+ let vlen = imageDataSqrCumsum.query(
335
+ cx - TEMPLATE_SIZE,
336
+ cy - TEMPLATE_SIZE,
337
+ cx + TEMPLATE_SIZE,
338
+ cy + TEMPLATE_SIZE,
339
+ );
340
+ vlen -=
341
+ 2 *
342
+ average *
343
+ imageDataCumsum.query(
344
+ cx - TEMPLATE_SIZE,
345
+ cy - TEMPLATE_SIZE,
346
+ cx + TEMPLATE_SIZE,
347
+ cy + TEMPLATE_SIZE,
348
+ );
349
+ vlen += nPixels * average * average;
350
+
351
+ if (vlen / nPixels < sdThresh * sdThresh) return null;
352
+ vlen = Math.sqrt(vlen);
353
+ return vlen;
354
+ };
355
+
356
+ const _getSimilarity = (options) => {
357
+ const { image, cx, cy, vlen, tx, ty, imageDataCumsum, imageDataSqrCumsum } = options;
358
+ const { data: imageData, width, height } = image;
359
+ const templateSize = TEMPLATE_SIZE;
360
+
361
+ if (cx - templateSize < 0 || cx + templateSize >= width) return null;
362
+ if (cy - templateSize < 0 || cy + templateSize >= height) return null;
363
+
364
+ const templateWidth = 2 * templateSize + 1;
365
+
366
+ let sx = imageDataCumsum.query(
367
+ cx - templateSize,
368
+ cy - templateSize,
369
+ cx + templateSize,
370
+ cy + templateSize,
371
+ );
372
+ let sxx = imageDataSqrCumsum.query(
373
+ cx - templateSize,
374
+ cy - templateSize,
375
+ cx + templateSize,
376
+ cy + templateSize,
377
+ );
378
+ let sxy = 0;
379
+
380
+ // !! This loop is the performance bottleneck. Use moving pointers to optimize
381
+ //
382
+ // for (let i = cx - templateSize, i2 = tx - templateSize; i <= cx + templateSize; i++, i2++) {
383
+ // for (let j = cy - templateSize, j2 = ty - templateSize; j <= cy + templateSize; j++, j2++) {
384
+ // sxy += imageData[j*width + i] * imageData[j2*width + i2];
385
+ // }
386
+ // }
387
+ //
388
+ let p1 = (cy - templateSize) * width + (cx - templateSize);
389
+ let p2 = (ty - templateSize) * width + (tx - templateSize);
390
+ let nextRowOffset = width - templateWidth;
391
+ for (let j = 0; j < templateWidth; j++) {
392
+ for (let i = 0; i < templateWidth; i++) {
393
+ sxy += imageData[p1] * imageData[p2];
394
+ p1 += 1;
395
+ p2 += 1;
396
+ }
397
+ p1 += nextRowOffset;
398
+ p2 += nextRowOffset;
399
+ }
400
+
401
+ let templateAverage = imageDataCumsum.query(
402
+ tx - templateSize,
403
+ ty - templateSize,
404
+ tx + templateSize,
405
+ ty + templateSize,
406
+ );
407
+ templateAverage /= templateWidth * templateWidth;
408
+ sxy -= templateAverage * sx;
409
+
410
+ let vlen2 = sxx - (sx * sx) / (templateWidth * templateWidth);
411
+ if (vlen2 == 0) return null;
412
+ vlen2 = Math.sqrt(vlen2);
413
+
414
+ // covariance between template and current pixel
415
+ const sim = (1.0 * sxy) / (vlen * vlen2);
416
+ return sim;
417
+ };
418
+
419
+ export { extract };