@camstack/addon-vision 0.1.0 → 0.1.2

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 (131) hide show
  1. package/dist/addons/animal-classifier/index.d.mts +6 -1
  2. package/dist/addons/animal-classifier/index.d.ts +6 -1
  3. package/dist/addons/animal-classifier/index.js +513 -49
  4. package/dist/addons/animal-classifier/index.js.map +1 -1
  5. package/dist/addons/animal-classifier/index.mjs +6 -4
  6. package/dist/addons/audio-classification/index.d.mts +6 -1
  7. package/dist/addons/audio-classification/index.d.ts +6 -1
  8. package/dist/addons/audio-classification/index.js +86 -26
  9. package/dist/addons/audio-classification/index.js.map +1 -1
  10. package/dist/addons/audio-classification/index.mjs +3 -2
  11. package/dist/addons/bird-global-classifier/index.d.mts +6 -1
  12. package/dist/addons/bird-global-classifier/index.d.ts +6 -1
  13. package/dist/addons/bird-global-classifier/index.js +514 -50
  14. package/dist/addons/bird-global-classifier/index.js.map +1 -1
  15. package/dist/addons/bird-global-classifier/index.mjs +6 -4
  16. package/dist/addons/bird-nabirds-classifier/index.d.mts +6 -1
  17. package/dist/addons/bird-nabirds-classifier/index.d.ts +6 -1
  18. package/dist/addons/bird-nabirds-classifier/index.js +523 -60
  19. package/dist/addons/bird-nabirds-classifier/index.js.map +1 -1
  20. package/dist/addons/bird-nabirds-classifier/index.mjs +6 -4
  21. package/dist/addons/face-detection/index.d.mts +6 -1
  22. package/dist/addons/face-detection/index.d.ts +6 -1
  23. package/dist/addons/face-detection/index.js +538 -39
  24. package/dist/addons/face-detection/index.js.map +1 -1
  25. package/dist/addons/face-detection/index.mjs +5 -3
  26. package/dist/addons/face-recognition/index.d.mts +6 -1
  27. package/dist/addons/face-recognition/index.d.ts +6 -1
  28. package/dist/addons/face-recognition/index.js +487 -33
  29. package/dist/addons/face-recognition/index.js.map +1 -1
  30. package/dist/addons/face-recognition/index.mjs +5 -3
  31. package/dist/addons/motion-detection/index.d.mts +3 -1
  32. package/dist/addons/motion-detection/index.d.ts +3 -1
  33. package/dist/addons/motion-detection/index.js +11 -3
  34. package/dist/addons/motion-detection/index.js.map +1 -1
  35. package/dist/addons/motion-detection/index.mjs +140 -3
  36. package/dist/addons/motion-detection/index.mjs.map +1 -1
  37. package/dist/addons/object-detection/index.d.mts +6 -1
  38. package/dist/addons/object-detection/index.d.ts +6 -1
  39. package/dist/addons/object-detection/index.js +369 -72
  40. package/dist/addons/object-detection/index.js.map +1 -1
  41. package/dist/addons/object-detection/index.mjs +5 -3
  42. package/dist/addons/plate-detection/index.d.mts +6 -1
  43. package/dist/addons/plate-detection/index.d.ts +6 -1
  44. package/dist/addons/plate-detection/index.js +531 -31
  45. package/dist/addons/plate-detection/index.js.map +1 -1
  46. package/dist/addons/plate-detection/index.mjs +5 -3
  47. package/dist/addons/plate-recognition/index.d.mts +7 -1
  48. package/dist/addons/plate-recognition/index.d.ts +7 -1
  49. package/dist/addons/plate-recognition/index.js +176 -44
  50. package/dist/addons/plate-recognition/index.js.map +1 -1
  51. package/dist/addons/plate-recognition/index.mjs +4 -3
  52. package/dist/addons/segmentation-refiner/index.d.mts +30 -0
  53. package/dist/addons/segmentation-refiner/index.d.ts +30 -0
  54. package/dist/addons/segmentation-refiner/index.js +1048 -0
  55. package/dist/addons/segmentation-refiner/index.js.map +1 -0
  56. package/dist/addons/segmentation-refiner/index.mjs +209 -0
  57. package/dist/addons/segmentation-refiner/index.mjs.map +1 -0
  58. package/dist/addons/vehicle-classifier/index.d.mts +31 -0
  59. package/dist/addons/vehicle-classifier/index.d.ts +31 -0
  60. package/dist/addons/vehicle-classifier/index.js +688 -0
  61. package/dist/addons/vehicle-classifier/index.js.map +1 -0
  62. package/dist/addons/vehicle-classifier/index.mjs +250 -0
  63. package/dist/addons/vehicle-classifier/index.mjs.map +1 -0
  64. package/dist/{chunk-6OR5TE7A.mjs → chunk-22BHCDT5.mjs} +2 -2
  65. package/dist/chunk-22BHCDT5.mjs.map +1 -0
  66. package/dist/{chunk-LPI42WL6.mjs → chunk-2IOKI4ES.mjs} +23 -12
  67. package/dist/chunk-2IOKI4ES.mjs.map +1 -0
  68. package/dist/chunk-7DYHXUPZ.mjs +36 -0
  69. package/dist/chunk-7DYHXUPZ.mjs.map +1 -0
  70. package/dist/chunk-BJTO5JO5.mjs +11 -0
  71. package/dist/chunk-BP7H4NFS.mjs +412 -0
  72. package/dist/chunk-BP7H4NFS.mjs.map +1 -0
  73. package/dist/chunk-BR2FPGOX.mjs +98 -0
  74. package/dist/chunk-BR2FPGOX.mjs.map +1 -0
  75. package/dist/{chunk-5AIQSN32.mjs → chunk-D6WEHN33.mjs} +66 -17
  76. package/dist/chunk-D6WEHN33.mjs.map +1 -0
  77. package/dist/{chunk-3MQFUDRU.mjs → chunk-DRYFGARD.mjs} +76 -47
  78. package/dist/chunk-DRYFGARD.mjs.map +1 -0
  79. package/dist/{chunk-ISOIDU4U.mjs → chunk-DUN6XU3N.mjs} +23 -5
  80. package/dist/chunk-DUN6XU3N.mjs.map +1 -0
  81. package/dist/{chunk-MEVASN3P.mjs → chunk-ESLHNWWE.mjs} +104 -22
  82. package/dist/chunk-ESLHNWWE.mjs.map +1 -0
  83. package/dist/{chunk-B3R66MPF.mjs → chunk-JUQEW6ON.mjs} +58 -21
  84. package/dist/chunk-JUQEW6ON.mjs.map +1 -0
  85. package/dist/{chunk-AYBFB7ID.mjs → chunk-R5J3WAUI.mjs} +200 -318
  86. package/dist/chunk-R5J3WAUI.mjs.map +1 -0
  87. package/dist/chunk-XZ6ZMXXU.mjs +39 -0
  88. package/dist/chunk-XZ6ZMXXU.mjs.map +1 -0
  89. package/dist/{chunk-5JJZGKL7.mjs → chunk-YPU4WTXZ.mjs} +102 -19
  90. package/dist/chunk-YPU4WTXZ.mjs.map +1 -0
  91. package/dist/{chunk-J4WRYHHY.mjs → chunk-YUCD2TFH.mjs} +66 -36
  92. package/dist/chunk-YUCD2TFH.mjs.map +1 -0
  93. package/dist/{chunk-PDSHDDPV.mjs → chunk-ZTJENCFC.mjs} +159 -35
  94. package/dist/chunk-ZTJENCFC.mjs.map +1 -0
  95. package/dist/{chunk-Q3SQOYG6.mjs → chunk-ZWYXXCXP.mjs} +67 -37
  96. package/dist/chunk-ZWYXXCXP.mjs.map +1 -0
  97. package/dist/index.d.mts +17 -5
  98. package/dist/index.d.ts +17 -5
  99. package/dist/index.js +1343 -550
  100. package/dist/index.js.map +1 -1
  101. package/dist/index.mjs +191 -20
  102. package/dist/index.mjs.map +1 -1
  103. package/package.json +94 -18
  104. package/python/coreml_inference.py +61 -18
  105. package/python/openvino_inference.py +12 -4
  106. package/python/pytorch_inference.py +12 -4
  107. package/dist/addons/camera-native-detection/index.d.mts +0 -32
  108. package/dist/addons/camera-native-detection/index.d.ts +0 -32
  109. package/dist/addons/camera-native-detection/index.js +0 -99
  110. package/dist/addons/camera-native-detection/index.js.map +0 -1
  111. package/dist/addons/camera-native-detection/index.mjs +0 -7
  112. package/dist/chunk-3MQFUDRU.mjs.map +0 -1
  113. package/dist/chunk-5AIQSN32.mjs.map +0 -1
  114. package/dist/chunk-5JJZGKL7.mjs.map +0 -1
  115. package/dist/chunk-6OR5TE7A.mjs.map +0 -1
  116. package/dist/chunk-AYBFB7ID.mjs.map +0 -1
  117. package/dist/chunk-B3R66MPF.mjs.map +0 -1
  118. package/dist/chunk-DTOAB2CE.mjs +0 -79
  119. package/dist/chunk-DTOAB2CE.mjs.map +0 -1
  120. package/dist/chunk-ISOIDU4U.mjs.map +0 -1
  121. package/dist/chunk-J4WRYHHY.mjs.map +0 -1
  122. package/dist/chunk-LPI42WL6.mjs.map +0 -1
  123. package/dist/chunk-MEVASN3P.mjs.map +0 -1
  124. package/dist/chunk-PDSHDDPV.mjs.map +0 -1
  125. package/dist/chunk-Q3SQOYG6.mjs.map +0 -1
  126. package/dist/chunk-QIMDG34B.mjs +0 -229
  127. package/dist/chunk-QIMDG34B.mjs.map +0 -1
  128. package/python/__pycache__/coreml_inference.cpython-313.pyc +0 -0
  129. package/python/__pycache__/openvino_inference.cpython-313.pyc +0 -0
  130. package/python/__pycache__/pytorch_inference.cpython-313.pyc +0 -0
  131. /package/dist/{addons/camera-native-detection/index.mjs.map → chunk-BJTO5JO5.mjs.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalogs/segmentation-models.ts","../src/addons/object-detection/index.ts","../src/shared/postprocess/yolo-seg.ts"],"sourcesContent":["import type { ModelCatalogEntry } from '@camstack/types'\nimport { hfModelUrl, COCO_80_LABELS } from '@camstack/types'\nimport { MLPACKAGE_FILES } from './object-detection-models.js'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nexport const SEGMENTATION_MODELS: readonly ModelCatalogEntry[] = [\n // ── YOLO11-seg ───────────────────────────────────────────────\n {\n id: 'yolo11n-seg',\n name: 'YOLO11 Nano Segmentation',\n description: 'YOLO11 Nano — fastest, smallest YOLO11 instance segmentation model',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/onnx/camstack-yolo11n-seg.onnx'),\n sizeMB: 11,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/coreml/camstack-yolo11n-seg.mlpackage'),\n sizeMB: 6,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/openvino/camstack-yolo11n-seg.xml'),\n sizeMB: 6,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'yolo11s-seg',\n name: 'YOLO11 Small Segmentation',\n description: 'YOLO11 Small — balanced speed and accuracy for instance segmentation',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/onnx/camstack-yolo11s-seg.onnx'),\n sizeMB: 39,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/coreml/camstack-yolo11s-seg.mlpackage'),\n sizeMB: 20,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/openvino/camstack-yolo11s-seg.xml'),\n sizeMB: 20,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'yolo11m-seg',\n name: 'YOLO11 Medium Segmentation',\n description: 'YOLO11 Medium — higher accuracy instance segmentation',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/onnx/camstack-yolo11m-seg.onnx'),\n sizeMB: 86,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/coreml/camstack-yolo11m-seg.mlpackage'),\n sizeMB: 43,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolo11-seg/openvino/camstack-yolo11m-seg.xml'),\n sizeMB: 43,\n runtimes: ['python'],\n },\n },\n },\n\n // ── YOLOv8-seg — CoreML supported ─────────────────────────────\n {\n id: 'yolov8n-seg',\n name: 'YOLOv8 Nano Segmentation',\n description: 'YOLOv8 Nano — fastest, smallest YOLOv8 instance segmentation model',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/onnx/camstack-yolov8n-seg.onnx'),\n sizeMB: 13,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/coreml/camstack-yolov8n-seg.mlpackage'),\n sizeMB: 7,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/openvino/camstack-yolov8n-seg.xml'),\n sizeMB: 7,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'yolov8s-seg',\n name: 'YOLOv8 Small Segmentation',\n description: 'YOLOv8 Small — balanced speed and accuracy for instance segmentation',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/onnx/camstack-yolov8s-seg.onnx'),\n sizeMB: 45,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/coreml/camstack-yolov8s-seg.mlpackage'),\n sizeMB: 23,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/openvino/camstack-yolov8s-seg.xml'),\n sizeMB: 23,\n runtimes: ['python'],\n },\n },\n },\n {\n id: 'yolov8m-seg',\n name: 'YOLOv8 Medium Segmentation',\n description: 'YOLOv8 Medium — higher accuracy instance segmentation',\n inputSize: { width: 640, height: 640 },\n labels: COCO_80_LABELS,\n formats: {\n onnx: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/onnx/camstack-yolov8m-seg.onnx'),\n sizeMB: 104,\n },\n coreml: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/coreml/camstack-yolov8m-seg.mlpackage'),\n sizeMB: 52,\n isDirectory: true,\n files: MLPACKAGE_FILES,\n runtimes: ['python'],\n },\n openvino: {\n url: hfModelUrl(HF_REPO, 'segmentation/yolov8-seg/openvino/camstack-yolov8m-seg.xml'),\n sizeMB: 53,\n runtimes: ['python'],\n },\n },\n },\n] as const\n","import type {\n IDetectorProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n FrameInput,\n DetectorOutput,\n SpatialDetection,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { OBJECT_DETECTION_MODELS } from '../../catalogs/object-detection-models.js'\nimport { SEGMENTATION_MODELS } from '../../catalogs/segmentation-models.js'\nimport { COCO_TO_MACRO, MACRO_LABELS, COCO_80_LABELS } from '@camstack/types'\nimport { letterbox } from '../../shared/image-utils.js'\nimport { yoloPostprocess } from '../../shared/postprocess/yolo.js'\nimport { yoloSegPostprocess } from '../../shared/postprocess/yolo-seg.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\n/** Returns true when the model id identifies a YOLO segmentation model (e.g. yolov8n-seg, yolo11m-seg) */\nfunction isSegModel(modelId: string): boolean {\n return modelId.includes('-seg')\n}\n\n/** Combined catalog: regular detection models + segmentation models */\nconst ALL_DETECTION_MODELS: readonly ModelCatalogEntry[] = [\n ...OBJECT_DETECTION_MODELS,\n ...SEGMENTATION_MODELS,\n]\n\n/**\n * classMapMode controls how raw COCO labels are mapped after inference:\n *\n * - 'macro' (default): apply COCO_TO_MACRO — only person / vehicle / animal\n * survive, all other classes are dropped.\n * - 'all': keep every raw COCO label (80 classes). originalClass === class.\n */\ntype ClassMapMode = 'macro' | 'all'\n\n/** Map COCO-class detections to macro categories (person/vehicle/animal) */\nfunction applyClassMap(\n detections: SpatialDetection[],\n classMap: ClassMapDefinition,\n): SpatialDetection[] {\n return detections\n .filter((d) => classMap.mapping[d.class] !== undefined)\n .map((d) => ({\n ...d,\n originalClass: d.class,\n class: classMap.mapping[d.class]!,\n }))\n}\n\n/** RAM estimates per model (MB) */\nconst RAM_ESTIMATES: Record<string, number> = {\n 'yolov8n': 80, 'yolov8s': 150, 'yolov8s-relu': 150, 'yolov8m': 300, 'yolov8l': 500, 'yolov8x': 800,\n 'yolov9t': 60, 'yolov9s': 120, 'yolov9c': 300,\n 'yolo11n': 70, 'yolo11s': 130, 'yolo11m': 280, 'yolo11l': 450, 'yolo11x': 750,\n 'yolo11n-seg': 84, 'yolo11s-seg': 156, 'yolo11m-seg': 336,\n 'yolov8n-seg': 96, 'yolov8s-seg': 180, 'yolov8m-seg': 360,\n}\n\n/**\n * Accuracy scores per model (0-100).\n * YOLO11 scores are higher than YOLOv8 equivalents to reflect the\n * ~2 mAP improvement at same parameter count (e.g. YOLO11n 39.5 vs YOLOv8n 37.3).\n * This ensures the resolver prefers YOLO11 when both families are available.\n */\nconst ACCURACY_SCORES: Record<string, number> = {\n 'yolov8n': 55, 'yolov8s': 70, 'yolov8s-relu': 68, 'yolov8m': 82, 'yolov8l': 88, 'yolov8x': 92,\n 'yolov9t': 58, 'yolov9s': 73, 'yolov9c': 86,\n 'yolo11n': 62, 'yolo11s': 78, 'yolo11m': 88, 'yolo11l': 93, 'yolo11x': 97,\n 'yolo11n-seg': 62, 'yolo11s-seg': 78, 'yolo11m-seg': 88,\n 'yolov8n-seg': 55, 'yolov8s-seg': 70, 'yolov8m-seg': 82,\n}\n\nexport default class ObjectDetectionAddon implements IDetectorProvider, IDetectionAddon {\n readonly id = 'object-detection'\n readonly slot = 'detector' as const\n readonly inputClasses: readonly string[] | null = null\n readonly outputClasses = ['person', 'vehicle', 'animal'] as const\n readonly slotPriority = 0\n readonly manifest: AddonManifest = {\n id: 'object-detection',\n name: 'Object Detection',\n version: '0.1.0',\n\n description: 'YOLO-based object detection — detects persons, vehicles, and animals',\n\n slot: 'detector',\n inputClasses: undefined,\n outputClasses: ['person', 'vehicle', 'animal'],\n supportsCustomModels: true,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'yolo11n',\n runtime: 'node',\n backend: 'cpu',\n confidence: 0.5,\n iouThreshold: 0.45,\n classMapMode: 'macro',\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private confidence = 0.5\n private iouThreshold = 0.45\n private classMapMode: ClassMapMode = 'macro'\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return ALL_DETECTION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: RAM_ESTIMATES[m.id] ?? 100,\n accuracyScore: ACCURACY_SCORES[m.id] ?? 60,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'yolo11n'\n this.confidence = (cfg['confidence'] as number | undefined) ?? 0.5\n this.iouThreshold = (cfg['iouThreshold'] as number | undefined) ?? 0.45\n this.classMapMode = (cfg['classMapMode'] as ClassMapMode | undefined) ?? 'macro'\n\n const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`ObjectDetectionAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n async detect(frame: FrameInput): Promise<DetectorOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n\n // Python engine path — send JPEG directly, Python handles preprocess + inference + postprocess\n if ('runJpeg' in this.engine! && typeof (this.engine as any).runJpeg === 'function') {\n const result = await (this.engine as any).runJpeg(frame.data) as Record<string, unknown>\n const rawDets = (result.detections ?? []) as Array<{ className: string; score: number; bbox: number[] }>\n const detections: SpatialDetection[] = rawDets.map((d) => ({\n class: this.classMapMode === 'all' ? d.className : (COCO_TO_MACRO.mapping[d.className] ?? d.className),\n originalClass: d.className,\n score: d.score,\n bbox: {\n x: d.bbox[0]! * frame.width,\n y: d.bbox[1]! * frame.height,\n w: (d.bbox[2]! - d.bbox[0]!) * frame.width,\n h: (d.bbox[3]! - d.bbox[1]!) * frame.height,\n },\n })).filter((d) => this.classMapMode === 'all' || COCO_TO_MACRO.mapping[d.originalClass!] !== undefined)\n\n return {\n detections,\n inferenceMs: (result.inferenceMs as number) ?? (Date.now() - start),\n modelId: this.modelEntry.id,\n }\n }\n\n // Node.js engine path — letterbox + run tensor + postprocess\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n const targetSize = Math.max(inputW, inputH)\n\n const lb = await letterbox(frame.data, targetSize)\n\n const numClasses = this.modelEntry.labels.length\n const labels = this.modelEntry.labels.map((l) => l.id)\n const postprocessOpts = {\n confidence: this.confidence,\n iouThreshold: this.iouThreshold,\n labels,\n scale: lb.scale,\n padX: lb.padX,\n padY: lb.padY,\n originalWidth: lb.originalWidth,\n originalHeight: lb.originalHeight,\n }\n\n let rawDetections: SpatialDetection[]\n\n if (isSegModel(this.modelEntry.id)) {\n // YOLO-seg models produce two outputs:\n // output0: [1, 4 + numClasses + 32, numBoxes] (detection + mask coefficients)\n // output1: [1, 32, 160, 160] (prototype masks)\n const outputs = await this.engine!.runMultiOutput(lb.data, [1, 3, targetSize, targetSize])\n const outputNames = Object.keys(outputs)\n\n if (outputNames.length < 2) {\n throw new Error(\n `ObjectDetectionAddon: seg model \"${this.modelEntry.id}\" returned ${outputNames.length} output(s); expected 2`,\n )\n }\n\n // ONNX output order is deterministic; first output is the detection tensor, second is protos\n const detectionOutput = outputs[outputNames[0]!]!\n const protoOutput = outputs[outputNames[1]!]!\n\n // Infer dims from tensor sizes\n const numMaskCoeffs = 32\n const numBoxes = detectionOutput.length / (4 + numClasses + numMaskCoeffs)\n const maskHeight = 160\n const maskWidth = 160\n\n rawDetections = yoloSegPostprocess(\n {\n detectionOutput,\n protoOutput,\n numClasses,\n numBoxes,\n numMaskCoeffs,\n maskHeight,\n maskWidth,\n },\n postprocessOpts,\n )\n } else {\n // Standard YOLO output: [1, 4+numClasses, numBoxes]\n const output = await this.engine!.run(lb.data, [1, 3, targetSize, targetSize])\n const numBoxes = output.length / (4 + numClasses)\n rawDetections = yoloPostprocess(output, numClasses, numBoxes, postprocessOpts)\n }\n\n const detections = this.classMapMode === 'all'\n ? rawDetections\n : applyClassMap(rawDetections, COCO_TO_MACRO)\n\n return {\n detections,\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = ALL_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n // Download model if needed\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n // Discover Python path for Python-based runtimes\n let pythonPath: string | undefined\n if (config?.runtime === 'python') {\n for (const cmd of ['python3', 'python']) {\n try {\n const { execSync } = await import('node:child_process')\n execSync(`${cmd} --version`, { timeout: 3000, stdio: 'ignore' })\n pythonPath = cmd\n break\n } catch { /* not found */ }\n }\n }\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n pythonPath,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...ALL_DETECTION_MODELS],\n allowCustom: true,\n allowConversion: true,\n acceptFormats: ['onnx', 'coreml', 'openvino', 'tflite'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'yolo',\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n { value: 'tensorrt', label: 'TensorRT (NVIDIA)' },\n ],\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Detection Thresholds',\n columns: 2,\n fields: [\n {\n key: 'confidence',\n label: 'Confidence Threshold',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.5,\n },\n {\n key: 'iouThreshold',\n label: 'IoU Threshold (NMS)',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.45,\n },\n ],\n },\n {\n id: 'classmap',\n title: 'Class Mapping',\n columns: 1,\n fields: [\n {\n key: 'classMapMode',\n label: 'Output classes',\n type: 'select',\n options: [\n { value: 'macro', label: 'Macro (person / vehicle / animal)' },\n { value: 'all', label: 'All COCO classes (80)' },\n ],\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return COCO_TO_MACRO\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...ALL_DETECTION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n // TODO: check downloaded models in modelsDir\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return this.classMapMode === 'all' ? COCO_80_LABELS : MACRO_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n","import type { SpatialDetection, BoundingBox } from '@camstack/types'\nimport { nms, iou as _iou } from './yolo.js'\nimport type { YoloPostprocessOptions } from './yolo.js'\n\nexport interface YoloSegOutput {\n /** Detection output: [1, 4 + numClasses + numMaskCoeffs, numBoxes] (row-major, batch dim stripped) */\n readonly detectionOutput: Float32Array\n /** Prototype masks: [1, numMaskCoeffs, maskH, maskW] (batch dim stripped) */\n readonly protoOutput: Float32Array\n readonly numClasses: number\n readonly numBoxes: number\n /** Number of mask prototype coefficients per detection (typically 32) */\n readonly numMaskCoeffs: number\n /** Height of prototype mask grid (typically 160) */\n readonly maskHeight: number\n /** Width of prototype mask grid (typically 160) */\n readonly maskWidth: number\n}\n\nexport interface YoloSegPostprocessOptions extends YoloPostprocessOptions {\n /** Binary mask threshold — pixels above this value become 255, others 0 (default: 0.5) */\n readonly maskThreshold?: number\n}\n\n/** Sigmoid activation: σ(x) = 1 / (1 + e^-x) */\nexport function sigmoid(x: number): number {\n return 1 / (1 + Math.exp(-x))\n}\n\n/**\n * Compute instance segmentation mask for a single detection.\n *\n * @param coeffs [numMaskCoeffs] mask coefficients for this detection\n * @param protos [numMaskCoeffs × maskH × maskW] prototype masks (flat, row-major)\n * @param numMaskCoeffs number of prototype channels (e.g. 32)\n * @param maskH prototype grid height (e.g. 160)\n * @param maskW prototype grid width (e.g. 160)\n * @returns [maskH × maskW] sigmoid-activated raw mask values in [0, 1]\n */\nexport function computeRawMask(\n coeffs: Float32Array,\n protos: Float32Array,\n numMaskCoeffs: number,\n maskH: number,\n maskW: number,\n): Float32Array {\n const maskSize = maskH * maskW\n const rawMask = new Float32Array(maskSize)\n\n // mask_raw[y * maskW + x] = sum_k( coeffs[k] * protos[k * maskSize + y * maskW + x] )\n // Then apply sigmoid element-wise.\n for (let px = 0; px < maskSize; px++) {\n let val = 0\n for (let k = 0; k < numMaskCoeffs; k++) {\n val += (coeffs[k] ?? 0) * (protos[k * maskSize + px] ?? 0)\n }\n rawMask[px] = sigmoid(val)\n }\n\n return rawMask\n}\n\n/**\n * Crop a flat [maskH × maskW] mask to a bounding box region (in mask coordinate space),\n * threshold to binary, and return the cropped Uint8Array along with its dimensions.\n *\n * @param rawMask [maskH × maskW] sigmoid-activated values in [0, 1]\n * @param maskH full mask grid height\n * @param maskW full mask grid width\n * @param bbox detection bounding box in the inference input space (e.g. 640×640 letterboxed)\n * @param maskThreshold threshold above which a pixel is considered foreground (default 0.5)\n * @param maskScale ratio of mask resolution to inference resolution (e.g. 160/640 = 0.25)\n * @returns { data: Uint8Array, width, height } of the cropped binary mask\n */\nexport function cropAndThresholdMask(\n rawMask: Float32Array,\n maskH: number,\n maskW: number,\n bbox: BoundingBox,\n maskThreshold: number,\n maskScale: number,\n): { readonly data: Uint8Array; readonly width: number; readonly height: number } {\n const cropX1 = Math.max(0, Math.floor(bbox.x * maskScale))\n const cropY1 = Math.max(0, Math.floor(bbox.y * maskScale))\n const cropX2 = Math.min(maskW, Math.ceil((bbox.x + bbox.w) * maskScale))\n const cropY2 = Math.min(maskH, Math.ceil((bbox.y + bbox.h) * maskScale))\n\n const cropW = Math.max(1, cropX2 - cropX1)\n const cropH = Math.max(1, cropY2 - cropY1)\n\n const data = new Uint8Array(cropW * cropH)\n\n for (let row = 0; row < cropH; row++) {\n const srcRow = cropY1 + row\n for (let col = 0; col < cropW; col++) {\n const srcCol = cropX1 + col\n const srcIdx = srcRow * maskW + srcCol\n data[row * cropW + col] = (rawMask[srcIdx] ?? 0) > maskThreshold ? 255 : 0\n }\n }\n\n return { data, width: cropW, height: cropH }\n}\n\n/**\n * YOLO-seg postprocessing: run detection filtering + NMS, then decode instance masks.\n *\n * The seg detection tensor has layout [1, 4 + numClasses + numMaskCoeffs, numBoxes]:\n * rows 0–3 : cx, cy, w, h\n * rows 4 to 4+C-1 : class scores\n * rows 4+C to end : mask coefficients (32)\n *\n * Steps:\n * 1. Filter boxes by confidence threshold, collecting mask coefficients per candidate.\n * 2. Run NMS across all candidates.\n * 3. For each surviving detection, compute the instance mask and attach it.\n */\nexport function yoloSegPostprocess(\n segOutput: YoloSegOutput,\n options: YoloSegPostprocessOptions,\n): SpatialDetection[] {\n const {\n detectionOutput,\n protoOutput,\n numClasses,\n numBoxes,\n numMaskCoeffs,\n maskHeight,\n maskWidth,\n } = segOutput\n\n const {\n confidence,\n iouThreshold,\n labels,\n scale,\n padX,\n padY,\n originalWidth,\n originalHeight,\n maskThreshold = 0.5,\n } = options\n\n // The mask resolution to inference resolution scale factor (e.g. 160/640 = 0.25)\n // We derive the inference size from scale/pad context: the letterboxed input is typically 640×640\n // but we receive coordinates in that space already, so we use maskHeight / inferH.\n // Since all YOLO-seg models use 640×640 input and 160×160 proto, the ratio is always 160/640.\n // We compute it generically from the known prototype dims + fixed YOLO input of 640.\n const yoloInputSize = 640\n const maskScale = maskHeight / yoloInputSize\n\n interface Candidate {\n readonly bbox: BoundingBox\n readonly score: number\n readonly classIdx: number\n readonly coeffs: Float32Array\n }\n\n const candidates: Candidate[] = []\n\n for (let i = 0; i < numBoxes; i++) {\n const cx = detectionOutput[0 * numBoxes + i] ?? 0\n const cy = detectionOutput[1 * numBoxes + i] ?? 0\n const w = detectionOutput[2 * numBoxes + i] ?? 0\n const h = detectionOutput[3 * numBoxes + i] ?? 0\n\n let bestScore = -Infinity\n let bestClass = 0\n\n for (let j = 0; j < numClasses; j++) {\n const score = detectionOutput[(4 + j) * numBoxes + i] ?? 0\n if (score > bestScore) {\n bestScore = score\n bestClass = j\n }\n }\n\n if (bestScore < confidence) continue\n\n const bbox: BoundingBox = {\n x: cx - w / 2,\n y: cy - h / 2,\n w,\n h,\n }\n\n // Extract mask coefficients for this box\n const coeffs = new Float32Array(numMaskCoeffs)\n for (let k = 0; k < numMaskCoeffs; k++) {\n coeffs[k] = detectionOutput[(4 + numClasses + k) * numBoxes + i] ?? 0\n }\n\n candidates.push({ bbox, score: bestScore, classIdx: bestClass, coeffs })\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, coeffs } = candidates[idx]!\n const label = labels[classIdx] ?? String(classIdx)\n\n // Scale bbox back from letterbox space 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 const finalBbox: BoundingBox = { x, y, w: x2 - x, h: y2 - y }\n\n // Decode instance mask using the letterbox-space bbox (before coord scaling)\n const rawMask = computeRawMask(coeffs, protoOutput, numMaskCoeffs, maskHeight, maskWidth)\n const { data: maskData, width: mW, height: mH } = cropAndThresholdMask(\n rawMask,\n maskHeight,\n maskWidth,\n bbox,\n maskThreshold,\n maskScale,\n )\n\n return {\n class: label,\n originalClass: label,\n score,\n bbox: finalBbox,\n mask: maskData,\n maskWidth: mW,\n maskHeight: mH,\n } satisfies SpatialDetection\n })\n}\n"],"mappings":"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","names":["COCO_80_LABELS","detections","COCO_80_LABELS"]}
@@ -0,0 +1,39 @@
1
+ // src/catalogs/vehicle-classification-models.ts
2
+ import { hfModelUrl } from "@camstack/types";
3
+ var HF_REPO = "camstack/camstack-models";
4
+ var hf = (path) => hfModelUrl(HF_REPO, path);
5
+ var VEHICLE_LABELS = [
6
+ { id: "vehicle-type", name: "Vehicle Type" }
7
+ ];
8
+ var VEHICLE_TYPE_MODELS = [
9
+ {
10
+ id: "vehicle-type-efficientnet",
11
+ name: "Vehicle Type (EfficientNet)",
12
+ description: "EfficientNet-B4 vehicle make/model/year classifier \u2014 8,949 classes from VMMRdb",
13
+ inputSize: { width: 380, height: 380 },
14
+ inputNormalization: "imagenet",
15
+ labels: VEHICLE_LABELS,
16
+ formats: {
17
+ onnx: { url: hf("vehicleClassification/efficientnet/onnx/camstack-vehicle-type-efficientnet.onnx"), sizeMB: 135 },
18
+ coreml: {
19
+ url: hf("vehicleClassification/efficientnet/coreml/camstack-vehicle-type-efficientnet.mlpackage"),
20
+ sizeMB: 10,
21
+ isDirectory: true,
22
+ files: ["Manifest.json", "Data/com.apple.CoreML/model.mlmodel", "Data/com.apple.CoreML/weights/weight.bin"],
23
+ runtimes: ["python"]
24
+ }
25
+ },
26
+ extraFiles: [
27
+ {
28
+ url: hf("vehicleClassification/efficientnet/camstack-vehicle-type-labels.json"),
29
+ filename: "camstack-vehicle-type-labels.json",
30
+ sizeMB: 0.2
31
+ }
32
+ ]
33
+ }
34
+ ];
35
+
36
+ export {
37
+ VEHICLE_TYPE_MODELS
38
+ };
39
+ //# sourceMappingURL=chunk-XZ6ZMXXU.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalogs/vehicle-classification-models.ts"],"sourcesContent":["import type { ModelCatalogEntry, LabelDefinition } from '@camstack/types'\nimport { hfModelUrl } from '@camstack/types'\n\nconst HF_REPO = 'camstack/camstack-models'\n\nconst hf = (path: string) => hfModelUrl(HF_REPO, path)\n\nconst VEHICLE_LABELS: readonly LabelDefinition[] = [\n { id: 'vehicle-type', name: 'Vehicle Type' },\n]\n\nexport const VEHICLE_TYPE_MODELS: readonly ModelCatalogEntry[] = [\n {\n id: 'vehicle-type-efficientnet',\n name: 'Vehicle Type (EfficientNet)',\n description: 'EfficientNet-B4 vehicle make/model/year classifier — 8,949 classes from VMMRdb',\n inputSize: { width: 380, height: 380 },\n inputNormalization: 'imagenet',\n labels: VEHICLE_LABELS,\n formats: {\n onnx: { url: hf('vehicleClassification/efficientnet/onnx/camstack-vehicle-type-efficientnet.onnx'), sizeMB: 135 },\n coreml: {\n url: hf('vehicleClassification/efficientnet/coreml/camstack-vehicle-type-efficientnet.mlpackage'),\n sizeMB: 10,\n isDirectory: true,\n files: ['Manifest.json', 'Data/com.apple.CoreML/model.mlmodel', 'Data/com.apple.CoreML/weights/weight.bin'],\n runtimes: ['python'],\n },\n },\n extraFiles: [\n {\n url: hf('vehicleClassification/efficientnet/camstack-vehicle-type-labels.json'),\n filename: 'camstack-vehicle-type-labels.json',\n sizeMB: 0.2,\n },\n ],\n },\n] as const\n"],"mappings":";AACA,SAAS,kBAAkB;AAE3B,IAAM,UAAU;AAEhB,IAAM,KAAK,CAAC,SAAiB,WAAW,SAAS,IAAI;AAErD,IAAM,iBAA6C;AAAA,EACjD,EAAE,IAAI,gBAAgB,MAAM,eAAe;AAC7C;AAEO,IAAM,sBAAoD;AAAA,EAC/D;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACrC,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,MAAM,EAAE,KAAK,GAAG,iFAAiF,GAAG,QAAQ,IAAI;AAAA,MAChH,QAAQ;AAAA,QACN,KAAK,GAAG,wFAAwF;AAAA,QAChG,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO,CAAC,iBAAiB,uCAAuC,0CAA0C;AAAA,QAC1G,UAAU,CAAC,QAAQ;AAAA,MACrB;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV;AAAA,QACE,KAAK,GAAG,sEAAsE;AAAA,QAC9E,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -1,13 +1,16 @@
1
1
  import {
2
2
  yoloPostprocess
3
3
  } from "./chunk-KUO2BVFY.mjs";
4
+ import {
5
+ MLPACKAGE_FILES
6
+ } from "./chunk-BP7H4NFS.mjs";
4
7
  import {
5
8
  cropRegion,
6
9
  letterbox
7
- } from "./chunk-6OR5TE7A.mjs";
10
+ } from "./chunk-22BHCDT5.mjs";
8
11
  import {
9
12
  resolveEngine
10
- } from "./chunk-LPI42WL6.mjs";
13
+ } from "./chunk-2IOKI4ES.mjs";
11
14
 
