@camstack/addon-vision 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addons/animal-classifier/index.js +999 -822
- package/dist/addons/animal-classifier/index.js.map +1 -1
- package/dist/addons/animal-classifier/index.mjs +242 -7
- package/dist/addons/animal-classifier/index.mjs.map +1 -1
- package/dist/addons/audio-classification/index.js +501 -378
- package/dist/addons/audio-classification/index.js.map +1 -1
- package/dist/addons/audio-classification/index.mjs +224 -4
- package/dist/addons/audio-classification/index.mjs.map +1 -1
- package/dist/addons/bird-global-classifier/index.js +1002 -825
- package/dist/addons/bird-global-classifier/index.js.map +1 -1
- package/dist/addons/bird-global-classifier/index.mjs +248 -7
- package/dist/addons/bird-global-classifier/index.mjs.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.js +1002 -825
- package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
- package/dist/addons/bird-nabirds-classifier/index.mjs +289 -7
- package/dist/addons/bird-nabirds-classifier/index.mjs.map +1 -1
- package/dist/addons/face-detection/index.js +1196 -934
- package/dist/addons/face-detection/index.js.map +1 -1
- package/dist/addons/face-detection/index.mjs +227 -7
- package/dist/addons/face-detection/index.mjs.map +1 -1
- package/dist/addons/face-recognition/index.js +1003 -807
- package/dist/addons/face-recognition/index.js.map +1 -1
- package/dist/addons/face-recognition/index.mjs +197 -6
- package/dist/addons/face-recognition/index.mjs.map +1 -1
- package/dist/addons/motion-detection/index.js +214 -111
- package/dist/addons/motion-detection/index.js.map +1 -1
- package/dist/addons/motion-detection/index.mjs +12 -9
- package/dist/addons/motion-detection/index.mjs.map +1 -1
- package/dist/addons/object-detection/index.js +1287 -1082
- package/dist/addons/object-detection/index.js.map +1 -1
- package/dist/addons/object-detection/index.mjs +373 -7
- package/dist/addons/object-detection/index.mjs.map +1 -1
- package/dist/addons/plate-detection/index.js +1075 -868
- package/dist/addons/plate-detection/index.js.map +1 -1
- package/dist/addons/plate-detection/index.mjs +230 -7
- package/dist/addons/plate-detection/index.mjs.map +1 -1
- package/dist/addons/plate-recognition/index.js +684 -505
- package/dist/addons/plate-recognition/index.js.map +1 -1
- package/dist/addons/plate-recognition/index.mjs +244 -5
- package/dist/addons/plate-recognition/index.mjs.map +1 -1
- package/dist/addons/segmentation-refiner/index.js +967 -790
- package/dist/addons/segmentation-refiner/index.js.map +1 -1
- package/dist/addons/segmentation-refiner/index.mjs +21 -17
- package/dist/addons/segmentation-refiner/index.mjs.map +1 -1
- package/dist/addons/vehicle-classifier/index.js +581 -410
- package/dist/addons/vehicle-classifier/index.js.map +1 -1
- package/dist/addons/vehicle-classifier/index.mjs +20 -16
- package/dist/addons/vehicle-classifier/index.mjs.map +1 -1
- package/dist/chunk-2YMA6QOV.mjs +193 -0
- package/dist/chunk-2YMA6QOV.mjs.map +1 -0
- package/dist/chunk-3IIFBJCD.mjs +45 -0
- package/dist/chunk-BS4DKYGN.mjs +48 -0
- package/dist/{chunk-7DYHXUPZ.mjs.map → chunk-BS4DKYGN.mjs.map} +1 -1
- package/dist/chunk-DE7I3VHO.mjs +106 -0
- package/dist/{chunk-KUO2BVFY.mjs.map → chunk-DE7I3VHO.mjs.map} +1 -1
- package/dist/chunk-F6D2OZ36.mjs +89 -0
- package/dist/chunk-F6D2OZ36.mjs.map +1 -0
- package/dist/chunk-GAOIFQDX.mjs +59 -0
- package/dist/chunk-GAOIFQDX.mjs.map +1 -0
- package/dist/chunk-HUIX2XVR.mjs +159 -0
- package/dist/chunk-HUIX2XVR.mjs.map +1 -0
- package/dist/chunk-K36R6HWY.mjs +51 -0
- package/dist/{chunk-XZ6ZMXXU.mjs.map → chunk-K36R6HWY.mjs.map} +1 -1
- package/dist/chunk-MBTAI3WE.mjs +78 -0
- package/dist/chunk-MBTAI3WE.mjs.map +1 -0
- package/dist/chunk-MGT6RUVX.mjs +423 -0
- package/dist/{chunk-BP7H4NFS.mjs.map → chunk-MGT6RUVX.mjs.map} +1 -1
- package/dist/chunk-PIFS7AIT.mjs +446 -0
- package/dist/{chunk-2IOKI4ES.mjs.map → chunk-PIFS7AIT.mjs.map} +1 -1
- package/dist/chunk-WG66JYYW.mjs +116 -0
- package/dist/{chunk-22BHCDT5.mjs.map → chunk-WG66JYYW.mjs.map} +1 -1
- package/dist/chunk-XD7WGXHZ.mjs +82 -0
- package/dist/{chunk-DUN6XU3N.mjs.map → chunk-XD7WGXHZ.mjs.map} +1 -1
- package/dist/chunk-YYDM6V2F.mjs +113 -0
- package/dist/{chunk-BR2FPGOX.mjs.map → chunk-YYDM6V2F.mjs.map} +1 -1
- package/dist/chunk-ZK7P3TZN.mjs +286 -0
- package/dist/chunk-ZK7P3TZN.mjs.map +1 -0
- package/dist/index.js +4443 -3924
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2698 -250
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-22BHCDT5.mjs +0 -101
- package/dist/chunk-2IOKI4ES.mjs +0 -335
- package/dist/chunk-7DYHXUPZ.mjs +0 -36
- package/dist/chunk-BJTO5JO5.mjs +0 -11
- package/dist/chunk-BP7H4NFS.mjs +0 -412
- package/dist/chunk-BR2FPGOX.mjs +0 -98
- package/dist/chunk-D6WEHN33.mjs +0 -276
- package/dist/chunk-D6WEHN33.mjs.map +0 -1
- package/dist/chunk-DRYFGARD.mjs +0 -289
- package/dist/chunk-DRYFGARD.mjs.map +0 -1
- package/dist/chunk-DUN6XU3N.mjs +0 -72
- package/dist/chunk-ESLHNWWE.mjs +0 -387
- package/dist/chunk-ESLHNWWE.mjs.map +0 -1
- package/dist/chunk-JUQEW6ON.mjs +0 -256
- package/dist/chunk-JUQEW6ON.mjs.map +0 -1
- package/dist/chunk-KUO2BVFY.mjs +0 -90
- package/dist/chunk-R5J3WAUI.mjs +0 -645
- package/dist/chunk-R5J3WAUI.mjs.map +0 -1
- package/dist/chunk-XZ6ZMXXU.mjs +0 -39
- package/dist/chunk-YPU4WTXZ.mjs +0 -269
- package/dist/chunk-YPU4WTXZ.mjs.map +0 -1
- package/dist/chunk-YUCD2TFH.mjs +0 -242
- package/dist/chunk-YUCD2TFH.mjs.map +0 -1
- package/dist/chunk-ZTJENCFC.mjs +0 -379
- package/dist/chunk-ZTJENCFC.mjs.map +0 -1
- package/dist/chunk-ZWYXXCXP.mjs +0 -248
- package/dist/chunk-ZWYXXCXP.mjs.map +0 -1
- /package/dist/{chunk-BJTO5JO5.mjs.map → chunk-3IIFBJCD.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/postprocess/scrfd.ts","../src/catalogs/face-detection-models.ts"],"sourcesContent":["import type { SpatialDetection, BoundingBox, Landmark } from '@camstack/types'\nimport { iou, nms } from './yolo.js'\n\nexport interface ScrfdRawOutputs {\n readonly [key: string]: Float32Array\n}\n\nconst STRIDES = [8, 16, 32] as const\nconst NUM_ANCHORS_PER_STRIDE = 2\n\n/** Generate anchor points for a given stride and input size */\nfunction generateAnchors(stride: number, inputSize: number): Array<{ cx: number; cy: number }> {\n const featureSize = Math.ceil(inputSize / stride)\n const anchors: Array<{ cx: number; cy: number }> = []\n for (let y = 0; y < featureSize; y++) {\n for (let x = 0; x < featureSize; x++) {\n for (let k = 0; k < NUM_ANCHORS_PER_STRIDE; k++) {\n anchors.push({\n cx: (x + 0.5) * stride,\n cy: (y + 0.5) * stride,\n })\n }\n }\n }\n return anchors\n}\n\nexport function scrfdPostprocess(\n outputs: ScrfdRawOutputs,\n confidence: number,\n inputSize: number,\n originalWidth: number,\n originalHeight: number,\n): SpatialDetection[] {\n // Scale factor from letterbox (assume square crop, so same scale both axes)\n const scaleX = originalWidth / inputSize\n const scaleY = originalHeight / inputSize\n\n interface Candidate {\n readonly bbox: BoundingBox\n readonly score: number\n readonly landmarks?: readonly Landmark[]\n }\n\n const candidates: Candidate[] = []\n\n for (const stride of STRIDES) {\n const scoreKey = Object.keys(outputs).find((k) => k.includes(`score_${stride}`) || k.includes(`_${stride}_score`))\n const bboxKey = Object.keys(outputs).find((k) => k.includes(`bbox_${stride}`) || k.includes(`_${stride}_bbox`))\n const kpsKey = Object.keys(outputs).find((k) => k.includes(`kps_${stride}`) || k.includes(`_${stride}_kps`))\n\n if (!scoreKey || !bboxKey) continue\n\n const scores = outputs[scoreKey]!\n const bboxes = outputs[bboxKey]!\n const kps = kpsKey ? outputs[kpsKey] : undefined\n const anchors = generateAnchors(stride, inputSize)\n\n const n = anchors.length\n\n for (let i = 0; i < n; i++) {\n const score = scores[i]!\n if (score < confidence) continue\n\n const anchor = anchors[i]!\n\n // Bboxes are relative to the anchor center in stride units, scaled by stride\n const x1 = anchor.cx - bboxes[i * 4]! * stride\n const y1 = anchor.cy - bboxes[i * 4 + 1]! * stride\n const x2 = anchor.cx + bboxes[i * 4 + 2]! * stride\n const y2 = anchor.cy + bboxes[i * 4 + 3]! * stride\n\n const bbox: BoundingBox = {\n x: x1 * scaleX,\n y: y1 * scaleY,\n w: (x2 - x1) * scaleX,\n h: (y2 - y1) * scaleY,\n }\n\n let landmarks: readonly Landmark[] | undefined\n if (kps) {\n const pts: Landmark[] = []\n for (let p = 0; p < 5; p++) {\n pts.push({\n x: (anchor.cx + kps[i * 10 + p * 2]! * stride) * scaleX,\n y: (anchor.cy + kps[i * 10 + p * 2 + 1]! * stride) * scaleY,\n })\n }\n landmarks = pts\n }\n\n candidates.push({ bbox, score, landmarks })\n }\n }\n\n if (candidates.length === 0) return []\n\n const keptIndices = nms(candidates, 0.45)\n\n return keptIndices.map((idx) => {\n const { bbox, score, landmarks } = candidates[idx]!\n return {\n class: 'face',\n originalClass: 'face',\n score,\n bbox,\n ...(landmarks ? { landmarks } : {}),\n } satisfies SpatialDetection\n })\n}\n","import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst FACE_LABELS: readonly LabelDefinition[] = [\n { id: 'face', name: 'Face' },\n] as const\n\nexport const FACE_DETECTION_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'scrfd-500m',\n name: 'SCRFD 500M',\n description: 'SCRFD 500M — ultra-lightweight face detector',\n inputSize: { width: 640, height: 640 },\n labels: FACE_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/onnx/camstack-scrfd-500m.onnx'),\n sizeMB: 2.2,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/coreml/camstack-scrfd-500m.mlpackage'),\n sizeMB: 1.2,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/openvino/camstack-scrfd-500m.xml'),\n sizeMB: 1.3,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'scrfd-2.5g',\n name: 'SCRFD 2.5G',\n description: 'SCRFD 2.5G — balanced face detection model',\n inputSize: { width: 640, height: 640 },\n labels: FACE_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/onnx/camstack-scrfd-2.5g.onnx'),\n sizeMB: 3.1,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/coreml/camstack-scrfd-2.5g.mlpackage'),\n sizeMB: 1.7,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/openvino/camstack-scrfd-2.5g.xml'),\n sizeMB: 1.8,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'scrfd-10g',\n name: 'SCRFD 10G',\n description: 'SCRFD 10G — high-accuracy face detector',\n inputSize: { width: 640, height: 640 },\n labels: FACE_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/onnx/camstack-scrfd-10g.onnx'),\n sizeMB: 16,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/coreml/camstack-scrfd-10g.mlpackage'),\n sizeMB: 8.2,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'faceDetection/scrfd/openvino/camstack-scrfd-10g.xml'),\n sizeMB: 8.3,\n runtimes: ['python'],\n },\n },\n },\n] as const\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
+
mod
|
|
36
|
+
));
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
__require,
|
|
40
|
+
__commonJS,
|
|
41
|
+
__export,
|
|
42
|
+
__reExport,
|
|
43
|
+
__toESM
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=chunk-3IIFBJCD.mjs.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
require_object_detection_models
|
|
3
|
+
} from "./chunk-MGT6RUVX.mjs";
|
|
4
|
+
import {
|
|
5
|
+
__commonJS,
|
|
6
|
+
__require
|
|
7
|
+
} from "./chunk-3IIFBJCD.mjs";
|
|
8
|
+
|
|
9
|
+
// src/catalogs/segmentation-refiner-models.js
|
|
10
|
+
var require_segmentation_refiner_models = __commonJS({
|
|
11
|
+
"src/catalogs/segmentation-refiner-models.js"(exports) {
|
|
12
|
+
"use strict";
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.SEGMENTATION_REFINER_MODELS = void 0;
|
|
15
|
+
var types_1 = __require("@camstack/types");
|
|
16
|
+
var object_detection_models_js_1 = require_object_detection_models();
|
|
17
|
+
var HF_REPO = "camstack/camstack-models";
|
|
18
|
+
var hf = (path) => (0, types_1.hfModelUrl)(HF_REPO, path);
|
|
19
|
+
var MASK_LABELS = [
|
|
20
|
+
{ id: "mask", name: "Segmentation Mask" }
|
|
21
|
+
];
|
|
22
|
+
exports.SEGMENTATION_REFINER_MODELS = [
|
|
23
|
+
{
|
|
24
|
+
id: "u2netp",
|
|
25
|
+
name: "U2-Net Portable",
|
|
26
|
+
description: "U2-Net-P \u2014 ultra-lightweight salient object segmentation (4.7 MB), no prompt needed",
|
|
27
|
+
inputSize: { width: 320, height: 320 },
|
|
28
|
+
labels: MASK_LABELS,
|
|
29
|
+
formats: {
|
|
30
|
+
onnx: { url: hf("segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx"), sizeMB: 5 },
|
|
31
|
+
coreml: {
|
|
32
|
+
url: hf("segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage"),
|
|
33
|
+
sizeMB: 3,
|
|
34
|
+
isDirectory: true,
|
|
35
|
+
files: object_detection_models_js_1.MLPACKAGE_FILES,
|
|
36
|
+
runtimes: ["python"]
|
|
37
|
+
}
|
|
38
|
+
// OpenVINO: not yet converted
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
require_segmentation_refiner_models
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=chunk-BS4DKYGN.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/catalogs/segmentation-refiner-models.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst hf = (path: string) => hfModelUrl(HF_REPO, path)\n\nconst MASK_LABELS: readonly LabelDefinition[] = [\n { id: 'mask', name: 'Segmentation Mask' },\n]\n\nexport const SEGMENTATION_REFINER_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'u2netp',\n name: 'U2-Net Portable',\n description: 'U2-Net-P — ultra-lightweight salient object segmentation (4.7 MB), no prompt needed',\n inputSize: { width: 320, height: 320 },\n labels: MASK_LABELS,\n formats: {\n onnx: { url: hf('segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx'), sizeMB: 5 },\n coreml: {\n url: hf('segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage'),\n sizeMB: 3,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n // OpenVINO: not yet converted\n },\n },\n]\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/catalogs/segmentation-refiner-models.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst hf = (path: string) => hfModelUrl(HF_REPO, path)\n\nconst MASK_LABELS: readonly LabelDefinition[] = [\n { id: 'mask', name: 'Segmentation Mask' },\n]\n\nexport const SEGMENTATION_REFINER_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'u2netp',\n name: 'U2-Net Portable',\n description: 'U2-Net-P — ultra-lightweight salient object segmentation (4.7 MB), no prompt needed',\n inputSize: { width: 320, height: 320 },\n labels: MASK_LABELS,\n formats: {\n onnx: { url: hf('segmentationRefiner/u2netp/onnx/camstack-u2netp.onnx'), sizeMB: 5 },\n coreml: {\n url: hf('segmentationRefiner/u2netp/coreml/camstack-u2netp.mlpackage'),\n sizeMB: 3,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n // OpenVINO: not yet converted\n },\n },\n]\n"],"mappings":";;;;;;;;;;;;;;AACA,QAAA,UAAA,UAAA,iBAAA;AACA,QAAA,+BAAA;AAEA,QAAM,UAAU;AAEhB,QAAM,KAAK,CAAC,UAAiB,GAAA,QAAA,YAAW,SAAS,IAAI;AAErD,QAAM,cAA0C;MAC9C,EAAE,IAAI,QAAQ,MAAM,oBAAmB;;AAG5B,YAAA,8BAA4D;MACvE;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAG;QACpC,QAAQ;QACR,SAAS;UACP,MAAM,EAAE,KAAK,GAAG,sDAAsD,GAAG,QAAQ,EAAC;UAClF,QAAQ;YACN,KAAK,GAAG,6DAA6D;YACrE,QAAQ;YACR,aAAa;YACb,OAAO,6BAAA;YACP,UAAU,CAAC,QAAQ;;;;;;;;","names":[]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__commonJS
|
|
3
|
+
} from "./chunk-3IIFBJCD.mjs";
|
|
4
|
+
|
|
5
|
+
// src/shared/postprocess/yolo.js
|
|
6
|
+
var require_yolo = __commonJS({
|
|
7
|
+
"src/shared/postprocess/yolo.js"(exports) {
|
|
8
|
+
"use strict";
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.iou = iou;
|
|
11
|
+
exports.nms = nms;
|
|
12
|
+
exports.yoloPostprocess = yoloPostprocess;
|
|
13
|
+
function iou(a, b) {
|
|
14
|
+
const ax1 = a.x;
|
|
15
|
+
const ay1 = a.y;
|
|
16
|
+
const ax2 = a.x + a.w;
|
|
17
|
+
const ay2 = a.y + a.h;
|
|
18
|
+
const bx1 = b.x;
|
|
19
|
+
const by1 = b.y;
|
|
20
|
+
const bx2 = b.x + b.w;
|
|
21
|
+
const by2 = b.y + b.h;
|
|
22
|
+
const interX1 = Math.max(ax1, bx1);
|
|
23
|
+
const interY1 = Math.max(ay1, by1);
|
|
24
|
+
const interX2 = Math.min(ax2, bx2);
|
|
25
|
+
const interY2 = Math.min(ay2, by2);
|
|
26
|
+
const interW = Math.max(0, interX2 - interX1);
|
|
27
|
+
const interH = Math.max(0, interY2 - interY1);
|
|
28
|
+
const interArea = interW * interH;
|
|
29
|
+
if (interArea === 0)
|
|
30
|
+
return 0;
|
|
31
|
+
const areaA = a.w * a.h;
|
|
32
|
+
const areaB = b.w * b.h;
|
|
33
|
+
const unionArea = areaA + areaB - interArea;
|
|
34
|
+
return unionArea === 0 ? 0 : interArea / unionArea;
|
|
35
|
+
}
|
|
36
|
+
function nms(boxes, iouThreshold) {
|
|
37
|
+
const indices = boxes.map((_, i) => i).sort((a, b) => boxes[b].score - boxes[a].score);
|
|
38
|
+
const kept = [];
|
|
39
|
+
const suppressed = /* @__PURE__ */ new Set();
|
|
40
|
+
for (const idx of indices) {
|
|
41
|
+
if (suppressed.has(idx))
|
|
42
|
+
continue;
|
|
43
|
+
kept.push(idx);
|
|
44
|
+
for (const other of indices) {
|
|
45
|
+
if (other === idx || suppressed.has(other))
|
|
46
|
+
continue;
|
|
47
|
+
if (iou(boxes[idx].bbox, boxes[other].bbox) > iouThreshold) {
|
|
48
|
+
suppressed.add(other);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return kept;
|
|
53
|
+
}
|
|
54
|
+
function yoloPostprocess(output, numClasses, numBoxes, options) {
|
|
55
|
+
const { confidence, iouThreshold, labels, scale, padX, padY, originalWidth, originalHeight } = options;
|
|
56
|
+
const candidates = [];
|
|
57
|
+
for (let i = 0; i < numBoxes; i++) {
|
|
58
|
+
const cx = output[0 * numBoxes + i];
|
|
59
|
+
const cy = output[1 * numBoxes + i];
|
|
60
|
+
const w = output[2 * numBoxes + i];
|
|
61
|
+
const h = output[3 * numBoxes + i];
|
|
62
|
+
let bestScore = -Infinity;
|
|
63
|
+
let bestClass = 0;
|
|
64
|
+
for (let j = 0; j < numClasses; j++) {
|
|
65
|
+
const score = output[(4 + j) * numBoxes + i];
|
|
66
|
+
if (score > bestScore) {
|
|
67
|
+
bestScore = score;
|
|
68
|
+
bestClass = j;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (bestScore < confidence)
|
|
72
|
+
continue;
|
|
73
|
+
const bbox = {
|
|
74
|
+
x: cx - w / 2,
|
|
75
|
+
y: cy - h / 2,
|
|
76
|
+
w,
|
|
77
|
+
h
|
|
78
|
+
};
|
|
79
|
+
candidates.push({ bbox, score: bestScore, classIdx: bestClass });
|
|
80
|
+
}
|
|
81
|
+
if (candidates.length === 0)
|
|
82
|
+
return [];
|
|
83
|
+
const keptIndices = nms(candidates, iouThreshold);
|
|
84
|
+
return keptIndices.map((idx) => {
|
|
85
|
+
const { bbox, score, classIdx } = candidates[idx];
|
|
86
|
+
const label = labels[classIdx] ?? String(classIdx);
|
|
87
|
+
const x = Math.max(0, Math.min(originalWidth, (bbox.x - padX) / scale));
|
|
88
|
+
const y = Math.max(0, Math.min(originalHeight, (bbox.y - padY) / scale));
|
|
89
|
+
const x2 = Math.max(0, Math.min(originalWidth, (bbox.x + bbox.w - padX) / scale));
|
|
90
|
+
const y2 = Math.max(0, Math.min(originalHeight, (bbox.y + bbox.h - padY) / scale));
|
|
91
|
+
const finalBbox = { x, y, w: x2 - x, h: y2 - y };
|
|
92
|
+
return {
|
|
93
|
+
class: label,
|
|
94
|
+
originalClass: label,
|
|
95
|
+
score,
|
|
96
|
+
bbox: finalBbox
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
require_yolo
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=chunk-DE7I3VHO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/postprocess/yolo.ts"],"sourcesContent":["import type { SpatialDetection, BoundingBox } from '@camstack/types'\n\nexport interface YoloPostprocessOptions {\n readonly confidence: number\n readonly iouThreshold: number\n readonly labels: readonly string[]\n readonly scale: number\n readonly padX: number\n readonly padY: number\n readonly originalWidth: number\n readonly originalHeight: number\n}\n\n/** Calculate IoU between two bounding boxes */\nexport function iou(a: BoundingBox, b: BoundingBox): number {\n const ax1 = a.x\n const ay1 = a.y\n const ax2 = a.x + a.w\n const ay2 = a.y + a.h\n\n const bx1 = b.x\n const by1 = b.y\n const bx2 = b.x + b.w\n const by2 = b.y + b.h\n\n const interX1 = Math.max(ax1, bx1)\n const interY1 = Math.max(ay1, by1)\n const interX2 = Math.min(ax2, bx2)\n const interY2 = Math.min(ay2, by2)\n\n const interW = Math.max(0, interX2 - interX1)\n const interH = Math.max(0, interY2 - interY1)\n const interArea = interW * interH\n\n if (interArea === 0) return 0\n\n const areaA = a.w * a.h\n const areaB = b.w * b.h\n const unionArea = areaA + areaB - interArea\n\n return unionArea === 0 ? 0 : interArea / unionArea\n}\n\n/** Non-maximum suppression — returns indices of kept boxes (sorted by score desc) */\nexport function nms(\n boxes: ReadonlyArray<{ readonly bbox: BoundingBox; readonly score: number }>,\n iouThreshold: number,\n): number[] {\n const indices = boxes\n .map((_, i) => i)\n .sort((a, b) => (boxes[b]!.score) - (boxes[a]!.score))\n\n const kept: number[] = []\n const suppressed = new Set<number>()\n\n for (const idx of indices) {\n if (suppressed.has(idx)) continue\n kept.push(idx)\n for (const other of indices) {\n if (other === idx || suppressed.has(other)) continue\n if (iou(boxes[idx]!.bbox, boxes[other]!.bbox) > iouThreshold) {\n suppressed.add(other)\n }\n }\n }\n\n return kept\n}\n\n/** Full YOLO v8/v9 postprocessing: filter → NMS → scale back to original coords */\nexport function yoloPostprocess(\n output: Float32Array,\n numClasses: number,\n numBoxes: number,\n options: YoloPostprocessOptions,\n): SpatialDetection[] {\n const { confidence, iouThreshold, labels, scale, padX, padY, originalWidth, originalHeight } = options\n\n interface Candidate {\n readonly bbox: BoundingBox\n readonly score: number\n readonly classIdx: number\n }\n\n const candidates: Candidate[] = []\n\n for (let i = 0; i < numBoxes; i++) {\n // YOLO v8/v9 output layout: [1, 4+numClasses, numBoxes] stored row-major\n const cx = output[0 * numBoxes + i]!\n const cy = output[1 * numBoxes + i]!\n const w = output[2 * numBoxes + i]!\n const h = output[3 * numBoxes + i]!\n\n let bestScore = -Infinity\n let bestClass = 0\n\n for (let j = 0; j < numClasses; j++) {\n const score = output[(4 + j) * numBoxes + i]!\n if (score > bestScore) {\n bestScore = score\n bestClass = j\n }\n }\n\n if (bestScore < confidence) continue\n\n // Convert cx,cy,w,h to x,y,w,h (top-left origin)\n const bbox: BoundingBox = {\n x: cx - w / 2,\n y: cy - h / 2,\n w,\n h,\n }\n\n candidates.push({ bbox, score: bestScore, classIdx: bestClass })\n }\n\n if (candidates.length === 0) return []\n\n const keptIndices = nms(candidates, iouThreshold)\n\n return keptIndices.map((idx) => {\n const { bbox, score, classIdx } = candidates[idx]!\n const label = labels[classIdx] ?? String(classIdx)\n\n // Transform from letterbox coords back to original image coords\n const x = Math.max(0, Math.min(originalWidth, (bbox.x - padX) / scale))\n const y = Math.max(0, Math.min(originalHeight, (bbox.y - padY) / scale))\n const x2 = Math.max(0, Math.min(originalWidth, (bbox.x + bbox.w - padX) / scale))\n const y2 = Math.max(0, Math.min(originalHeight, (bbox.y + bbox.h - padY) / scale))\n\n const finalBbox: BoundingBox = { x, y, w: x2 - x, h: y2 - y }\n\n return {\n class: label,\n originalClass: label,\n score,\n bbox: finalBbox,\n } satisfies SpatialDetection\n })\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/shared/postprocess/yolo.ts"],"sourcesContent":["import type { SpatialDetection, BoundingBox } from '@camstack/types'\n\nexport interface YoloPostprocessOptions {\n readonly confidence: number\n readonly iouThreshold: number\n readonly labels: readonly string[]\n readonly scale: number\n readonly padX: number\n readonly padY: number\n readonly originalWidth: number\n readonly originalHeight: number\n}\n\n/** Calculate IoU between two bounding boxes */\nexport function iou(a: BoundingBox, b: BoundingBox): number {\n const ax1 = a.x\n const ay1 = a.y\n const ax2 = a.x + a.w\n const ay2 = a.y + a.h\n\n const bx1 = b.x\n const by1 = b.y\n const bx2 = b.x + b.w\n const by2 = b.y + b.h\n\n const interX1 = Math.max(ax1, bx1)\n const interY1 = Math.max(ay1, by1)\n const interX2 = Math.min(ax2, bx2)\n const interY2 = Math.min(ay2, by2)\n\n const interW = Math.max(0, interX2 - interX1)\n const interH = Math.max(0, interY2 - interY1)\n const interArea = interW * interH\n\n if (interArea === 0) return 0\n\n const areaA = a.w * a.h\n const areaB = b.w * b.h\n const unionArea = areaA + areaB - interArea\n\n return unionArea === 0 ? 0 : interArea / unionArea\n}\n\n/** Non-maximum suppression — returns indices of kept boxes (sorted by score desc) */\nexport function nms(\n boxes: ReadonlyArray<{ readonly bbox: BoundingBox; readonly score: number }>,\n iouThreshold: number,\n): number[] {\n const indices = boxes\n .map((_, i) => i)\n .sort((a, b) => (boxes[b]!.score) - (boxes[a]!.score))\n\n const kept: number[] = []\n const suppressed = new Set<number>()\n\n for (const idx of indices) {\n if (suppressed.has(idx)) continue\n kept.push(idx)\n for (const other of indices) {\n if (other === idx || suppressed.has(other)) continue\n if (iou(boxes[idx]!.bbox, boxes[other]!.bbox) > iouThreshold) {\n suppressed.add(other)\n }\n }\n }\n\n return kept\n}\n\n/** Full YOLO v8/v9 postprocessing: filter → NMS → scale back to original coords */\nexport function yoloPostprocess(\n output: Float32Array,\n numClasses: number,\n numBoxes: number,\n options: YoloPostprocessOptions,\n): SpatialDetection[] {\n const { confidence, iouThreshold, labels, scale, padX, padY, originalWidth, originalHeight } = options\n\n interface Candidate {\n readonly bbox: BoundingBox\n readonly score: number\n readonly classIdx: number\n }\n\n const candidates: Candidate[] = []\n\n for (let i = 0; i < numBoxes; i++) {\n // YOLO v8/v9 output layout: [1, 4+numClasses, numBoxes] stored row-major\n const cx = output[0 * numBoxes + i]!\n const cy = output[1 * numBoxes + i]!\n const w = output[2 * numBoxes + i]!\n const h = output[3 * numBoxes + i]!\n\n let bestScore = -Infinity\n let bestClass = 0\n\n for (let j = 0; j < numClasses; j++) {\n const score = output[(4 + j) * numBoxes + i]!\n if (score > bestScore) {\n bestScore = score\n bestClass = j\n }\n }\n\n if (bestScore < confidence) continue\n\n // Convert cx,cy,w,h to x,y,w,h (top-left origin)\n const bbox: BoundingBox = {\n x: cx - w / 2,\n y: cy - h / 2,\n w,\n h,\n }\n\n candidates.push({ bbox, score: bestScore, classIdx: bestClass })\n }\n\n if (candidates.length === 0) return []\n\n const keptIndices = nms(candidates, iouThreshold)\n\n return keptIndices.map((idx) => {\n const { bbox, score, classIdx } = candidates[idx]!\n const label = labels[classIdx] ?? String(classIdx)\n\n // Transform from letterbox coords back to original image coords\n const x = Math.max(0, Math.min(originalWidth, (bbox.x - padX) / scale))\n const y = Math.max(0, Math.min(originalHeight, (bbox.y - padY) / scale))\n const x2 = Math.max(0, Math.min(originalWidth, (bbox.x + bbox.w - padX) / scale))\n const y2 = Math.max(0, Math.min(originalHeight, (bbox.y + bbox.h - padY) / scale))\n\n const finalBbox: BoundingBox = { x, y, w: x2 - x, h: y2 - y }\n\n return {\n class: label,\n originalClass: label,\n score,\n bbox: finalBbox,\n } satisfies SpatialDetection\n })\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
require_object_detection_models
|
|
3
|
+
} from "./chunk-MGT6RUVX.mjs";
|
|
4
|
+
import {
|
|
5
|
+
__commonJS,
|
|
6
|
+
__require
|
|
7
|
+
} from "./chunk-3IIFBJCD.mjs";
|
|
8
|
+
|
|
9
|
+
// src/shared/postprocess/arcface.js
|
|
10
|
+
var require_arcface = __commonJS({
|
|
11
|
+
"src/shared/postprocess/arcface.js"(exports) {
|
|
12
|
+
"use strict";
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.l2Normalize = l2Normalize;
|
|
15
|
+
exports.cosineSimilarity = cosineSimilarity;
|
|
16
|
+
function l2Normalize(vec) {
|
|
17
|
+
let sumSq = 0;
|
|
18
|
+
for (let i = 0; i < vec.length; i++) {
|
|
19
|
+
sumSq += vec[i] * vec[i];
|
|
20
|
+
}
|
|
21
|
+
const norm = Math.sqrt(sumSq);
|
|
22
|
+
if (norm === 0)
|
|
23
|
+
return new Float32Array(vec.length);
|
|
24
|
+
const out = new Float32Array(vec.length);
|
|
25
|
+
for (let i = 0; i < vec.length; i++) {
|
|
26
|
+
out[i] = vec[i] / norm;
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function cosineSimilarity(a, b) {
|
|
31
|
+
if (a.length !== b.length)
|
|
32
|
+
throw new Error("Embedding length mismatch");
|
|
33
|
+
let dot = 0;
|
|
34
|
+
for (let i = 0; i < a.length; i++) {
|
|
35
|
+
dot += a[i] * b[i];
|
|
36
|
+
}
|
|
37
|
+
return dot;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// src/catalogs/face-recognition-models.js
|
|
43
|
+
var require_face_recognition_models = __commonJS({
|
|
44
|
+
"src/catalogs/face-recognition-models.js"(exports) {
|
|
45
|
+
"use strict";
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.FACE_RECOGNITION_MODELS = void 0;
|
|
48
|
+
var types_1 = __require("@camstack/types");
|
|
49
|
+
var object_detection_models_js_1 = require_object_detection_models();
|
|
50
|
+
var HF_REPO = "camstack/camstack-models";
|
|
51
|
+
var FACE_EMBEDDING_LABELS = [
|
|
52
|
+
{ id: "embedding", name: "Face Embedding" }
|
|
53
|
+
];
|
|
54
|
+
exports.FACE_RECOGNITION_MODELS = [
|
|
55
|
+
{
|
|
56
|
+
id: "arcface-r100",
|
|
57
|
+
name: "ArcFace R100",
|
|
58
|
+
description: "ArcFace ResNet-100 \u2014 high-accuracy face recognition embeddings",
|
|
59
|
+
inputSize: { width: 112, height: 112 },
|
|
60
|
+
inputLayout: "nhwc",
|
|
61
|
+
labels: FACE_EMBEDDING_LABELS,
|
|
62
|
+
formats: {
|
|
63
|
+
onnx: {
|
|
64
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx"),
|
|
65
|
+
sizeMB: 130
|
|
66
|
+
},
|
|
67
|
+
coreml: {
|
|
68
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage"),
|
|
69
|
+
sizeMB: 65,
|
|
70
|
+
isDirectory: true,
|
|
71
|
+
files: object_detection_models_js_1.MLPACKAGE_FILES,
|
|
72
|
+
runtimes: ["python"]
|
|
73
|
+
},
|
|
74
|
+
openvino: {
|
|
75
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "faceRecognition/arcface/openvino/camstack-arcface-r100.xml"),
|
|
76
|
+
sizeMB: 65,
|
|
77
|
+
runtimes: ["python"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
require_arcface,
|
|
87
|
+
require_face_recognition_models
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=chunk-F6D2OZ36.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/postprocess/arcface.ts","../src/catalogs/face-recognition-models.ts"],"sourcesContent":["/** L2 normalize a vector in-place, returning a new Float32Array */\nexport function l2Normalize(vec: Float32Array): Float32Array {\n let sumSq = 0\n for (let i = 0; i < vec.length; i++) {\n sumSq += vec[i]! * vec[i]!\n }\n const norm = Math.sqrt(sumSq)\n if (norm === 0) return new Float32Array(vec.length)\n\n const out = new Float32Array(vec.length)\n for (let i = 0; i < vec.length; i++) {\n out[i] = vec[i]! / norm\n }\n return out\n}\n\n/** Cosine similarity between two embeddings (assumes they are already L2-normalized) */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) throw new Error('Embedding length mismatch')\n let dot = 0\n for (let i = 0; i < a.length; i++) {\n dot += a[i]! * b[i]!\n }\n return dot\n}\n","import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst FACE_EMBEDDING_LABELS: readonly LabelDefinition[] = [\n { id: 'embedding', name: 'Face Embedding' },\n] as const\n\nexport const FACE_RECOGNITION_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'arcface-r100',\n name: 'ArcFace R100',\n description: 'ArcFace ResNet-100 — high-accuracy face recognition embeddings',\n inputSize: { width: 112, height: 112 },\n inputLayout: 'nhwc',\n labels: FACE_EMBEDDING_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/onnx/camstack-arcface-arcface.onnx'),\n sizeMB: 130,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/coreml/camstack-arcface-r100.mlpackage'),\n sizeMB: 65,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'faceRecognition/arcface/openvino/camstack-arcface-r100.xml'),\n sizeMB: 65,\n runtimes: ['python'],\n },\n },\n },\n] as const\n"],"mappings":";;;;;;;;;;;;;AACA,YAAA,cAAA;AAgBA,YAAA,mBAAA;AAhBA,aAAgB,YAAY,KAAiB;AAC3C,UAAI,QAAQ;AACZ,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,iBAAS,IAAI,CAAC,IAAK,IAAI,CAAC;MAC1B;AACA,YAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,UAAI,SAAS;AAAG,eAAO,IAAI,aAAa,IAAI,MAAM;AAElD,YAAM,MAAM,IAAI,aAAa,IAAI,MAAM;AACvC,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAI,CAAC,IAAI,IAAI,CAAC,IAAK;MACrB;AACA,aAAO;IACT;AAGA,aAAgB,iBAAiB,GAAiB,GAAe;AAC/D,UAAI,EAAE,WAAW,EAAE;AAAQ,cAAM,IAAI,MAAM,2BAA2B;AACtE,UAAI,MAAM;AACV,eAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,eAAO,EAAE,CAAC,IAAK,EAAE,CAAC;MACpB;AACA,aAAO;IACT;;;;;;;;;;ACvBA,QAAA,UAAA,UAAA,iBAAA;AACA,QAAA,+BAAA;AAEA,QAAM,UAAU;AAEhB,QAAM,wBAAoD;MACxD,EAAE,IAAI,aAAa,MAAM,iBAAgB;;AAG9B,YAAA,0BAAwD;MACnE;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAG;QACpC,aAAa;QACb,QAAQ;QACR,SAAS;UACP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,4DAA4D;YACrF,QAAQ;;UAEV,QAAQ;YACN,MAAK,GAAA,QAAA,YAAW,SAAS,gEAAgE;YACzF,QAAQ;YACR,aAAa;YACb,OAAO,6BAAA;YACP,UAAU,CAAC,QAAQ;;UAErB,UAAU;YACR,MAAK,GAAA,QAAA,YAAW,SAAS,4DAA4D;YACrF,QAAQ;YACR,UAAU,CAAC,QAAQ;;;;;;;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
require_object_detection_models
|
|
3
|
+
} from "./chunk-MGT6RUVX.mjs";
|
|
4
|
+
import {
|
|
5
|
+
__commonJS,
|
|
6
|
+
__require
|
|
7
|
+
} from "./chunk-3IIFBJCD.mjs";
|
|
8
|
+
|
|
9
|
+
// src/catalogs/plate-detection-models.js
|
|
10
|
+
var require_plate_detection_models = __commonJS({
|
|
11
|
+
"src/catalogs/plate-detection-models.js"(exports) {
|
|
12
|
+
"use strict";
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.PLATE_DETECTION_MODELS = void 0;
|
|
15
|
+
var types_1 = __require("@camstack/types");
|
|
16
|
+
var object_detection_models_js_1 = require_object_detection_models();
|
|
17
|
+
var HF_REPO = "camstack/camstack-models";
|
|
18
|
+
var PLATE_LABELS = [
|
|
19
|
+
{ id: "plate", name: "License Plate" }
|
|
20
|
+
];
|
|
21
|
+
exports.PLATE_DETECTION_MODELS = [
|
|
22
|
+
{
|
|
23
|
+
id: "yolov8n-plate",
|
|
24
|
+
name: "YOLOv8 Nano \u2014 License Plate",
|
|
25
|
+
description: "YOLOv8 Nano fine-tuned for license plate detection",
|
|
26
|
+
inputSize: { width: 640, height: 640 },
|
|
27
|
+
labels: PLATE_LABELS,
|
|
28
|
+
formats: {
|
|
29
|
+
onnx: {
|
|
30
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateDetection/yolov8-plate/onnx/camstack-yolov8n-plate.onnx"),
|
|
31
|
+
sizeMB: 12
|
|
32
|
+
},
|
|
33
|
+
coreml: {
|
|
34
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateDetection/yolov8-plate/coreml/camstack-yolov8n-plate.mlpackage"),
|
|
35
|
+
sizeMB: 5.9,
|
|
36
|
+
isDirectory: true,
|
|
37
|
+
files: object_detection_models_js_1.MLPACKAGE_FILES,
|
|
38
|
+
runtimes: ["python"]
|
|
39
|
+
},
|
|
40
|
+
openvino: {
|
|
41
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateDetection/yolov8-plate/openvino/camstack-yolov8n-plate.xml"),
|
|
42
|
+
sizeMB: 6.1,
|
|
43
|
+
runtimes: ["python"]
|
|
44
|
+
},
|
|
45
|
+
tflite: {
|
|
46
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateDetection/yolov8-plate/tflite/camstack-yolov8n-plate_float32.tflite"),
|
|
47
|
+
sizeMB: 12,
|
|
48
|
+
runtimes: ["python"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
require_plate_detection_models
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=chunk-GAOIFQDX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/catalogs/plate-detection-models.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst PLATE_LABELS: readonly LabelDefinition[] = [\n { id: 'plate', name: 'License Plate' },\n] as const\n\nexport const PLATE_DETECTION_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'yolov8n-plate',\n name: 'YOLOv8 Nano — License Plate',\n description: 'YOLOv8 Nano fine-tuned for license plate detection',\n inputSize: { width: 640, height: 640 },\n labels: PLATE_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'plateDetection/yolov8-plate/onnx/camstack-yolov8n-plate.onnx'),\n sizeMB: 12,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'plateDetection/yolov8-plate/coreml/camstack-yolov8n-plate.mlpackage'),\n sizeMB: 5.9,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'plateDetection/yolov8-plate/openvino/camstack-yolov8n-plate.xml'),\n sizeMB: 6.1,\n runtimes: ['python'],\n },\n tflite: {\n url: hfModelUrl(HF_REPO, 'plateDetection/yolov8-plate/tflite/camstack-yolov8n-plate_float32.tflite'),\n sizeMB: 12,\n runtimes: ['python'],\n },\n },\n },\n] as const\n"],"mappings":";;;;;;;;;;;;;;AACA,QAAA,UAAA,UAAA,iBAAA;AACA,QAAA,+BAAA;AAEA,QAAM,UAAU;AAEhB,QAAM,eAA2C;MAC/C,EAAE,IAAI,SAAS,MAAM,gBAAe;;AAGzB,YAAA,yBAAuD;MAClE;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAG;QACpC,QAAQ;QACR,SAAS;UACP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,8DAA8D;YACvF,QAAQ;;UAEV,QAAQ;YACN,MAAK,GAAA,QAAA,YAAW,SAAS,qEAAqE;YAC9F,QAAQ;YACR,aAAa;YACb,OAAO,6BAAA;YACP,UAAU,CAAC,QAAQ;;UAErB,UAAU;YACR,MAAK,GAAA,QAAA,YAAW,SAAS,iEAAiE;YAC1F,QAAQ;YACR,UAAU,CAAC,QAAQ;;UAErB,QAAQ;YACN,MAAK,GAAA,QAAA,YAAW,SAAS,0EAA0E;YACnG,QAAQ;YACR,UAAU,CAAC,QAAQ;;;;;;;","names":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__commonJS,
|
|
3
|
+
__require
|
|
4
|
+
} from "./chunk-3IIFBJCD.mjs";
|
|
5
|
+
|
|
6
|
+
// src/shared/postprocess/paddleocr.js
|
|
7
|
+
var require_paddleocr = __commonJS({
|
|
8
|
+
"src/shared/postprocess/paddleocr.js"(exports) {
|
|
9
|
+
"use strict";
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ctcDecode = ctcDecode;
|
|
12
|
+
function ctcDecode(output, seqLen, numChars, charset) {
|
|
13
|
+
let totalLogScore = 0;
|
|
14
|
+
const rawIndices = [];
|
|
15
|
+
for (let t = 0; t < seqLen; t++) {
|
|
16
|
+
const offset = t * numChars;
|
|
17
|
+
let bestIdx = 0;
|
|
18
|
+
let bestVal = output[offset];
|
|
19
|
+
for (let c = 1; c < numChars; c++) {
|
|
20
|
+
const val = output[offset + c];
|
|
21
|
+
if (val > bestVal) {
|
|
22
|
+
bestVal = val;
|
|
23
|
+
bestIdx = c;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
rawIndices.push(bestIdx);
|
|
27
|
+
totalLogScore += bestVal;
|
|
28
|
+
}
|
|
29
|
+
const collapsed = [];
|
|
30
|
+
for (let i = 0; i < rawIndices.length; i++) {
|
|
31
|
+
const cur = rawIndices[i];
|
|
32
|
+
if (i === 0 || cur !== rawIndices[i - 1]) {
|
|
33
|
+
collapsed.push(cur);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const filtered = collapsed.filter((idx) => idx !== 0);
|
|
37
|
+
const text = filtered.map((idx) => charset[idx] ?? "").join("");
|
|
38
|
+
const confidence = seqLen > 0 ? totalLogScore / seqLen : 0;
|
|
39
|
+
return { text, confidence };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/catalogs/plate-recognition-models.js
|
|
45
|
+
var require_plate_recognition_models = __commonJS({
|
|
46
|
+
"src/catalogs/plate-recognition-models.js"(exports) {
|
|
47
|
+
"use strict";
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.PLATE_RECOGNITION_MODELS = void 0;
|
|
50
|
+
var types_1 = __require("@camstack/types");
|
|
51
|
+
var HF_REPO = "camstack/camstack-models";
|
|
52
|
+
var PLATE_TEXT_LABELS = [
|
|
53
|
+
{ id: "text", name: "Plate Text" }
|
|
54
|
+
];
|
|
55
|
+
exports.PLATE_RECOGNITION_MODELS = [
|
|
56
|
+
// ── PaddleOCR PP-OCRv5 ────────────────────────────────────────
|
|
57
|
+
{
|
|
58
|
+
id: "paddleocr-latin",
|
|
59
|
+
name: "PaddleOCR Latin",
|
|
60
|
+
description: "PaddleOCR PP-OCRv5 recognition model for Latin-script license plates",
|
|
61
|
+
inputSize: { width: 320, height: 48 },
|
|
62
|
+
labels: PLATE_TEXT_LABELS,
|
|
63
|
+
formats: {
|
|
64
|
+
// ONNX only — PaddleOCR has dynamic dimensions incompatible with CoreML native conversion.
|
|
65
|
+
// On Apple Silicon, ONNX Runtime uses CoreML EP automatically for acceleration.
|
|
66
|
+
onnx: {
|
|
67
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-rec.onnx"),
|
|
68
|
+
sizeMB: 7.5
|
|
69
|
+
},
|
|
70
|
+
openvino: {
|
|
71
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-latin.xml"),
|
|
72
|
+
sizeMB: 4,
|
|
73
|
+
runtimes: ["python"]
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
extraFiles: [
|
|
77
|
+
{
|
|
78
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-dict.txt"),
|
|
79
|
+
filename: "camstack-paddleocr-latin-dict.txt",
|
|
80
|
+
sizeMB: 0.01
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "paddleocr-en",
|
|
86
|
+
name: "PaddleOCR English",
|
|
87
|
+
description: "PaddleOCR PP-OCRv5 recognition model optimized for English license plates",
|
|
88
|
+
inputSize: { width: 320, height: 48 },
|
|
89
|
+
labels: PLATE_TEXT_LABELS,
|
|
90
|
+
formats: {
|
|
91
|
+
onnx: {
|
|
92
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-en-rec.onnx"),
|
|
93
|
+
sizeMB: 7.5
|
|
94
|
+
},
|
|
95
|
+
openvino: {
|
|
96
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/openvino/camstack-paddleocr-en.xml"),
|
|
97
|
+
sizeMB: 4,
|
|
98
|
+
runtimes: ["python"]
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
extraFiles: [
|
|
102
|
+
{
|
|
103
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/paddleocr/onnx/camstack-paddleocr-en-dict.txt"),
|
|
104
|
+
filename: "camstack-paddleocr-en-dict.txt",
|
|
105
|
+
sizeMB: 0.01
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
// ── CRNN-MobileNetV3 (via OnnxTR/docTR) ─────────────────────────
|
|
110
|
+
// Simple CNN+LSTM+CTC architecture — good CoreML compatibility (no dynamic ops)
|
|
111
|
+
{
|
|
112
|
+
id: "crnn-mobilenet-v3-small",
|
|
113
|
+
name: "CRNN MobileNet V3 Small",
|
|
114
|
+
description: "CRNN MobileNetV3-Small \u2014 lightweight text recognition, CoreML compatible via OnnxTR",
|
|
115
|
+
inputSize: { width: 128, height: 32 },
|
|
116
|
+
labels: PLATE_TEXT_LABELS,
|
|
117
|
+
formats: {
|
|
118
|
+
onnx: {
|
|
119
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-small.onnx"),
|
|
120
|
+
sizeMB: 8
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
extraFiles: [
|
|
124
|
+
{
|
|
125
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
|
|
126
|
+
filename: "camstack-crnn-mobilenet-charset.txt",
|
|
127
|
+
sizeMB: 0.01
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "crnn-mobilenet-v3-large",
|
|
133
|
+
name: "CRNN MobileNet V3 Large",
|
|
134
|
+
description: "CRNN MobileNetV3-Large \u2014 higher accuracy text recognition, CoreML compatible",
|
|
135
|
+
inputSize: { width: 128, height: 32 },
|
|
136
|
+
labels: PLATE_TEXT_LABELS,
|
|
137
|
+
formats: {
|
|
138
|
+
onnx: {
|
|
139
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-large.onnx"),
|
|
140
|
+
sizeMB: 17
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
extraFiles: [
|
|
144
|
+
{
|
|
145
|
+
url: (0, types_1.hfModelUrl)(HF_REPO, "plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt"),
|
|
146
|
+
filename: "camstack-crnn-mobilenet-charset.txt",
|
|
147
|
+
sizeMB: 0.01
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export {
|
|
156
|
+
require_paddleocr,
|
|
157
|
+
require_plate_recognition_models
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=chunk-HUIX2XVR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/postprocess/paddleocr.ts","../src/catalogs/plate-recognition-models.ts"],"sourcesContent":["/** Decode CTC output to text.\n *\n * Output shape: [1, seqLen, numChars]\n * Algorithm: argmax per timestep → collapse consecutive duplicates → remove blank (index 0) → join\n */\nexport function ctcDecode(\n output: Float32Array,\n seqLen: number,\n numChars: number,\n charset: readonly string[], // index 0 = blank token\n): { text: string; confidence: number } {\n // Step 1: argmax per timestep + track confidence as mean of selected scores\n let totalLogScore = 0\n const rawIndices: number[] = []\n\n for (let t = 0; t < seqLen; t++) {\n const offset = t * numChars\n let bestIdx = 0\n let bestVal = output[offset]!\n\n for (let c = 1; c < numChars; c++) {\n const val = output[offset + c]!\n if (val > bestVal) {\n bestVal = val\n bestIdx = c\n }\n }\n\n rawIndices.push(bestIdx)\n totalLogScore += bestVal\n }\n\n // Step 2: collapse consecutive duplicates\n const collapsed: number[] = []\n for (let i = 0; i < rawIndices.length; i++) {\n const cur = rawIndices[i]!\n if (i === 0 || cur !== rawIndices[i - 1]) {\n collapsed.push(cur)\n }\n }\n\n // Step 3: remove blank (index 0)\n const filtered = collapsed.filter((idx) => idx !== 0)\n\n // Step 4: join characters\n const text = filtered.map((idx) => charset[idx] ?? '').join('')\n\n const confidence = seqLen > 0 ? totalLogScore / seqLen : 0\n\n return { text, confidence }\n}\n","import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst PLATE_TEXT_LABELS: readonly LabelDefinition[] = [\n { id: 'text', name: 'Plate Text' },\n] as const\n\nexport const PLATE_RECOGNITION_MODELS: readonly ModelCatalogEntry[] = [\n // ── PaddleOCR PP-OCRv5 ────────────────────────────────────────\n {\n id: 'paddleocr-latin',\n name: 'PaddleOCR Latin',\n description: 'PaddleOCR PP-OCRv5 recognition model for Latin-script license plates',\n inputSize: { width: 320, height: 48 },\n labels: PLATE_TEXT_LABELS,\n formats: {\n // ONNX only — PaddleOCR has dynamic dimensions incompatible with CoreML native conversion.\n // On Apple Silicon, ONNX Runtime uses CoreML EP automatically for acceleration.\n onnx: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-rec.onnx'),\n sizeMB: 7.5,\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/openvino/camstack-paddleocr-latin.xml'),\n sizeMB: 4,\n runtimes: ['python'],\n },\n },\n extraFiles: [\n {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/onnx/camstack-paddleocr-latin-dict.txt'),\n filename: 'camstack-paddleocr-latin-dict.txt',\n sizeMB: 0.01,\n },\n ],\n },\n {\n id: 'paddleocr-en',\n name: 'PaddleOCR English',\n description: 'PaddleOCR PP-OCRv5 recognition model optimized for English license plates',\n inputSize: { width: 320, height: 48 },\n labels: PLATE_TEXT_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/onnx/camstack-paddleocr-en-rec.onnx'),\n sizeMB: 7.5,\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/openvino/camstack-paddleocr-en.xml'),\n sizeMB: 4,\n runtimes: ['python'],\n },\n },\n extraFiles: [\n {\n url: hfModelUrl(HF_REPO, 'plateRecognition/paddleocr/onnx/camstack-paddleocr-en-dict.txt'),\n filename: 'camstack-paddleocr-en-dict.txt',\n sizeMB: 0.01,\n },\n ],\n },\n\n // ── CRNN-MobileNetV3 (via OnnxTR/docTR) ─────────────────────────\n // Simple CNN+LSTM+CTC architecture — good CoreML compatibility (no dynamic ops)\n {\n id: 'crnn-mobilenet-v3-small',\n name: 'CRNN MobileNet V3 Small',\n description: 'CRNN MobileNetV3-Small — lightweight text recognition, CoreML compatible via OnnxTR',\n inputSize: { width: 128, height: 32 },\n labels: PLATE_TEXT_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-small.onnx'),\n sizeMB: 8,\n },\n },\n extraFiles: [\n {\n url: hfModelUrl(HF_REPO, 'plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt'),\n filename: 'camstack-crnn-mobilenet-charset.txt',\n sizeMB: 0.01,\n },\n ],\n },\n {\n id: 'crnn-mobilenet-v3-large',\n name: 'CRNN MobileNet V3 Large',\n description: 'CRNN MobileNetV3-Large — higher accuracy text recognition, CoreML compatible',\n inputSize: { width: 128, height: 32 },\n labels: PLATE_TEXT_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'plateRecognition/crnn-mobilenet/onnx/camstack-crnn-mobilenet-v3-large.onnx'),\n sizeMB: 17,\n },\n },\n extraFiles: [\n {\n url: hfModelUrl(HF_REPO, 'plateRecognition/crnn-mobilenet/camstack-crnn-mobilenet-charset.txt'),\n filename: 'camstack-crnn-mobilenet-charset.txt',\n sizeMB: 0.01,\n },\n ],\n },\n] as const\n"],"mappings":";;;;;;;;;;AAKA,YAAA,YAAA;AAAA,aAAgB,UACd,QACA,QACA,UACA,SAA0B;AAG1B,UAAI,gBAAgB;AACpB,YAAM,aAAuB,CAAA;AAE7B,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAM,SAAS,IAAI;AACnB,YAAI,UAAU;AACd,YAAI,UAAU,OAAO,MAAM;AAE3B,iBAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,gBAAM,MAAM,OAAO,SAAS,CAAC;AAC7B,cAAI,MAAM,SAAS;AACjB,sBAAU;AACV,sBAAU;UACZ;QACF;AAEA,mBAAW,KAAK,OAAO;AACvB,yBAAiB;MACnB;AAGA,YAAM,YAAsB,CAAA;AAC5B,eAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,cAAM,MAAM,WAAW,CAAC;AACxB,YAAI,MAAM,KAAK,QAAQ,WAAW,IAAI,CAAC,GAAG;AACxC,oBAAU,KAAK,GAAG;QACpB;MACF;AAGA,YAAM,WAAW,UAAU,OAAO,CAAC,QAAQ,QAAQ,CAAC;AAGpD,YAAM,OAAO,SAAS,IAAI,CAAC,QAAQ,QAAQ,GAAG,KAAK,EAAE,EAAE,KAAK,EAAE;AAE9D,YAAM,aAAa,SAAS,IAAI,gBAAgB,SAAS;AAEzD,aAAO,EAAE,MAAM,WAAU;IAC3B;;;;;;;;;;ACjDA,QAAA,UAAA,UAAA,iBAAA;AAEA,QAAM,UAAU;AAEhB,QAAM,oBAAgD;MACpD,EAAE,IAAI,QAAQ,MAAM,aAAY;;AAGrB,YAAA,2BAAyD;;MAEpE;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,GAAE;QACnC,QAAQ;QACR,SAAS;;;UAGP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,mEAAmE;YAC5F,QAAQ;;UAEV,UAAU;YACR,MAAK,GAAA,QAAA,YAAW,SAAS,kEAAkE;YAC3F,QAAQ;YACR,UAAU,CAAC,QAAQ;;;QAGvB,YAAY;UACV;YACE,MAAK,GAAA,QAAA,YAAW,SAAS,mEAAmE;YAC5F,UAAU;YACV,QAAQ;;;;MAId;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,GAAE;QACnC,QAAQ;QACR,SAAS;UACP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,gEAAgE;YACzF,QAAQ;;UAEV,UAAU;YACR,MAAK,GAAA,QAAA,YAAW,SAAS,+DAA+D;YACxF,QAAQ;YACR,UAAU,CAAC,QAAQ;;;QAGvB,YAAY;UACV;YACE,MAAK,GAAA,QAAA,YAAW,SAAS,gEAAgE;YACzF,UAAU;YACV,QAAQ;;;;;;MAOd;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,GAAE;QACnC,QAAQ;QACR,SAAS;UACP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,4EAA4E;YACrG,QAAQ;;;QAGZ,YAAY;UACV;YACE,MAAK,GAAA,QAAA,YAAW,SAAS,qEAAqE;YAC9F,UAAU;YACV,QAAQ;;;;MAId;QACE,IAAI;QACJ,MAAM;QACN,aAAa;QACb,WAAW,EAAE,OAAO,KAAK,QAAQ,GAAE;QACnC,QAAQ;QACR,SAAS;UACP,MAAM;YACJ,MAAK,GAAA,QAAA,YAAW,SAAS,4EAA4E;YACrG,QAAQ;;;QAGZ,YAAY;UACV;YACE,MAAK,GAAA,QAAA,YAAW,SAAS,qEAAqE;YAC9F,UAAU;YACV,QAAQ;;;;;;;","names":[]}
|