@visutry/tryon-core 0.2.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 (86) hide show
  1. package/README.md +58 -0
  2. package/dist/__fixtures__/faceFixtures.d.ts +13 -0
  3. package/dist/__fixtures__/faceFixtures.d.ts.map +1 -0
  4. package/dist/__fixtures__/faceFixtures.js +206 -0
  5. package/dist/__fixtures__/faceFixtures.js.map +1 -0
  6. package/dist/adapter/visutry-site.d.ts +76 -0
  7. package/dist/adapter/visutry-site.d.ts.map +1 -0
  8. package/dist/adapter/visutry-site.js +172 -0
  9. package/dist/adapter/visutry-site.js.map +1 -0
  10. package/dist/analytics.d.ts +89 -0
  11. package/dist/analytics.d.ts.map +1 -0
  12. package/dist/analytics.js +49 -0
  13. package/dist/analytics.js.map +1 -0
  14. package/dist/coordinate/CoordinateSystem.d.ts +46 -0
  15. package/dist/coordinate/CoordinateSystem.d.ts.map +1 -0
  16. package/dist/coordinate/CoordinateSystem.js +88 -0
  17. package/dist/coordinate/CoordinateSystem.js.map +1 -0
  18. package/dist/face/FaceMetricsCalculator.d.ts +52 -0
  19. package/dist/face/FaceMetricsCalculator.d.ts.map +1 -0
  20. package/dist/face/FaceMetricsCalculator.js +375 -0
  21. package/dist/face/FaceMetricsCalculator.js.map +1 -0
  22. package/dist/face/FaceSemanticMapper.d.ts +54 -0
  23. package/dist/face/FaceSemanticMapper.d.ts.map +1 -0
  24. package/dist/face/FaceSemanticMapper.js +129 -0
  25. package/dist/face/FaceSemanticMapper.js.map +1 -0
  26. package/dist/face/FaceShapeScorer.d.ts +35 -0
  27. package/dist/face/FaceShapeScorer.d.ts.map +1 -0
  28. package/dist/face/FaceShapeScorer.js +265 -0
  29. package/dist/face/FaceShapeScorer.js.map +1 -0
  30. package/dist/face/feature-extractor.d.ts +46 -0
  31. package/dist/face/feature-extractor.d.ts.map +1 -0
  32. package/dist/face/feature-extractor.js +106 -0
  33. package/dist/face/feature-extractor.js.map +1 -0
  34. package/dist/face/logreg-classifier.d.ts +117 -0
  35. package/dist/face/logreg-classifier.d.ts.map +1 -0
  36. package/dist/face/logreg-classifier.js +304 -0
  37. package/dist/face/logreg-classifier.js.map +1 -0
  38. package/dist/feature-flag.d.ts +43 -0
  39. package/dist/feature-flag.d.ts.map +1 -0
  40. package/dist/feature-flag.js +58 -0
  41. package/dist/feature-flag.js.map +1 -0
  42. package/dist/i18n/index.d.ts +15 -0
  43. package/dist/i18n/index.d.ts.map +1 -0
  44. package/dist/i18n/index.js +91 -0
  45. package/dist/i18n/index.js.map +1 -0
  46. package/dist/index.d.ts +24 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +33 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/manifest/ManifestValidator.d.ts +23 -0
  51. package/dist/manifest/ManifestValidator.d.ts.map +1 -0
  52. package/dist/manifest/ManifestValidator.js +129 -0
  53. package/dist/manifest/ManifestValidator.js.map +1 -0
  54. package/dist/pose/GlassesPoseSolver.d.ts +64 -0
  55. package/dist/pose/GlassesPoseSolver.d.ts.map +1 -0
  56. package/dist/pose/GlassesPoseSolver.js +299 -0
  57. package/dist/pose/GlassesPoseSolver.js.map +1 -0
  58. package/dist/privacy/PrivacyGuard.d.ts +44 -0
  59. package/dist/privacy/PrivacyGuard.d.ts.map +1 -0
  60. package/dist/privacy/PrivacyGuard.js +105 -0
  61. package/dist/privacy/PrivacyGuard.js.map +1 -0
  62. package/dist/quality/QualityGate.d.ts +22 -0
  63. package/dist/quality/QualityGate.d.ts.map +1 -0
  64. package/dist/quality/QualityGate.js +161 -0
  65. package/dist/quality/QualityGate.js.map +1 -0
  66. package/dist/smoothing/PoseSmoothing.d.ts +37 -0
  67. package/dist/smoothing/PoseSmoothing.d.ts.map +1 -0
  68. package/dist/smoothing/PoseSmoothing.js +146 -0
  69. package/dist/smoothing/PoseSmoothing.js.map +1 -0
  70. package/dist/types/index.d.ts +444 -0
  71. package/dist/types/index.d.ts.map +1 -0
  72. package/dist/types/index.js +8 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/utils/errors.d.ts +7 -0
  75. package/dist/utils/errors.d.ts.map +1 -0
  76. package/dist/utils/errors.js +20 -0
  77. package/dist/utils/errors.js.map +1 -0
  78. package/dist/utils/index.d.ts +2 -0
  79. package/dist/utils/index.d.ts.map +1 -0
  80. package/dist/utils/index.js +2 -0
  81. package/dist/utils/index.js.map +1 -0
  82. package/dist/utils/math.d.ts +40 -0
  83. package/dist/utils/math.d.ts.map +1 -0
  84. package/dist/utils/math.js +149 -0
  85. package/dist/utils/math.js.map +1 -0
  86. package/package.json +31 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Analytics event types for face-shape analysis (spec §12).