12
15
  // src/catalogs/plate-detection-models.ts
13
16
  import { hfModelUrl } from "@camstack/types";
@@ -29,15 +32,20 @@ var PLATE_DETECTION_MODELS = [
29
32
  },
30
33
  coreml: {
31
34
  url: hfModelUrl(HF_REPO, "plateDetection/yolov8-plate/coreml/camstack-yolov8n-plate.mlpackage"),
32
- sizeMB: 5.9
35
+ sizeMB: 5.9,
36
+ isDirectory: true,
37
+ files: MLPACKAGE_FILES,
38
+ runtimes: ["python"]
33
39
  },
34
40
  openvino: {
35
41
  url: hfModelUrl(HF_REPO, "plateDetection/yolov8-plate/openvino/camstack-yolov8n-plate.xml"),
36
- sizeMB: 6.1
42
+ sizeMB: 6.1,
43
+ runtimes: ["python"]
37
44
  },
38
45
  tflite: {
39
46
  url: hfModelUrl(HF_REPO, "plateDetection/yolov8-plate/tflite/camstack-yolov8n-plate_float32.tflite"),
40
- sizeMB: 12
47
+ sizeMB: 12,
48
+ runtimes: ["python"]
41
49
  }
42
50
  }
43
51
  }
@@ -58,7 +66,6 @@ var PlateDetectionAddon = class {
58
66
  name: "License Plate Detection",
59
67
  version: "0.1.0",
60
68
  description: "YOLO-based license plate detector \u2014 crops plate regions from vehicle detections",
61
- packageName: "@camstack/addon-vision",
62
69
  slot: "cropper",
63
70
  inputClasses: ["vehicle"],
64
71
  outputClasses: ["plate"],
@@ -66,21 +73,34 @@ var PlateDetectionAddon = class {
66
73
  mayRequirePython: false,
67
74
  defaultConfig: {
68
75
  modelId: "yolov8n-plate",
69
- runtime: "auto",
76
+ runtime: "node",
70
77
  backend: "cpu",
71
78
  confidence: 0.5,
72
79
  iouThreshold: 0.45
73
80
  }
74
81
  };
75
- engine;
82
+ engine = null;
76
83
  modelEntry;
77
84
  confidence = 0.5;
78
85
  iouThreshold = 0.45;
86
+ resolvedConfig = null;
87
+ ctx = null;
88
+ getModelRequirements() {
89
+ return PLATE_DETECTION_MODELS.map((m) => ({
90
+ modelId: m.id,
91
+ name: m.name,
92
+ minRAM_MB: 80,
93
+ accuracyScore: 60,
94
+ formats: Object.keys(m.formats)
95
+ }));
96
+ }
97
+ configure(config) {
98
+ this.resolvedConfig = config;
99
+ }
79
100
  async initialize(ctx) {
101
+ this.ctx = ctx;
80
102
  const cfg = ctx.addonConfig;
81
- const modelId = cfg["modelId"] ?? "yolov8n-plate";
82
- const runtime = cfg["runtime"] ?? "auto";
83
- const backend = cfg["backend"] ?? "cpu";
103
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "yolov8n-plate";
84
104
  this.confidence = cfg["confidence"] ?? 0.5;
85
105
  this.iouThreshold = cfg["iouThreshold"] ?? 0.45;
86
106
  const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId);
@@ -88,15 +108,9 @@ var PlateDetectionAddon = class {
88
108
  throw new Error(`PlateDetectionAddon: unknown modelId "${modelId}"`);
89
109
  }
90
110
  this.modelEntry = entry;
91
- const resolved = await resolveEngine({
92
- runtime,
93
- backend,
94
- modelEntry: entry,
95
- modelsDir: ctx.locationPaths.models
96
- });
97
- this.engine = resolved.engine;
98
111
  }
