@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,109 @@
1
+ import { compute as hammingCompute } from "./hamming-distance.js";
2
+ import { createRandomizer } from "../utils/randomizer.js";
3
+ const MIN_FEATURE_PER_NODE = 16;
4
+ const NUM_ASSIGNMENT_HYPOTHESES = 128;
5
+ const NUM_CENTERS = 8;
6
+ const _computeKMedoids = (options) => {
7
+ const { points, pointIndexes, randomizer } = options;
8
+ const randomPointIndexes = [];
9
+ for (let i = 0; i < pointIndexes.length; i++) {
10
+ randomPointIndexes.push(i);
11
+ }
12
+ let bestSumD = Number.MAX_SAFE_INTEGER;
13
+ let bestAssignmentIndex = -1;
14
+ const assignments = [];
15
+ for (let i = 0; i < NUM_ASSIGNMENT_HYPOTHESES; i++) {
16
+ randomizer.arrayShuffle({ arr: randomPointIndexes, sampleSize: NUM_CENTERS });
17
+ let sumD = 0;
18
+ const assignment = [];
19
+ for (let j = 0; j < pointIndexes.length; j++) {
20
+ let bestD = Number.MAX_SAFE_INTEGER;
21
+ for (let k = 0; k < NUM_CENTERS; k++) {
22
+ const centerIndex = pointIndexes[randomPointIndexes[k]];
23
+ const d = hammingCompute({
24
+ v1: points[pointIndexes[j]].descriptors,
25
+ v2: points[centerIndex].descriptors,
26
+ });
27
+ if (d < bestD) {
28
+ assignment[j] = randomPointIndexes[k];
29
+ bestD = d;
30
+ }
31
+ }
32
+ sumD += bestD;
33
+ }
34
+ assignments.push(assignment);
35
+ if (sumD < bestSumD) {
36
+ bestSumD = sumD;
37
+ bestAssignmentIndex = i;
38
+ }
39
+ }
40
+ return assignments[bestAssignmentIndex];
41
+ };
42
+ // kmedoids clustering of points, with hamming distance of FREAK descriptor
43
+ //
44
+ // node = {
45
+ // isLeaf: bool,
46
+ // children: [], list of children node
47
+ // pointIndexes: [], list of int, point indexes
48
+ // centerPointIndex: int
49
+ // }
50
+ const build = ({ points }) => {
51
+ const pointIndexes = [];
52
+ for (let i = 0; i < points.length; i++) {
53
+ pointIndexes.push(i);
54
+ }
55
+ const randomizer = createRandomizer();
56
+ const rootNode = _build({
57
+ points: points,
58
+ pointIndexes: pointIndexes,
59
+ centerPointIndex: null,
60
+ randomizer,
61
+ });
62
+ return { rootNode };
63
+ };
64
+ // recursive build hierarchy clusters
65
+ const _build = (options) => {
66
+ const { points, pointIndexes, centerPointIndex, randomizer } = options;
67
+ let isLeaf = false;
68
+ if (pointIndexes.length <= NUM_CENTERS || pointIndexes.length <= MIN_FEATURE_PER_NODE) {
69
+ isLeaf = true;
70
+ }
71
+ const clusters = {};
72
+ if (!isLeaf) {
73
+ // compute clusters
74
+ const assignment = _computeKMedoids({ points, pointIndexes, randomizer });
75
+ for (let i = 0; i < assignment.length; i++) {
76
+ if (clusters[pointIndexes[assignment[i]]] === undefined) {
77
+ clusters[pointIndexes[assignment[i]]] = [];
78
+ }
79
+ clusters[pointIndexes[assignment[i]]].push(pointIndexes[i]);
80
+ }
81
+ }
82
+ if (Object.keys(clusters).length === 1) {
83
+ isLeaf = true;
84
+ }
85
+ const node = {
86
+ centerPointIndex: centerPointIndex,
87
+ };
88
+ if (isLeaf) {
89
+ node.leaf = true;
90
+ node.pointIndexes = [];
91
+ for (let i = 0; i < pointIndexes.length; i++) {
92
+ node.pointIndexes.push(pointIndexes[i]);
93
+ }
94
+ return node;
95
+ }
96
+ // recursive build children
97
+ node.leaf = false;
98
+ node.children = [];
99
+ Object.keys(clusters).forEach((centerIndex) => {
100
+ node.children.push(_build({
101
+ points: points,
102
+ pointIndexes: clusters[centerIndex],
103
+ centerPointIndex: centerIndex,
104
+ randomizer,
105
+ }));
106
+ });
107
+ return node;
108
+ };
109
+ export { build };
@@ -0,0 +1 @@
1
+ export function computeHoughMatches(options: any): any[];
@@ -0,0 +1,169 @@
1
+ const kHoughBinDelta = 1;
2
+ // mathces [querypointIndex:x, keypointIndex: x]
3
+ const computeHoughMatches = (options) => {
4
+ const { keywidth, keyheight, querywidth, queryheight, matches } = options;
5
+ const maxX = querywidth * 1.2;
6
+ const minX = -maxX;
7
+ const maxY = queryheight * 1.2;
8
+ const minY = -maxY;
9
+ const numAngleBins = 12;
10
+ const numScaleBins = 10;
11
+ const minScale = -1;
12
+ const maxScale = 1;
13
+ const scaleK = 10.0;
14
+ const scaleOneOverLogK = 1.0 / Math.log(scaleK);
15
+ const maxDim = Math.max(keywidth, keyheight);
16
+ const keycenterX = Math.floor(keywidth / 2);
17
+ const keycenterY = Math.floor(keyheight / 2);
18
+ // compute numXBins and numYBins based on matches
19
+ const projectedDims = [];
20
+ for (let i = 0; i < matches.length; i++) {
21
+ const queryscale = matches[i].querypoint.scale;
22
+ const keyscale = matches[i].keypoint.scale;
23
+ if (keyscale == 0)
24
+ console.log("ERROR divide zero");
25
+ const scale = queryscale / keyscale;
26
+ projectedDims.push(scale * maxDim);
27
+ }
28
+ // TODO optimize median
29
+ // weird. median should be [Math.floor(projectedDims.length/2) - 1] ?
30
+ projectedDims.sort((a1, a2) => {
31
+ return a1 - a2;
32
+ });
33
+ const medianProjectedDim = projectedDims[Math.floor(projectedDims.length / 2) - (projectedDims.length % 2 == 0 ? 1 : 0) - 1];
34
+ const binSize = 0.25 * medianProjectedDim;
35
+ const numXBins = Math.max(5, Math.ceil((maxX - minX) / binSize));
36
+ const numYBins = Math.max(5, Math.ceil((maxY - minY) / binSize));
37
+ const numXYBins = numXBins * numYBins;
38
+ const numXYAngleBins = numXYBins * numAngleBins;
39
+ // do voting
40
+ const querypointValids = [];
41
+ const querypointBinLocations = [];
42
+ const votes = {};
43
+ for (let i = 0; i < matches.length; i++) {
44
+ const querypoint = matches[i].querypoint;
45
+ const keypoint = matches[i].keypoint;
46
+ const { x, y, scale, angle } = _mapCorrespondence({
47
+ querypoint,
48
+ keypoint,
49
+ keycenterX,
50
+ keycenterY,
51
+ scaleOneOverLogK,
52
+ });
53
+ // Check that the vote is within range
54
+ if (x < minX ||
55
+ x >= maxX ||
56
+ y < minY ||
57
+ y >= maxY ||
58
+ angle <= -Math.PI ||
59
+ angle > Math.PI ||
60
+ scale < minScale ||
61
+ scale >= maxScale) {
62
+ querypointValids[i] = false;
63
+ continue;
64
+ }
65
+ // map properties to bins
66
+ let fbinX = (numXBins * (x - minX)) / (maxX - minX);
67
+ let fbinY = (numYBins * (y - minY)) / (maxY - minY);
68
+ let fbinAngle = (numAngleBins * (angle + Math.PI)) / (2.0 * Math.PI);
69
+ let fbinScale = (numScaleBins * (scale - minScale)) / (maxScale - minScale);
70
+ querypointBinLocations[i] = {
71
+ binX: fbinX,
72
+ binY: fbinY,
73
+ binAngle: fbinAngle,
74
+ binScale: fbinScale,
75
+ };
76
+ let binX = Math.floor(fbinX - 0.5);
77
+ let binY = Math.floor(fbinY - 0.5);
78
+ let binScale = Math.floor(fbinScale - 0.5);
79
+ let binAngle = (Math.floor(fbinAngle - 0.5) + numAngleBins) % numAngleBins;
80
+ // check can vote all 16 bins
81
+ if (binX < 0 ||
82
+ binX + 1 >= numXBins ||
83
+ binY < 0 ||
84
+ binY + 1 >= numYBins ||
85
+ binScale < 0 ||
86
+ binScale + 1 >= numScaleBins) {
87
+ querypointValids[i] = false;
88
+ continue;
89
+ }
90
+ for (let dx = 0; dx < 2; dx++) {
91
+ let binX2 = binX + dx;
92
+ for (let dy = 0; dy < 2; dy++) {
93
+ let binY2 = binY + dy;
94
+ for (let dangle = 0; dangle < 2; dangle++) {
95
+ let binAngle2 = (binAngle + dangle) % numAngleBins;
96
+ for (let dscale = 0; dscale < 2; dscale++) {
97
+ let binScale2 = binScale + dscale;
98
+ const binIndex = binX2 + binY2 * numXBins + binAngle2 * numXYBins + binScale2 * numXYAngleBins;
99
+ if (votes[binIndex] === undefined)
100
+ votes[binIndex] = 0;
101
+ votes[binIndex] += 1;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ querypointValids[i] = true;
107
+ }
108
+ let maxVotes = 0;
109
+ let maxVoteIndex = -1;
110
+ Object.keys(votes).forEach((index) => {
111
+ if (votes[index] > maxVotes) {
112
+ maxVotes = votes[index];
113
+ maxVoteIndex = index;
114
+ }
115
+ });
116
+ if (maxVotes < 3)
117
+ return [];
118
+ // get back bins from vote index
119
+ const binX = Math.floor(((maxVoteIndex % numXYAngleBins) % numXYBins) % numXBins);
120
+ const binY = Math.floor((((maxVoteIndex - binX) % numXYAngleBins) % numXYBins) / numXBins);
121
+ const binAngle = Math.floor(((maxVoteIndex - binX - binY * numXBins) % numXYAngleBins) / numXYBins);
122
+ const binScale = Math.floor((maxVoteIndex - binX - binY * numXBins - binAngle * numXYBins) / numXYAngleBins);
123
+ //console.log("hough voted: ", {binX, binY, binAngle, binScale, maxVoteIndex});
124
+ const houghMatches = [];
125
+ for (let i = 0; i < matches.length; i++) {
126
+ if (!querypointValids[i])
127
+ continue;
128
+ const queryBins = querypointBinLocations[i];
129
+ // compute bin difference
130
+ const distBinX = Math.abs(queryBins.binX - (binX + 0.5));
131
+ if (distBinX >= kHoughBinDelta)
132
+ continue;
133
+ const distBinY = Math.abs(queryBins.binY - (binY + 0.5));
134
+ if (distBinY >= kHoughBinDelta)
135
+ continue;
136
+ const distBinScale = Math.abs(queryBins.binScale - (binScale + 0.5));
137
+ if (distBinScale >= kHoughBinDelta)
138
+ continue;
139
+ const temp = Math.abs(queryBins.binAngle - (binAngle + 0.5));
140
+ const distBinAngle = Math.min(temp, numAngleBins - temp);
141
+ if (distBinAngle >= kHoughBinDelta)
142
+ continue;
143
+ houghMatches.push(matches[i]);
144
+ }
145
+ return houghMatches;
146
+ };
147
+ const _mapCorrespondence = ({ querypoint, keypoint, keycenterX, keycenterY, scaleOneOverLogK }) => {
148
+ // map angle to (-pi, pi]
149
+ let angle = querypoint.angle - keypoint.angle;
150
+ if (angle <= -Math.PI)
151
+ angle += 2 * Math.PI;
152
+ else if (angle > Math.PI)
153
+ angle -= 2 * Math.PI;
154
+ const scale = querypoint.scale / keypoint.scale;
155
+ // 2x2 similarity
156
+ const cos = scale * Math.cos(angle);
157
+ const sin = scale * Math.sin(angle);
158
+ const S = [cos, -sin, sin, cos];
159
+ const tp = [S[0] * keypoint.x + S[1] * keypoint.y, S[2] * keypoint.x + S[3] * keypoint.y];
160
+ const tx = querypoint.x - tp[0];
161
+ const ty = querypoint.y - tp[1];
162
+ return {
163
+ x: S[0] * keycenterX + S[1] * keycenterY + tx,
164
+ y: S[2] * keycenterX + S[3] * keycenterY + ty,
165
+ angle: angle,
166
+ scale: Math.log(scale) * scaleOneOverLogK,
167
+ };
168
+ };
169
+ export { computeHoughMatches };
@@ -0,0 +1,28 @@
1
+ export class Matcher {
2
+ constructor(queryWidth: any, queryHeight: any, debugMode?: boolean);
3
+ queryWidth: any;
4
+ queryHeight: any;
5
+ debugMode: boolean;
6
+ matchDetection(keyframes: any, featurePoints: any): {
7
+ keyframeIndex: number;
8
+ debugExtra: {
9
+ frames: never[];
10
+ };
11
+ screenCoords?: undefined;
12
+ worldCoords?: undefined;
13
+ } | {
14
+ screenCoords: {
15
+ x: any;
16
+ y: any;
17
+ }[];
18
+ worldCoords: {
19
+ x: number;
20
+ y: number;
21
+ z: number;
22
+ }[];
23
+ keyframeIndex: number;
24
+ debugExtra: {
25
+ frames: never[];
26
+ };
27
+ };
28
+ }
@@ -0,0 +1,48 @@
1
+ import { match } from "./matching.js";
2
+ class Matcher {
3
+ constructor(queryWidth, queryHeight, debugMode = false) {
4
+ this.queryWidth = queryWidth;
5
+ this.queryHeight = queryHeight;
6
+ this.debugMode = debugMode;
7
+ }
8
+ matchDetection(keyframes, featurePoints) {
9
+ let debugExtra = { frames: [] };
10
+ let bestResult = null;
11
+ for (let i = 0; i < keyframes.length; i++) {
12
+ const { H, matches, debugExtra: frameDebugExtra, } = match({
13
+ keyframe: keyframes[i],
14
+ querypoints: featurePoints,
15
+ querywidth: this.queryWidth,
16
+ queryheight: this.queryHeight,
17
+ debugMode: this.debugMode,
18
+ });
19
+ debugExtra.frames.push(frameDebugExtra);
20
+ if (H) {
21
+ if (bestResult === null || bestResult.matches.length < matches.length) {
22
+ bestResult = { keyframeIndex: i, H, matches };
23
+ }
24
+ }
25
+ }
26
+ if (bestResult === null) {
27
+ return { keyframeIndex: -1, debugExtra };
28
+ }
29
+ const screenCoords = [];
30
+ const worldCoords = [];
31
+ const keyframe = keyframes[bestResult.keyframeIndex];
32
+ for (let i = 0; i < bestResult.matches.length; i++) {
33
+ const querypoint = bestResult.matches[i].querypoint;
34
+ const keypoint = bestResult.matches[i].keypoint;
35
+ screenCoords.push({
36
+ x: querypoint.x,
37
+ y: querypoint.y,
38
+ });
39
+ worldCoords.push({
40
+ x: (keypoint.x + 0.5) / keyframe.scale,
41
+ y: (keypoint.y + 0.5) / keyframe.scale,
42
+ z: 0,
43
+ });
44
+ }
45
+ return { screenCoords, worldCoords, keyframeIndex: bestResult.keyframeIndex, debugExtra };
46
+ }
47
+ }
48
+ export { Matcher };
@@ -0,0 +1,41 @@
1
+ export function match({ keyframe, querypoints, querywidth, queryheight, debugMode }: {
2
+ keyframe: any;
3
+ querypoints: any;
4
+ querywidth: any;
5
+ queryheight: any;
6
+ debugMode: any;
7
+ }): {
8
+ debugExtra: {
9
+ matches: {
10
+ querypoint: any;
11
+ keypoint: any;
12
+ }[];
13
+ houghMatches: any[];
14
+ inlierMatches: any[];
15
+ matches2: {
16
+ querypoint: any;
17
+ keypoint: any;
18
+ }[];
19
+ houghMatches2: any[];
20
+ inlierMatches2: any[];
21
+ };
22
+ H?: undefined;
23
+ matches?: undefined;
24
+ } | {
25
+ H: number[];
26
+ matches: any[];
27
+ debugExtra: {
28
+ matches: {
29
+ querypoint: any;
30
+ keypoint: any;
31
+ }[];
32
+ houghMatches: any[];
33
+ inlierMatches: any[];
34
+ matches2: {
35
+ querypoint: any;
36
+ keypoint: any;
37
+ }[];
38
+ houghMatches2: any[];
39
+ inlierMatches2: any[];
40
+ };
41
+ };
@@ -0,0 +1,197 @@
1
+ import TinyQueue from "tinyqueue";
2
+ import { compute as hammingCompute } from "./hamming-distance.js";
3
+ import { computeHoughMatches } from "./hough.js";
4
+ import { computeHomography } from "./ransacHomography.js";
5
+ import { multiplyPointHomographyInhomogenous, matrixInverse33 } from "../utils/geometry.js";
6
+ const INLIER_THRESHOLD = 3;
7
+ //const MIN_NUM_INLIERS = 8; //default
8
+ const MIN_NUM_INLIERS = 6;
9
+ const CLUSTER_MAX_POP = 8;
10
+ const HAMMING_THRESHOLD = 0.7;
11
+ // match list of querpoints against pre-built list of keyframes
12
+ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) => {
13
+ let debugExtra = {};
14
+ const matches = [];
15
+ for (let j = 0; j < querypoints.length; j++) {
16
+ const querypoint = querypoints[j];
17
+ const keypoints = querypoint.maxima ? keyframe.maximaPoints : keyframe.minimaPoints;
18
+ if (keypoints.length === 0)
19
+ continue;
20
+ const rootNode = querypoint.maxima
21
+ ? keyframe.maximaPointsCluster.rootNode
22
+ : keyframe.minimaPointsCluster.rootNode;
23
+ const keypointIndexes = [];
24
+ const queue = new TinyQueue([], (a1, a2) => {
25
+ return a1.d - a2.d;
26
+ });
27
+ // query all potential keypoints
28
+ _query({ node: rootNode, keypoints, querypoint, queue, keypointIndexes, numPop: 0 });
29
+ let bestIndex = -1;
30
+ let bestD1 = Number.MAX_SAFE_INTEGER;
31
+ let bestD2 = Number.MAX_SAFE_INTEGER;
32
+ for (let k = 0; k < keypointIndexes.length; k++) {
33
+ const keypoint = keypoints[keypointIndexes[k]];
34
+ const d = hammingCompute({ v1: keypoint.descriptors, v2: querypoint.descriptors });
35
+ if (d < bestD1) {
36
+ bestD2 = bestD1;
37
+ bestD1 = d;
38
+ bestIndex = keypointIndexes[k];
39
+ }
40
+ else if (d < bestD2) {
41
+ bestD2 = d;
42
+ }
43
+ }
44
+ if (bestIndex !== -1 &&
45
+ (bestD2 === Number.MAX_SAFE_INTEGER || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)) {
46
+ matches.push({ querypoint, keypoint: keypoints[bestIndex] });
47
+ }
48
+ }
49
+ if (debugMode) {
50
+ debugExtra.matches = matches;
51
+ }
52
+ if (matches.length < MIN_NUM_INLIERS)
53
+ return { debugExtra };
54
+ const houghMatches = computeHoughMatches({
55
+ keywidth: keyframe.width,
56
+ keyheight: keyframe.height,
57
+ querywidth,
58
+ queryheight,
59
+ matches,
60
+ });
61
+ if (debugMode) {
62
+ debugExtra.houghMatches = houghMatches;
63
+ }
64
+ const H = computeHomography({
65
+ srcPoints: houghMatches.map((m) => [m.keypoint.x, m.keypoint.y]),
66
+ dstPoints: houghMatches.map((m) => [m.querypoint.x, m.querypoint.y]),
67
+ keyframe,
68
+ });
69
+ if (H === null)
70
+ return { debugExtra };
71
+ const inlierMatches = _findInlierMatches({
72
+ H,
73
+ matches: houghMatches,
74
+ threshold: INLIER_THRESHOLD,
75
+ });
76
+ if (debugMode) {
77
+ debugExtra.inlierMatches = inlierMatches;
78
+ }
79
+ if (inlierMatches.length < MIN_NUM_INLIERS)
80
+ return { debugExtra };
81
+ // do another loop of match using the homography
82
+ const HInv = matrixInverse33(H, 0.00001);
83
+ const dThreshold2 = 10 * 10;
84
+ const matches2 = [];
85
+ for (let j = 0; j < querypoints.length; j++) {
86
+ const querypoint = querypoints[j];
87
+ const mapquerypoint = multiplyPointHomographyInhomogenous([querypoint.x, querypoint.y], HInv);
88
+ let bestIndex = -1;
89
+ let bestD1 = Number.MAX_SAFE_INTEGER;
90
+ let bestD2 = Number.MAX_SAFE_INTEGER;
91
+ const keypoints = querypoint.maxima ? keyframe.maximaPoints : keyframe.minimaPoints;
92
+ for (let k = 0; k < keypoints.length; k++) {
93
+ const keypoint = keypoints[k];
94
+ // check distance threshold
95
+ const d2 = (keypoint.x - mapquerypoint[0]) * (keypoint.x - mapquerypoint[0]) +
96
+ (keypoint.y - mapquerypoint[1]) * (keypoint.y - mapquerypoint[1]);
97
+ if (d2 > dThreshold2)
98
+ continue;
99
+ const d = hammingCompute({ v1: keypoint.descriptors, v2: querypoint.descriptors });
100
+ if (d < bestD1) {
101
+ bestD2 = bestD1;
102
+ bestD1 = d;
103
+ bestIndex = k;
104
+ }
105
+ else if (d < bestD2) {
106
+ bestD2 = d;
107
+ }
108
+ }
109
+ if (bestIndex !== -1 &&
110
+ (bestD2 === Number.MAX_SAFE_INTEGER || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)) {
111
+ matches2.push({ querypoint, keypoint: keypoints[bestIndex] });
112
+ }
113
+ }
114
+ if (debugMode) {
115
+ debugExtra.matches2 = matches2;
116
+ }
117
+ const houghMatches2 = computeHoughMatches({
118
+ keywidth: keyframe.width,
119
+ keyheight: keyframe.height,
120
+ querywidth,
121
+ queryheight,
122
+ matches: matches2,
123
+ });
124
+ if (debugMode) {
125
+ debugExtra.houghMatches2 = houghMatches2;
126
+ }
127
+ const H2 = computeHomography({
128
+ srcPoints: houghMatches2.map((m) => [m.keypoint.x, m.keypoint.y]),
129
+ dstPoints: houghMatches2.map((m) => [m.querypoint.x, m.querypoint.y]),
130
+ keyframe,
131
+ });
132
+ if (H2 === null)
133
+ return { debugExtra };
134
+ const inlierMatches2 = _findInlierMatches({
135
+ H: H2,
136
+ matches: houghMatches2,
137
+ threshold: INLIER_THRESHOLD,
138
+ });
139
+ if (debugMode) {
140
+ debugExtra.inlierMatches2 = inlierMatches2;
141
+ }
142
+ return { H: H2, matches: inlierMatches2, debugExtra };
143
+ };
144
+ const _query = ({ node, keypoints, querypoint, queue, keypointIndexes, numPop }) => {
145
+ if (node.leaf) {
146
+ for (let i = 0; i < node.pointIndexes.length; i++) {
147
+ keypointIndexes.push(node.pointIndexes[i]);
148
+ }
149
+ return;
150
+ }
151
+ const distances = [];
152
+ for (let i = 0; i < node.children.length; i++) {
153
+ const childNode = node.children[i];
154
+ const centerPointIndex = childNode.centerPointIndex;
155
+ const d = hammingCompute({
156
+ v1: keypoints[centerPointIndex].descriptors,
157
+ v2: querypoint.descriptors,
158
+ });
159
+ distances.push(d);
160
+ }
161
+ let minD = Number.MAX_SAFE_INTEGER;
162
+ for (let i = 0; i < node.children.length; i++) {
163
+ minD = Math.min(minD, distances[i]);
164
+ }
165
+ for (let i = 0; i < node.children.length; i++) {
166
+ if (distances[i] !== minD) {
167
+ queue.push({ node: node.children[i], d: distances[i] });
168
+ }
169
+ }
170
+ for (let i = 0; i < node.children.length; i++) {
171
+ if (distances[i] === minD) {
172
+ _query({ node: node.children[i], keypoints, querypoint, queue, keypointIndexes, numPop });
173
+ }
174
+ }
175
+ if (numPop < CLUSTER_MAX_POP && queue.length > 0) {
176
+ const { node, d } = queue.pop();
177
+ numPop += 1;
178
+ _query({ node, keypoints, querypoint, queue, keypointIndexes, numPop });
179
+ }
180
+ };
181
+ const _findInlierMatches = (options) => {
182
+ const { H, matches, threshold } = options;
183
+ const threshold2 = threshold * threshold;
184
+ const goodMatches = [];
185
+ for (let i = 0; i < matches.length; i++) {
186
+ const querypoint = matches[i].querypoint;
187
+ const keypoint = matches[i].keypoint;
188
+ const mp = multiplyPointHomographyInhomogenous([keypoint.x, keypoint.y], H);
189
+ const d2 = (mp[0] - querypoint.x) * (mp[0] - querypoint.x) +
190
+ (mp[1] - querypoint.y) * (mp[1] - querypoint.y);
191
+ if (d2 <= threshold2) {
192
+ goodMatches.push(matches[i]);
193
+ }
194
+ }
195
+ return goodMatches;
196
+ };
197
+ export { match };
@@ -0,0 +1 @@
1
+ export function computeHomography(options: any): number[] | null;