3
+ *
4
+ * The host application wires these events into its analytics pipeline
5
+ * (e.g. GA4). Events carry algorithm metadata and outcome signals only —
6
+ * NEVER photos, base64, landmarks, or any reversible biometric data.
7
+ */
8
+ /**
9
+ * Create a no-op reporter (default when analytics is disabled).
10
+ * Useful as a safe default in tests and when `privacy.allowAnalytics` is false.
11
+ */
12
+ export function noopReporter() {
13
+ return () => {
14
+ /* no-op */
15
+ };
16
+ }
17
+ /**
18
+ * Create a reporter that buffers events and flushes them via the provided
19
+ * sink. Useful for batching in production.
20
+ */
21
+ export function createBufferedReporter(sink, flushIntervalMs = 5000) {
22
+ let buffer = [];
23
+ let timer = null;
24
+ if (flushIntervalMs > 0) {
25
+ timer = setInterval(() => {
26
+ if (buffer.length > 0) {
27
+ sink(buffer);
28
+ buffer = [];
29
+ }
30
+ }, flushIntervalMs);
31
+ }
32
+ return {
33
+ reporter: (event) => {
34
+ buffer.push(event);
35
+ },
36
+ flush: () => {
37
+ if (buffer.length > 0) {
38
+ sink(buffer);
39
+ buffer = [];
40
+ }
41
+ },
42
+ destroy: () => {
43
+ if (timer)
44
+ clearInterval(timer);
45
+ timer = null;
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgGH;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,GAAG,EAAE;QACV,WAAW;IACb,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAoD,EACpD,eAAe,GAAG,IAAI;IAEtB,IAAI,MAAM,GAAiC,EAAE,CAAC;IAC9C,IAAI,KAAK,GAA0C,IAAI,CAAC;IAExD,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YACvB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,CAAC;gBACb,MAAM,GAAG,EAAE,CAAC;YACd,CAAC;QACH,CAAC,EAAE,eAAe,CAAC,CAAC;IACtB,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,CAAC;gBACb,MAAM,GAAG,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,KAAK;gBAAE,aAAa,CAAC,KAAK,CAAC,CAAC;YAChC,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { CoordinateSystemType, Point2D, Point3D } from "../types/index.js";
2
+ /**
3
+ * Coordinate system conversions for VisuTry SDK.
4
+ *
5
+ * Four coordinate systems are used throughout the SDK:
6
+ *
7
+ * - `pixel-image` origin top-left, x right, y down. Raw video / image frames.
8
+ * - `normalized-image` origin top-left, x∈[0,1] right, y∈[0,1] down. SDK-internal face results.
9
+ * - `render-world` origin scene-center, x right, y up. Glasses model rendering.
10
+ * - `glasses-local` origin model origin, x right, y up, z temple. Single glasses model.
11
+ *
12
+ * Adapters always emit `NormalizedFaceResult`. The core operates exclusively in
13
+ * normalized-image space. The renderer only ever receives `GlassesPose`, never raw
14
+ * landmarks.
15
+ */
16
+ export declare class CoordinateSystem {
17
+ /** Convert a pixel-space point to normalized image space. */
18
+ static pixelToNormalized(point: Point2D | Point3D, width: number, height: number): Point3D;
19
+ /** Convert a batch of pixel points to normalized image space. */
20
+ static pixelToNormalizedBatch(points: Point3D[], width: number, height: number): Point3D[];
21
+ /** Convert a normalized image point back to pixel space. */
22
+ static normalizedToPixel(point: Point3D, width: number, height: number): Point3D;
23
+ /**
24
+ * Convert a normalized image point (y down) into render-world space (y up),
25
+ * centering the origin at the image center. This is used when the renderer
26
+ * needs to place auxiliary geometry; the primary glasses pose is produced by
27
+ * `GlassesPoseSolver` which handles its own mapping.
28
+ *
29
+ * The mapping is: x_w = (x_n - 0.5) * aspectScale, y_w = (0.5 - y_n), z kept.
30
+ */
31
+ static normalizedToRenderWorld(point: Point3D, aspectRatio?: number): Point3D;
32
+ /**
33
+ * Convert render-world (y up) back to normalized image (y down).
34
+ */
35
+ static renderWorldToNormalized(point: Point3D, aspectRatio?: number): Point3D;
36
+ /**
37
+ * Validate that a value lies within the normalized unit square.
38
+ * Returns the clamped value and whether clamping was needed.
39
+ */
40
+ static clampNormalized(value: number): {
41
+ value: number;
42
+ clamped: boolean;
43
+ };
44
+ static describe(type: CoordinateSystemType): string;
45
+ }
46
+ //# sourceMappingURL=CoordinateSystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoordinateSystem.d.ts","sourceRoot":"","sources":["../../src/coordinate/CoordinateSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEhF;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAgB;IAC3B,6DAA6D;IAC7D,MAAM,CAAC,iBAAiB,CACtB,KAAK,EAAE,OAAO,GAAG,OAAO,EACxB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO;IAUV,iEAAiE;IACjE,MAAM,CAAC,sBAAsB,CAC3B,MAAM,EAAE,OAAO,EAAE,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,EAAE;IAIZ,4DAA4D;IAC5D,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAQhF;;;;;;;OAOG;IACH,MAAM,CAAC,uBAAuB,CAC5B,KAAK,EAAE,OAAO,EACd,WAAW,SAAI,GACd,OAAO;IAQV;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,OAAO;IASxE;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAM1E,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM;CAYpD"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Coordinate system conversions for VisuTry SDK.
3
+ *
4
+ * Four coordinate systems are used throughout the SDK:
5
+ *
6
+ * - `pixel-image` origin top-left, x right, y down. Raw video / image frames.
7
+ * - `normalized-image` origin top-left, x∈[0,1] right, y∈[0,1] down. SDK-internal face results.
8
+ * - `render-world` origin scene-center, x right, y up. Glasses model rendering.
9
+ * - `glasses-local` origin model origin, x right, y up, z temple. Single glasses model.
10
+ *
11
+ * Adapters always emit `NormalizedFaceResult`. The core operates exclusively in
12
+ * normalized-image space. The renderer only ever receives `GlassesPose`, never raw
13
+ * landmarks.
14
+ */
15
+ export class CoordinateSystem {
16
+ /** Convert a pixel-space point to normalized image space. */
17
+ static pixelToNormalized(point, width, height) {
18
+ const w = width || 1;
19
+ const h = height || 1;
20
+ return {
21
+ x: point.x / w,
22
+ y: point.y / h,
23
+ z: "z" in point && point.z !== undefined ? point.z / Math.max(w, h) : 0,
24
+ };
25
+ }
26
+ /** Convert a batch of pixel points to normalized image space. */
27
+ static pixelToNormalizedBatch(points, width, height) {
28
+ return points.map((p) => this.pixelToNormalized(p, width, height));
29
+ }
30
+ /** Convert a normalized image point back to pixel space. */
31
+ static normalizedToPixel(point, width, height) {
32
+ return {
33
+ x: point.x * width,
34
+ y: point.y * height,
35
+ z: point.z * Math.max(width, height),
36
+ };
37
+ }
38
+ /**
39
+ * Convert a normalized image point (y down) into render-world space (y up),
40
+ * centering the origin at the image center. This is used when the renderer
41
+ * needs to place auxiliary geometry; the primary glasses pose is produced by
42
+ * `GlassesPoseSolver` which handles its own mapping.
43
+ *
44
+ * The mapping is: x_w = (x_n - 0.5) * aspectScale, y_w = (0.5 - y_n), z kept.
45
+ */
46
+ static normalizedToRenderWorld(point, aspectRatio = 1) {
47
+ return {
48
+ x: (point.x - 0.5) * aspectRatio,
49
+ y: 0.5 - point.y,
50
+ z: point.z,
51
+ };
52
+ }
53
+ /**
54
+ * Convert render-world (y up) back to normalized image (y down).
55
+ */
56
+ static renderWorldToNormalized(point, aspectRatio = 1) {
57
+ const sx = aspectRatio || 1;
58
+ return {
59
+ x: point.x / sx + 0.5,
60
+ y: 0.5 - point.y,
61
+ z: point.z,
62
+ };
63
+ }
64
+ /**
65
+ * Validate that a value lies within the normalized unit square.
66
+ * Returns the clamped value and whether clamping was needed.
67
+ */
68
+ static clampNormalized(value) {
69
+ if (value < 0)
70
+ return { value: 0, clamped: true };
71
+ if (value > 1)
72
+ return { value: 1, clamped: true };
73
+ return { value, clamped: false };
74
+ }
75
+ static describe(type) {
76
+ switch (type) {
77
+ case "pixel-image":
78
+ return "Pixel Image — origin top-left, x right, y down. Raw frames.";
79
+ case "normalized-image":
80
+ return "Normalized Image — origin top-left, x∈[0,1] right, y∈[0,1] down. SDK internal.";
81
+ case "render-world":
82
+ return "Render World — origin scene-center, x right, y up. Glasses rendering.";
83
+ case "glasses-local":
84
+ return "Glasses Local — origin model origin, x right, y up, z temple. Single model.";
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=CoordinateSystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoordinateSystem.js","sourceRoot":"","sources":["../../src/coordinate/CoordinateSystem.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,gBAAgB;IAC3B,6DAA6D;IAC7D,MAAM,CAAC,iBAAiB,CACtB,KAAwB,EACxB,KAAa,EACb,MAAc;QAEd,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;QACtB,OAAO;YACL,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC;YACd,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC;YACd,CAAC,EAAE,GAAG,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACxE,CAAC;IACJ,CAAC;IAED,iEAAiE;IACjE,MAAM,CAAC,sBAAsB,CAC3B,MAAiB,EACjB,KAAa,EACb,MAAc;QAEd,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,4DAA4D;IAC5D,MAAM,CAAC,iBAAiB,CAAC,KAAc,EAAE,KAAa,EAAE,MAAc;QACpE,OAAO;YACL,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,KAAK;YAClB,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,MAAM;YACnB,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;SACrC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,uBAAuB,CAC5B,KAAc,EACd,WAAW,GAAG,CAAC;QAEf,OAAO;YACL,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,WAAW;YAChC,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;YAChB,CAAC,EAAE,KAAK,CAAC,CAAC;SACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAAC,KAAc,EAAE,WAAW,GAAG,CAAC;QAC5D,MAAM,EAAE,GAAG,WAAW,IAAI,CAAC,CAAC;QAC5B,OAAO;YACL,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,GAAG;YACrB,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;YAChB,CAAC,EAAE,KAAK,CAAC,CAAC;SACX,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,KAAa;QAClC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,IAA0B;QACxC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,aAAa;gBAChB,OAAO,6DAA6D,CAAC;YACvE,KAAK,kBAAkB;gBACrB,OAAO,gFAAgF,CAAC;YAC1F,KAAK,cAAc;gBACjB,OAAO,uEAAuE,CAAC;YACjF,KAAK,eAAe;gBAClB,OAAO,6EAA6E,CAAC;QACzF,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,52 @@
1
+ import type { FaceMetrics, FaceSemanticPoints, NormalizedFaceResult } from "../types/index.js";
2
+ /**
3
+ * Computes geometric `FaceMetrics` from `FaceSemanticPoints`.
4
+ *
5
+ * Design rules (spec §12.2):
6
+ * - All distances use normalized coordinates.
7
+ * - Missing points are tolerated — a metric is simply left undefined / the
8
+ * measurement quality degrades. The calculator never throws on missing data.
9
+ * - Every result carries a `measurementQuality` in [0,1].
10
+ * - Multi-frame analysis aggregates via median (distances) / trimmed mean (ratios).
11
+ */
12
+ export declare class FaceMetricsCalculator {
13
+ /**
14
+ * Compute metrics for a single normalized face result.
15
+ */
16
+ compute(face: NormalizedFaceResult): FaceMetrics;
17
+ /**
18
+ * Compute metrics directly from semantic points. This is the core entry
19
+ * point — `NormalizedFaceResult` is only a thin wrapper around it.
20
+ */
21
+ computeFromSemantic(s: FaceSemanticPoints): FaceMetrics;
22
+ /**
23
+ * Aggregate metrics across multiple frames (spec §12.3). Distances use the
24
+ * median; ratios are recomputed from medians to stay internally consistent;
25
+ * `measurementQuality` blends per-frame quality with cross-frame stability.
26
+ */
27
+ aggregate(frames: NormalizedFaceResult[]): FaceMetrics;
28
+ private safeDistance;
29
+ /**
30
+ * 2D distance (x, y only — no z). Used for visutry-compatible ratios.
31
+ */
32
+ private safeDistance2D;
33
+ /**
34
+ * Compute visutry-compatible ratios using 2D distances.
35
+ * This mirrors visutry's analyzeFaceLandmarks() exactly:
36
+ * - faceAspectRatio = faceHeight / faceWidth (H/W, 2D)
37
+ * - cheekToFaceWidth = cheekWidth / faceWidth
38
+ * - jawToCheekWidth = jawWidth / cheekWidth
39
+ * - foreheadToCheekWidth = foreheadWidth / cheekWidth
40
+ * - eyeLineTiltDeg = atan2(dy, dx) * 180/PI
41
+ * - symmetryOffset = |noseBridge.x - faceCenterX| / faceWidth
42
+ * - noseBridgeToFaceWidth = noseBridgeWidth / faceWidth
43
+ */
44
+ private computeVisutryRatios;
45
+ private countKeyPoints;
46
+ private computeQuality;
47
+ private classifyChin;
48
+ private stabilityFactor;
49
+ private majorityVote;
50
+ private emptyMetrics;
51
+ }
52
+ //# sourceMappingURL=FaceMetricsCalculator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FaceMetricsCalculator.d.ts","sourceRoot":"","sources":["../../src/face/FaceMetricsCalculator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG/F;;;;;;;;;GASG;AACH,qBAAa,qBAAqB;IAChC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,oBAAoB,GAAG,WAAW;IAIhD;;;OAGG;IACH,mBAAmB,CAAC,CAAC,EAAE,kBAAkB,GAAG,WAAW;IAqHvD;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG,WAAW;IAkGtD,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,oBAAoB;IAwC5B,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,YAAY;CAgBrB"}
@@ -0,0 +1,375 @@
1
+ import { distance2D, distance3D, median, trimmedMean, clamp01 } from "../utils/math.js";
2
+ /**
3
+ * Computes geometric `FaceMetrics` from `FaceSemanticPoints`.
4
+ *
5
+ * Design rules (spec §12.2):
6
+ * - All distances use normalized coordinates.
7
+ * - Missing points are tolerated — a metric is simply left undefined / the
8
+ * measurement quality degrades. The calculator never throws on missing data.
9
+ * - Every result carries a `measurementQuality` in [0,1].
10
+ * - Multi-frame analysis aggregates via median (distances) / trimmed mean (ratios).
11
+ */
12
+ export class FaceMetricsCalculator {
13
+ /**
14
+ * Compute metrics for a single normalized face result.
15
+ */
16
+ compute(face) {
17
+ return this.computeFromSemantic(face.landmarks.semantic);
18
+ }
19
+ /**
20
+ * Compute metrics directly from semantic points. This is the core entry
21
+ * point — `NormalizedFaceResult` is only a thin wrapper around it.
22
+ */
23
+ computeFromSemantic(s) {
24
+ const present = this.countKeyPoints(s);
25
+ // --- Horizontal widths -------------------------------------------------
26
+ const cheekboneWidth = this.safeDistance(s.leftCheek, s.rightCheek);
27
+ const jawWidth = this.safeDistance(s.leftJaw, s.rightJaw);
28
+ const eyeOuterDistance = this.safeDistance(s.leftEyeOuter, s.rightEyeOuter);
29
+ const eyeInnerDistance = this.safeDistance(s.leftEyeInner, s.rightEyeInner);
30
+ const eyeCenterDistance = this.safeDistance(s.leftEyeCenter, s.rightEyeCenter);
31
+ // visutry additions: face outline width, forehead width, nose bridge width
32
+ const faceOutlineWidth = this.safeDistance(s.leftFace, s.rightFace);
33
+ const foreheadWidth = this.safeDistance(s.leftForehead, s.rightForehead);
34
+ const noseBridgeWidth = this.safeDistance(s.noseLeft, s.noseRight);
35
+ // faceWidth: prefer face outline width (widest part, visutry convention);
36
+ // fall back to cheekbone width, then eye outer distance.
37
+ const faceWidth = faceOutlineWidth ?? cheekboneWidth ?? eyeOuterDistance ?? 0;
38
+ // --- Vertical height ---------------------------------------------------
39
+ let faceHeight;
40
+ if (s.foreheadCenter && s.chin) {
41
+ faceHeight = distance3D(s.foreheadCenter, s.chin);
42
+ }
43
+ else if (s.eyesCenter && s.chin) {
44
+ faceHeight = distance3D(s.eyesCenter, s.chin) / 0.55;
45
+ }
46
+ // --- Nose bridge to eye line ------------------------------------------
47
+ let noseBridgeToEyeLine = 0;
48
+ if (s.noseBridge && s.eyesCenter) {
49
+ noseBridgeToEyeLine = Math.abs(s.noseBridge.y - s.eyesCenter.y);
50
+ }
51
+ // --- Ratios ------------------------------------------------------------
52
+ const widthHeightRatio = faceHeight && faceHeight > 1e-6 ? faceWidth / faceHeight : 0;
53
+ const jawCheekRatio = jawWidth !== undefined && cheekboneWidth && cheekboneWidth > 1e-6
54
+ ? jawWidth / cheekboneWidth
55
+ : 0;
56
+ const foreheadCheekRatio = foreheadWidth !== undefined && cheekboneWidth && cheekboneWidth > 1e-6
57
+ ? foreheadWidth / cheekboneWidth
58
+ : undefined;
59
+ // --- Eye line tilt (degrees) ------------------------------------------
60
+ // Angle of the line connecting left/right eye outer corners relative to
61
+ // horizontal. Positive = right side higher. Used for photo quality check.
62
+ let eyeLineTiltDeg;
63
+ if (s.leftEyeOuter && s.rightEyeOuter) {
64
+ const dx = s.rightEyeOuter.x - s.leftEyeOuter.x;
65
+ const dy = s.rightEyeOuter.y - s.leftEyeOuter.y;
66
+ if (Math.abs(dx) > 1e-6) {
67
+ eyeLineTiltDeg = Math.atan2(dy, dx) * (180 / Math.PI);
68
+ }
69
+ }
70
+ // --- Symmetry offset ---------------------------------------------------
71
+ // Nose bridge deviation from face center (midpoint of leftFace/rightFace).
72
+ // 0 = perfectly symmetric, larger = more offset.
73
+ let symmetryOffset;
74
+ if (s.noseBridge && s.leftFace && s.rightFace && faceWidth > 1e-6) {
75
+ const faceCenterX = (s.leftFace.x + s.rightFace.x) / 2;
76
+ symmetryOffset = Math.abs(s.noseBridge.x - faceCenterX) / faceWidth;
77
+ }
78
+ // --- Face span (bounding box max dimension) ----------------------------
79
+ let faceSpan;
80
+ if (s.leftFace && s.rightFace && s.foreheadCenter && s.chin) {
81
+ const w = Math.abs(s.rightFace.x - s.leftFace.x);
82
+ const h = Math.abs(s.chin.y - s.foreheadCenter.y);
83
+ faceSpan = Math.max(w, h);
84
+ }
85
+ // --- Chin type classification (geometric heuristic, width/height aware) -
86
+ const chinType = this.classifyChin(jawCheekRatio, widthHeightRatio, jawWidth, cheekboneWidth, s.chin, s.leftJaw, s.rightJaw);
87
+ // --- Measurement quality ----------------------------------------------
88
+ const measurementQuality = this.computeQuality(present, s);
89
+ // --- visutry-compatible 2D ratios -------------------------------------
90
+ // visutry uses 2D distances (Math.hypot(dx, dy) with no z-component).
91
+ // We compute these separately to ensure exact numerical equivalence.
92
+ const visutry = this.computeVisutryRatios(s);
93
+ return {
94
+ faceWidth,
95
+ faceHeight: faceHeight ?? 0,
96
+ cheekboneWidth: cheekboneWidth ?? 0,
97
+ jawWidth: jawWidth ?? 0,
98
+ foreheadWidth,
99
+ faceOutlineWidth,
100
+ eyeOuterDistance: eyeOuterDistance ?? 0,
101
+ eyeInnerDistance: eyeInnerDistance ?? 0,
102
+ eyeCenterDistance: eyeCenterDistance ?? 0,
103
+ noseBridgeToEyeLine,
104
+ noseBridgeWidth,
105
+ widthHeightRatio,
106
+ jawCheekRatio,
107
+ foreheadCheekRatio,
108
+ eyeLineTiltDeg,
109
+ symmetryOffset,
110
+ faceSpan,
111
+ chinType,
112
+ measurementQuality,
113
+ visutry,
114
+ };
115
+ }
116
+ /**
117
+ * Aggregate metrics across multiple frames (spec §12.3). Distances use the
118
+ * median; ratios are recomputed from medians to stay internally consistent;
119
+ * `measurementQuality` blends per-frame quality with cross-frame stability.
120
+ */
121
+ aggregate(frames) {
122
+ if (frames.length === 0) {
123
+ return this.emptyMetrics();
124
+ }
125
+ if (frames.length === 1) {
126
+ return this.compute(frames[0]);
127
+ }
128
+ const perFrame = frames.map((f) => this.compute(f));
129
+ const pick = (key) => perFrame.map((m) => m[key]).filter((v) => typeof v === "number" && !Number.isNaN(v));
130
+ const faceWidth = median(pick("faceWidth"));
131
+ const faceHeight = median(pick("faceHeight"));
132
+ const cheekboneWidth = median(pick("cheekboneWidth"));
133
+ const jawWidth = median(pick("jawWidth"));
134
+ const eyeOuterDistance = median(pick("eyeOuterDistance"));
135
+ const eyeInnerDistance = median(pick("eyeInnerDistance"));
136
+ const eyeCenterDistance = median(pick("eyeCenterDistance"));
137
+ const noseBridgeToEyeLine = median(pick("noseBridgeToEyeLine"));
138
+ // visutry additions — aggregate optional metrics when available
139
+ const foreheadWidthArr = perFrame.map((m) => m.foreheadWidth).filter((v) => typeof v === "number" && !Number.isNaN(v));
140
+ const faceOutlineWidthArr = perFrame.map((m) => m.faceOutlineWidth).filter((v) => typeof v === "number" && !Number.isNaN(v));
141
+ const noseBridgeWidthArr = perFrame.map((m) => m.noseBridgeWidth).filter((v) => typeof v === "number" && !Number.isNaN(v));
142
+ const eyeLineTiltArr = perFrame.map((m) => m.eyeLineTiltDeg).filter((v) => typeof v === "number" && !Number.isNaN(v));
143
+ const symmetryOffsetArr = perFrame.map((m) => m.symmetryOffset).filter((v) => typeof v === "number" && !Number.isNaN(v));
144
+ const faceSpanArr = perFrame.map((m) => m.faceSpan).filter((v) => typeof v === "number" && !Number.isNaN(v));
145
+ const foreheadWidth = foreheadWidthArr.length > 0 ? median(foreheadWidthArr) : undefined;
146
+ const faceOutlineWidth = faceOutlineWidthArr.length > 0 ? median(faceOutlineWidthArr) : undefined;
147
+ const noseBridgeWidth = noseBridgeWidthArr.length > 0 ? median(noseBridgeWidthArr) : undefined;
148
+ const eyeLineTiltDeg = eyeLineTiltArr.length > 0 ? median(eyeLineTiltArr) : undefined;
149
+ const symmetryOffset = symmetryOffsetArr.length > 0 ? median(symmetryOffsetArr) : undefined;
150
+ const faceSpan = faceSpanArr.length > 0 ? median(faceSpanArr) : undefined;
151
+ const widthHeightRatio = faceHeight > 1e-6 ? faceWidth / faceHeight : 0;
152
+ const jawCheekRatio = cheekboneWidth > 1e-6 ? jawWidth / cheekboneWidth : 0;
153
+ const foreheadCheekRatio = foreheadWidth !== undefined && cheekboneWidth > 1e-6
154
+ ? foreheadWidth / cheekboneWidth
155
+ : undefined;
156
+ const qualities = pick("measurementQuality");
157
+ const avgQuality = trimmedMean(qualities, 0.2);
158
+ // Stability bonus: low variance across frames increases confidence.
159
+ const wds = pick("faceWidth");
160
+ const stability = this.stabilityFactor(wds);
161
+ const measurementQuality = clamp01(avgQuality * 0.6 + stability * 0.4);
162
+ // Chin type: majority vote across frames.
163
+ const chinVotes = perFrame.map((m) => m.chinType);
164
+ const chinType = this.majorityVote(chinVotes);
165
+ // Aggregate visutry-compatible ratios (median of per-frame values)
166
+ const visutryArr = perFrame.map((m) => m.visutry).filter((v) => v !== undefined);
167
+ const visutry = visutryArr.length > 0
168
+ ? {
169
+ faceAspectRatio: median(visutryArr.map((v) => v.faceAspectRatio)),
170
+ cheekToFaceWidth: median(visutryArr.map((v) => v.cheekToFaceWidth)),
171
+ jawToCheekWidth: median(visutryArr.map((v) => v.jawToCheekWidth)),
172
+ foreheadToCheekWidth: median(visutryArr.map((v) => v.foreheadToCheekWidth)),
173
+ eyeLineTiltDeg: median(visutryArr.map((v) => v.eyeLineTiltDeg)),
174
+ symmetryOffset: median(visutryArr.map((v) => v.symmetryOffset)),
175
+ noseBridgeToFaceWidth: median(visutryArr.map((v) => v.noseBridgeToFaceWidth)),
176
+ }
177
+ : undefined;
178
+ return {
179
+ faceWidth,
180
+ faceHeight,
181
+ cheekboneWidth,
182
+ jawWidth,
183
+ foreheadWidth,
184
+ faceOutlineWidth,
185
+ eyeOuterDistance,
186
+ eyeInnerDistance,
187
+ eyeCenterDistance,
188
+ noseBridgeToEyeLine,
189
+ noseBridgeWidth,
190
+ widthHeightRatio,
191
+ jawCheekRatio,
192
+ foreheadCheekRatio,
193
+ eyeLineTiltDeg,
194
+ symmetryOffset,
195
+ faceSpan,
196
+ chinType,
197
+ measurementQuality,
198
+ visutry,
199
+ };
200
+ }
201
+ // -----------------------------------------------------------------------
202
+ // Helpers
203
+ // -----------------------------------------------------------------------
204
+ safeDistance(a, b) {
205
+ if (!a || !b)
206
+ return undefined;
207
+ return distance3D({ x: a.x, y: a.y, z: a.z ?? 0 }, { x: b.x, y: b.y, z: b.z ?? 0 });
208
+ }
209
+ /**
210
+ * 2D distance (x, y only — no z). Used for visutry-compatible ratios.
211
+ */
212
+ safeDistance2D(a, b) {
213
+ if (!a || !b)
214
+ return undefined;
215
+ return distance2D({ x: a.x, y: a.y }, { x: b.x, y: b.y });
216
+ }
217
+ /**
218
+ * Compute visutry-compatible ratios using 2D distances.
219
+ * This mirrors visutry's analyzeFaceLandmarks() exactly:
220
+ * - faceAspectRatio = faceHeight / faceWidth (H/W, 2D)
221
+ * - cheekToFaceWidth = cheekWidth / faceWidth
222
+ * - jawToCheekWidth = jawWidth / cheekWidth
223
+ * - foreheadToCheekWidth = foreheadWidth / cheekWidth
224
+ * - eyeLineTiltDeg = atan2(dy, dx) * 180/PI
225
+ * - symmetryOffset = |noseBridge.x - faceCenterX| / faceWidth
226
+ * - noseBridgeToFaceWidth = noseBridgeWidth / faceWidth
227
+ */
228
+ computeVisutryRatios(s) {
229
+ const required = [s.foreheadCenter, s.chin, s.leftFace, s.rightFace,
230
+ s.leftCheek, s.rightCheek, s.leftJaw, s.rightJaw,
231
+ s.leftForehead, s.rightForehead, s.leftEyeOuter, s.rightEyeOuter,
232
+ s.noseLeft, s.noseRight, s.noseBridge];
233
+ if (required.some((p) => !p))
234
+ return undefined;
235
+ // 2D distances — visutry multiplies by imageWidth/imageHeight but since
236
+ // these are ratios, the scaling cancels out. We compute with normalized
237
+ // coordinates directly.
238
+ const faceHeight = this.safeDistance2D(s.foreheadCenter, s.chin);
239
+ const faceWidth = this.safeDistance2D(s.leftFace, s.rightFace);
240
+ const cheekWidth = this.safeDistance2D(s.leftCheek, s.rightCheek);
241
+ const jawWidth = this.safeDistance2D(s.leftJaw, s.rightJaw);
242
+ const foreheadWidth = this.safeDistance2D(s.leftForehead, s.rightForehead);
243
+ const noseBridgeWidth = this.safeDistance2D(s.noseLeft, s.noseRight);
244
+ if (faceHeight <= 0 || faceWidth <= 0 || cheekWidth <= 0)
245
+ return undefined;
246
+ // Eye line tilt — visutry uses atan2(dy*H, dx*W). With normalized coords
247
+ // (W=H=1), this is atan2(dy, dx).
248
+ const dx = s.rightEyeOuter.x - s.leftEyeOuter.x;
249
+ const dy = s.rightEyeOuter.y - s.leftEyeOuter.y;
250
+ const eyeLineTiltDeg = Math.atan2(dy, dx) * (180 / Math.PI);
251
+ // Symmetry offset
252
+ const faceCenterX = (s.leftFace.x + s.rightFace.x) / 2;
253
+ const symmetryOffset = Math.abs(s.noseBridge.x - faceCenterX) / faceWidth;
254
+ return {
255
+ faceAspectRatio: faceHeight / faceWidth,
256
+ cheekToFaceWidth: cheekWidth / faceWidth,
257
+ jawToCheekWidth: jawWidth / cheekWidth,
258
+ foreheadToCheekWidth: foreheadWidth / cheekWidth,
259
+ eyeLineTiltDeg,
260
+ symmetryOffset,
261
+ noseBridgeToFaceWidth: noseBridgeWidth / faceWidth,
262
+ };
263
+ }
264
+ countKeyPoints(s) {
265
+ const keys = [
266
+ "leftEyeOuter",
267
+ "leftEyeInner",
268
+ "rightEyeInner",
269
+ "rightEyeOuter",
270
+ "leftEyeCenter",
271
+ "rightEyeCenter",
272
+ "eyesCenter",
273
+ "noseBridge",
274
+ "noseTip",
275
+ "chin",
276
+ "leftCheek",
277
+ "rightCheek",
278
+ "leftJaw",
279
+ "rightJaw",
280
+ "leftBrowCenter",
281
+ "rightBrowCenter",
282
+ "foreheadCenter",
283
+ // visutry additions
284
+ "leftFace",
285
+ "rightFace",
286
+ "leftForehead",
287
+ "rightForehead",
288
+ "noseLeft",
289
+ "noseRight",
290
+ ];
291
+ let count = 0;
292
+ for (const k of keys)
293
+ if (s[k])
294
+ count++;
295
+ return count;
296
+ }
297
+ computeQuality(present, s) {
298
+ // Base quality from coverage of 23 key points.
299
+ const coverage = clamp01(present / 23);
300
+ // Critical points weight: eyes, noseBridge, chin, cheeks, jaw are essential.
301
+ const critical = [
302
+ "leftEyeCenter",
303
+ "rightEyeCenter",
304
+ "eyesCenter",
305
+ "noseBridge",
306
+ "chin",
307
+ "leftCheek",
308
+ "rightCheek",
309
+ "leftJaw",
310
+ "rightJaw",
311
+ ];
312
+ const criticalPresent = critical.filter((k) => s[k]).length;
313
+ const criticalRatio = criticalPresent / critical.length;
314
+ // Blend: critical points matter more than peripheral coverage.
315
+ return clamp01(coverage * 0.35 + criticalRatio * 0.65);
316
+ }
317
+ classifyChin(jawCheekRatio, widthHeightRatio, jawWidth, cheekboneWidth, chin, leftJaw, rightJaw) {
318
+ if (jawWidth === undefined || cheekboneWidth === undefined || !chin || !leftJaw || !rightJaw) {
319
+ return "unknown";
320
+ }
321
+ // A pointed chin tapers strongly: jaw much narrower than cheekbone.
322
+ if (jawCheekRatio < 0.72) {
323
+ return "pointed";
324
+ }
325
+ // A broad jaw (jaw ≈ cheekbone) is square when proportions are medium and
326
+ // rounded when the face is nearly as wide as it is tall (a round face).
327
+ if (jawCheekRatio >= 0.86) {
328
+ return widthHeightRatio >= 0.9 ? "rounded" : "square";
329
+ }
330
+ // Intermediate taper => rounded.
331
+ return "rounded";
332
+ }
333
+ stabilityFactor(values) {
334
+ if (values.length < 2)
335
+ return 1;
336
+ const m = values.reduce((a, b) => a + b, 0) / values.length;
337
+ if (m < 1e-6)
338
+ return 0.5;
339
+ const variance = values.reduce((a, b) => a + (b - m) * (b - m), 0) / values.length;
340
+ const cv = Math.sqrt(variance) / m; // coefficient of variation
341
+ // cv near 0 => stable (1); cv >= 0.15 => unstable (0).
342
+ return clamp01(1 - cv / 0.15);
343
+ }
344
+ majorityVote(values) {
345
+ const counts = new Map();
346
+ for (const v of values)
347
+ counts.set(v, (counts.get(v) ?? 0) + 1);
348
+ let best = "unknown";
349
+ let bestCount = 0;
350
+ for (const [k, c] of counts) {
351
+ if (c > bestCount) {
352
+ best = k;
353
+ bestCount = c;
354
+ }
355
+ }
356
+ return best;
357
+ }
358
+ emptyMetrics() {
359
+ return {
360
+ faceWidth: 0,
361
+ faceHeight: 0,
362
+ cheekboneWidth: 0,
363
+ jawWidth: 0,
364
+ eyeOuterDistance: 0,
365
+ eyeInnerDistance: 0,
366
+ eyeCenterDistance: 0,
367
+ noseBridgeToEyeLine: 0,
368
+ widthHeightRatio: 0,
369
+ jawCheekRatio: 0,
370
+ chinType: "unknown",
371
+ measurementQuality: 0,
372
+ };
373
+ }
374
+ }
375
+ //# sourceMappingURL=FaceMetricsCalculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FaceMetricsCalculator.js","sourceRoot":"","sources":["../../src/face/FaceMetricsCalculator.ts"],"names":[],"mappings":"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"}