99
112
  async crop(input) {
113
+ if (!this.engine) await this.ensureEngine();
100
114
  const start = Date.now();
101
115
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
102
116
  const targetSize = Math.max(inputW, inputH);
@@ -123,12 +137,81 @@ var PlateDetectionAddon = class {
123
137
  modelId: this.modelEntry.id
124
138
  };
125
139
  }
140
+ async ensureEngine() {
141
+ const config = this.resolvedConfig;
142
+ const modelId = config?.modelId ?? this.modelEntry.id;
143
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
144
+ const backend = config?.backend ?? "cpu";
145
+ const format = config?.format ?? "onnx";
146
+ const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
147
+ this.modelEntry = entry;
148
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
149
+ if (this.ctx.models) {
150
+ await this.ctx.models.ensure(modelId, format);
151
+ }
152
+ const resolved = await resolveEngine({
153
+ runtime,
154
+ backend,
155
+ modelEntry: entry,
156
+ modelsDir,
157
+ models: this.ctx.models
158
+ });
159
+ this.engine = resolved.engine;
160
+ }
126
161
  async shutdown() {
127
162
  await this.engine?.dispose();
128
163
  }
129
164
  getConfigSchema() {
130
165
  return {
131
166
  sections: [
167
+ {
168
+ id: "model",
169
+ title: "Model",
170
+ columns: 1,
171
+ fields: [
172
+ {
173
+ key: "modelId",
174
+ label: "Model",
175
+ type: "model-selector",
176
+ catalog: [...PLATE_DETECTION_MODELS],
177
+ allowCustom: false,
178
+ allowConversion: false,
179
+ acceptFormats: ["onnx", "coreml", "openvino"],
180
+ requiredMetadata: ["inputSize", "labels", "outputFormat"],
181
+ outputFormatHint: "yolo"
182
+ }
183
+ ]
184
+ },
185
+ {
186
+ id: "runtime",
187
+ title: "Runtime",
188
+ columns: 2,
189
+ fields: [
190
+ {
191
+ key: "runtime",
192
+ label: "Runtime",
193
+ type: "select",
194
+ options: [
195
+ { value: "auto", label: "Auto" },
196
+ { value: "onnx", label: "ONNX Runtime" },
197
+ { value: "coreml", label: "CoreML (Apple)" },
198
+ { value: "openvino", label: "OpenVINO (Intel)" }
199
+ ]
200
+ },
201
+ {
202
+ key: "backend",
203
+ label: "Backend",
204
+ type: "select",
205
+ showWhen: { field: "runtime", equals: "onnx" },
206
+ options: [
207
+ { value: "auto", label: "Auto" },
208
+ { value: "cpu", label: "CPU" },
209
+ { value: "coreml", label: "CoreML" },
210
+ { value: "cuda", label: "CUDA (NVIDIA)" }
211
+ ]
212
+ }
213
+ ]
214
+ },
132
215
  {
133
216
  id: "thresholds",
134
217
  title: "Detection Thresholds",
@@ -183,4 +266,4 @@ export {
183
266
  PLATE_DETECTION_MODELS,
184
267
  PlateDetectionAddon
185
268
  };
186
- //# sourceMappingURL=chunk-5JJZGKL7.mjs.map
269
+ //# sourceMappingURL=chunk-YPU4WTXZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalogs/plate-detection-models.ts","../src/addons/plate-detection/index.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","import type {\n ICropperProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n CropInput,\n CropperOutput,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { PLATE_DETECTION_MODELS } from '../../catalogs/plate-detection-models.js'\nimport { cropRegion, letterbox } from '../../shared/image-utils.js'\nimport { yoloPostprocess } from '../../shared/postprocess/yolo.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\nconst PLATE_LABEL: LabelDefinition = { id: 'plate', name: 'License Plate' }\nconst PLATE_LABELS: readonly LabelDefinition[] = [PLATE_LABEL]\nconst PLATE_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\nexport default class PlateDetectionAddon implements ICropperProvider, IDetectionAddon {\n readonly id = 'plate-detection'\n readonly slot = 'cropper' as const\n readonly inputClasses = ['vehicle'] as const\n readonly outputClasses = ['plate'] as const\n readonly slotPriority = 0\n readonly manifest: AddonManifest = {\n id: 'plate-detection',\n name: 'License Plate Detection',\n version: '0.1.0',\n\n description: 'YOLO-based license plate detector — crops plate regions from vehicle detections',\n\n slot: 'cropper',\n inputClasses: ['vehicle'],\n outputClasses: ['plate'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'yolov8n-plate',\n runtime: 'node',\n backend: 'cpu',\n confidence: 0.5,\n iouThreshold: 0.45,\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private confidence = 0.5\n private iouThreshold = 0.45\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return PLATE_DETECTION_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: 80,\n accuracyScore: 60,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'yolov8n-plate'\n this.confidence = (cfg['confidence'] as number | undefined) ?? 0.5\n this.iouThreshold = (cfg['iouThreshold'] as number | undefined) ?? 0.45\n\n const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`PlateDetectionAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n async crop(input: CropInput): Promise<CropperOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n const targetSize = Math.max(inputW, inputH)\n\n // Crop the vehicle region from the full frame\n const vehicleCrop = await cropRegion(input.frame.data, input.roi)\n\n const lb = await letterbox(vehicleCrop, targetSize)\n const output = await this.engine!.run(lb.data, [1, 3, targetSize, targetSize])\n\n const numClasses = this.modelEntry.labels.length\n const numBoxes = output.length / (4 + numClasses)\n const labels = this.modelEntry.labels.map((l) => l.id)\n\n const plates = yoloPostprocess(output, numClasses, numBoxes, {\n confidence: this.confidence,\n iouThreshold: this.iouThreshold,\n labels,\n scale: lb.scale,\n padX: lb.padX,\n padY: lb.padY,\n originalWidth: lb.originalWidth,\n originalHeight: lb.originalHeight,\n })\n\n // Override class to 'plate'\n const crops = plates.map((p) => ({ ...p, class: 'plate', originalClass: p.originalClass }))\n\n return {\n crops,\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = PLATE_DETECTION_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...PLATE_DETECTION_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'coreml', 'openvino'],\n requiredMetadata: ['inputSize', 'labels', 'outputFormat'],\n outputFormatHint: 'yolo',\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Detection Thresholds',\n columns: 2,\n fields: [\n {\n key: 'confidence',\n label: 'Confidence Threshold',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.5,\n },\n {\n key: 'iouThreshold',\n label: 'IoU Threshold (NMS)',\n type: 'slider',\n min: 0.1,\n max: 1.0,\n step: 0.05,\n default: 0.45,\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return PLATE_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...PLATE_DETECTION_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return PLATE_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n"],"mappings":"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","names":["PLATE_LABELS"]}
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  ANIMAL_TYPE_MODELS
3
- } from "./chunk-ISOIDU4U.mjs";
3
+ } from "./chunk-DUN6XU3N.mjs";
4
4
  import {
5
5
  cropRegion,
6
6
  resizeAndNormalize
7
- } from "./chunk-6OR5TE7A.mjs";
7
+ } from "./chunk-22BHCDT5.mjs";
8
8
  import {
9
9
  resolveEngine
10
- } from "./chunk-LPI42WL6.mjs";
10
+ } from "./chunk-2IOKI4ES.mjs";
11
11
 
12
12
  // src/addons/animal-classifier/index.ts
13
13
  var ANIMAL_TYPE_LABEL = { id: "animal-type", name: "Animal Type" };
@@ -43,42 +43,49 @@ var AnimalClassifierAddon = class {
43
43
  name: "Animal Classifier",
44
44
  version: "0.1.0",
45
45
  description: "ViT-based animal type classifier \u2014 10 common species",
46
- packageName: "@camstack/addon-vision",
47
46
  slot: "classifier",
47
+ labelOutputType: "classification",
48
48
  inputClasses: ["animal"],
49
49
  outputClasses: ["animal-type:*"],
50
50
  supportsCustomModels: false,
51
51
  mayRequirePython: false,
52
52
  defaultConfig: {
53
53
  modelId: "animals-10",
54
- runtime: "auto",
54
+ runtime: "node",
55
55
  backend: "cpu",
56
56
  minConfidence: 0.3
57
57
  }
58
58
  };
59
- engine;
59
+ engine = null;
60
60
  modelEntry;
61
61
  minConfidence = 0.3;
62
+ resolvedConfig = null;
63
+ ctx = null;
64
+ getModelRequirements() {
65
+ return ANIMAL_TYPE_MODELS.map((m) => ({
66
+ modelId: m.id,
67
+ name: m.name,
68
+ minRAM_MB: 800,
69
+ accuracyScore: 75,
70
+ formats: Object.keys(m.formats)
71
+ }));
72
+ }
73
+ configure(config) {
74
+ this.resolvedConfig = config;
75
+ }
62
76
  async initialize(ctx) {
77
+ this.ctx = ctx;
63
78
  const cfg = ctx.addonConfig;
64
- const modelId = cfg["modelId"] ?? "animals-10";
65
- const runtime = cfg["runtime"] ?? "auto";
66
- const backend = cfg["backend"] ?? "cpu";
79
+ const modelId = cfg["modelId"] ?? this.resolvedConfig?.modelId ?? "animals-10";
67
80
  this.minConfidence = cfg["minConfidence"] ?? 0.3;
68
81
  const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId);
69
82
  if (!entry) {
70
83
  throw new Error(`AnimalClassifierAddon: unknown modelId "${modelId}"`);
71
84
  }
72
85
  this.modelEntry = entry;
73
- const resolved = await resolveEngine({
74
- runtime,
75
- backend,
76
- modelEntry: entry,
77
- modelsDir: ctx.locationPaths.models
78
- });
79
- this.engine = resolved.engine;
80
86
  }
81
87
  async classify(input) {
88
+ if (!this.engine) await this.ensureEngine();
82
89
  const start = Date.now();
83
90
  const { width: inputW, height: inputH } = this.modelEntry.inputSize;
84
91
  const animalCrop = await cropRegion(input.frame.data, input.roi);
@@ -113,6 +120,27 @@ var AnimalClassifierAddon = class {
113
120
  modelId: this.modelEntry.id
114
121
  };
115
122
  }
123
+ async ensureEngine() {
124
+ const config = this.resolvedConfig;
125
+ const modelId = config?.modelId ?? this.modelEntry.id;
126
+ const runtime = config?.runtime === "python" ? "coreml" : config?.runtime === "node" ? "onnx" : "auto";
127
+ const backend = config?.backend ?? "cpu";
128
+ const format = config?.format ?? "onnx";
129
+ const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId) ?? this.modelEntry;
130
+ this.modelEntry = entry;
131
+ const modelsDir = this.ctx.models?.getModelsDir() ?? this.ctx.locationPaths.models;
132
+ if (this.ctx.models) {
133
+ await this.ctx.models.ensure(modelId, format);
134
+ }
135
+ const resolved = await resolveEngine({
136
+ runtime,
137
+ backend,
138
+ modelEntry: entry,
139
+ modelsDir,
140
+ models: this.ctx.models
141
+ });
142
+ this.engine = resolved.engine;
143
+ }
116
144
  async shutdown() {
117
145
  await this.engine?.dispose();
118
146
  }
@@ -137,22 +165,6 @@ var AnimalClassifierAddon = class {
137
165
  }
138
166
  ]
139
167
  },
140
- {
141
- id: "thresholds",
142
- title: "Classification Settings",
143
- columns: 1,
144
- fields: [
145
- {
146
- key: "minConfidence",
147
- label: "Minimum Confidence",
148
- type: "slider",
149
- min: 0.05,
150
- max: 1,
151
- step: 0.05,
152
- default: 0.3
153
- }
154
- ]
155
- },
156
168
  {
157
169
  id: "runtime",
158
170
  title: "Runtime",
@@ -163,23 +175,41 @@ var AnimalClassifierAddon = class {
163
175
  label: "Runtime",
164
176
  type: "select",
165
177
  options: [
166
- { value: "auto", label: "Auto (recommended)" },
178
+ { value: "auto", label: "Auto" },
167
179
  { value: "onnx", label: "ONNX Runtime" },
168
- { value: "coreml", label: "CoreML (Apple)" }
180
+ { value: "coreml", label: "CoreML (Apple)" },
181
+ { value: "openvino", label: "OpenVINO (Intel)" }
169
182
  ]
170
183
  },
171
184
  {
172
185
  key: "backend",
173
186
  label: "Backend",
174
187
  type: "select",
175
- dependsOn: { runtime: "onnx" },
188
+ showWhen: { field: "runtime", equals: "onnx" },
176
189
  options: [
190
+ { value: "auto", label: "Auto" },
177
191
  { value: "cpu", label: "CPU" },
178
192
  { value: "coreml", label: "CoreML" },
179
193
  { value: "cuda", label: "CUDA (NVIDIA)" }
180
194
  ]
181
195
  }
182
196
  ]
197
+ },
198
+ {
199
+ id: "thresholds",
200
+ title: "Classification Settings",
201
+ columns: 1,
202
+ fields: [
203
+ {
204
+ key: "minConfidence",
205
+ label: "Minimum Confidence",
206
+ type: "slider",
207
+ min: 0.05,
208
+ max: 1,
209
+ step: 0.05,
210
+ default: 0.3
211
+ }
212
+ ]
183
213
  }
184
214
  ]
185
215
  };
@@ -209,4 +239,4 @@ var AnimalClassifierAddon = class {
209
239
  export {
210
240
  AnimalClassifierAddon
211
241
  };
212
- //# sourceMappingURL=chunk-J4WRYHHY.mjs.map
242
+ //# sourceMappingURL=chunk-YUCD2TFH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/addons/animal-classifier/index.ts"],"sourcesContent":["import type {\n IClassifierProvider,\n IDetectionAddon,\n AddonManifest,\n AddonContext,\n CropInput,\n ClassifierOutput,\n ConfigUISchema,\n ClassMapDefinition,\n ProbeResult,\n ModelCatalogEntry,\n DetectionModel,\n LabelDefinition,\n IInferenceEngine,\n ModelRequirement,\n ResolvedInferenceConfig,\n} from '@camstack/types'\nimport { ANIMAL_TYPE_MODELS } from '../../catalogs/animal-classification-models.js'\nimport { cropRegion, resizeAndNormalize } from '../../shared/image-utils.js'\nimport { resolveEngine } from '../../shared/engine-resolver.js'\n\nconst ANIMAL_TYPE_LABEL: LabelDefinition = { id: 'animal-type', name: 'Animal Type' }\nconst ANIMAL_TYPE_LABELS: readonly LabelDefinition[] = [ANIMAL_TYPE_LABEL]\nconst ANIMAL_CLASS_MAP: ClassMapDefinition = { mapping: {}, preserveOriginal: true }\n\nconst ANIMAL_10_CLASSES = [\n 'cat',\n 'cow',\n 'dog',\n 'dolphin',\n 'eagle',\n 'giant panda',\n 'horse',\n 'monkey',\n 'sheep',\n 'spider',\n] as const\n\nfunction softmax(logits: Float32Array): Float32Array {\n const max = logits.reduce((a, b) => Math.max(a, b), -Infinity)\n const exps = logits.map((v) => Math.exp(v - max))\n const sum = exps.reduce((a, b) => a + b, 0)\n return exps.map((v) => v / sum) as unknown as Float32Array\n}\n\nexport default class AnimalClassifierAddon implements IClassifierProvider, IDetectionAddon {\n readonly id = 'animal-classifier'\n readonly slot = 'classifier' as const\n readonly inputClasses = ['animal'] as const\n readonly outputClasses = ['animal-type:*'] as const\n readonly slotPriority = 0\n readonly requiredSteps = [] as const\n readonly manifest: AddonManifest = {\n id: 'animal-classifier',\n name: 'Animal Classifier',\n version: '0.1.0',\n\n description: 'ViT-based animal type classifier — 10 common species',\n\n slot: 'classifier',\n labelOutputType: 'classification',\n inputClasses: ['animal'],\n outputClasses: ['animal-type:*'],\n supportsCustomModels: false,\n mayRequirePython: false,\n defaultConfig: {\n modelId: 'animals-10',\n runtime: 'node',\n backend: 'cpu',\n minConfidence: 0.3,\n },\n }\n\n private engine: IInferenceEngine | null = null\n private modelEntry!: ModelCatalogEntry\n private minConfidence = 0.3\n private resolvedConfig: ResolvedInferenceConfig | null = null\n private ctx: AddonContext | null = null\n\n getModelRequirements(): ModelRequirement[] {\n return ANIMAL_TYPE_MODELS.map((m) => ({\n modelId: m.id,\n name: m.name,\n minRAM_MB: 800,\n accuracyScore: 75,\n formats: Object.keys(m.formats) as readonly string[],\n }))\n }\n\n configure(config: ResolvedInferenceConfig): void {\n this.resolvedConfig = config\n }\n\n async initialize(ctx: AddonContext): Promise<void> {\n this.ctx = ctx\n const cfg = ctx.addonConfig\n const modelId = (cfg['modelId'] as string | undefined) ?? this.resolvedConfig?.modelId ?? 'animals-10'\n this.minConfidence = (cfg['minConfidence'] as number | undefined) ?? 0.3\n\n const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId)\n if (!entry) {\n throw new Error(`AnimalClassifierAddon: unknown modelId \"${modelId}\"`)\n }\n this.modelEntry = entry\n }\n\n async classify(input: CropInput): Promise<ClassifierOutput> {\n if (!this.engine) await this.ensureEngine()\n const start = Date.now()\n const { width: inputW, height: inputH } = this.modelEntry.inputSize\n\n // Crop the animal region\n const animalCrop = await cropRegion(input.frame.data, input.roi)\n\n // Resize to 224x224, ImageNet normalization, NCHW\n const normalized = await resizeAndNormalize(animalCrop, inputW, inputH, 'imagenet', 'nchw')\n\n // Run inference — output shape: [1, 10]\n const rawOutput = await this.engine!.run(normalized, [1, 3, inputH, inputW])\n\n // Softmax to get probabilities\n const probs = softmax(rawOutput)\n\n // Find argmax\n let maxIdx = 0\n let maxScore = probs[0] ?? 0\n for (let i = 1; i < probs.length; i++) {\n const score = probs[i] ?? 0\n if (score > maxScore) {\n maxScore = score\n maxIdx = i\n }\n }\n\n if (maxScore < this.minConfidence) {\n return {\n classifications: [],\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n const label = ANIMAL_10_CLASSES[maxIdx] ?? `animal_${maxIdx}`\n\n return {\n classifications: [\n {\n class: label,\n score: maxScore,\n },\n ],\n inferenceMs: Date.now() - start,\n modelId: this.modelEntry.id,\n }\n }\n\n private async ensureEngine(): Promise<void> {\n const config = this.resolvedConfig\n const modelId = config?.modelId ?? this.modelEntry.id\n const runtime = config?.runtime === 'python' ? 'coreml' : (config?.runtime === 'node' ? 'onnx' : 'auto')\n const backend = config?.backend ?? 'cpu'\n const format = config?.format ?? 'onnx'\n\n const entry = ANIMAL_TYPE_MODELS.find((m) => m.id === modelId) ?? this.modelEntry\n this.modelEntry = entry\n\n const modelsDir = this.ctx!.models?.getModelsDir() ?? this.ctx!.locationPaths.models\n\n if (this.ctx!.models) {\n await this.ctx!.models.ensure(modelId, format as any)\n }\n\n const resolved = await resolveEngine({\n runtime: runtime as 'auto',\n backend,\n modelEntry: entry,\n modelsDir,\n models: this.ctx!.models,\n })\n this.engine = resolved.engine\n }\n\n async shutdown(): Promise<void> {\n await this.engine?.dispose()\n }\n\n getConfigSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'model',\n title: 'Model',\n columns: 1,\n fields: [\n {\n key: 'modelId',\n label: 'Model',\n type: 'model-selector',\n catalog: [...ANIMAL_TYPE_MODELS],\n allowCustom: false,\n allowConversion: false,\n acceptFormats: ['onnx', 'coreml', 'openvino'],\n requiredMetadata: ['inputSize', 'labels'],\n outputFormatHint: 'classification',\n },\n ],\n },\n {\n id: 'runtime',\n title: 'Runtime',\n columns: 2,\n fields: [\n {\n key: 'runtime',\n label: 'Runtime',\n type: 'select',\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'onnx', label: 'ONNX Runtime' },\n { value: 'coreml', label: 'CoreML (Apple)' },\n { value: 'openvino', label: 'OpenVINO (Intel)' },\n ],\n },\n {\n key: 'backend',\n label: 'Backend',\n type: 'select',\n showWhen: { field: 'runtime', equals: 'onnx' },\n options: [\n { value: 'auto', label: 'Auto' },\n { value: 'cpu', label: 'CPU' },\n { value: 'coreml', label: 'CoreML' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\n },\n ],\n },\n {\n id: 'thresholds',\n title: 'Classification Settings',\n columns: 1,\n fields: [\n {\n key: 'minConfidence',\n label: 'Minimum Confidence',\n type: 'slider',\n min: 0.05,\n max: 1.0,\n step: 0.05,\n default: 0.3,\n },\n ],\n },\n ],\n }\n }\n\n getClassMap(): ClassMapDefinition {\n return ANIMAL_CLASS_MAP\n }\n\n getModelCatalog(): ModelCatalogEntry[] {\n return [...ANIMAL_TYPE_MODELS]\n }\n\n getAvailableModels(): DetectionModel[] {\n return []\n }\n\n getActiveLabels(): readonly LabelDefinition[] {\n return ANIMAL_TYPE_LABELS\n }\n\n async probe(): Promise<ProbeResult> {\n return {\n available: true,\n runtime: this.engine?.runtime ?? 'onnx',\n device: this.engine?.device ?? 'cpu',\n capabilities: ['fp32'],\n }\n }\n}\n"],"mappings":"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","names":[]}