@jax-data-science/sci-image-visualizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +404 -0
- package/esm2022/index.mjs +52 -0
- package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
- package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
- package/esm2022/lib/contracts/display-types.mjs +8 -0
- package/esm2022/lib/contracts/image.contract.mjs +11 -0
- package/esm2022/lib/contracts/intensity.mjs +28 -0
- package/esm2022/lib/contracts/plot-type.mjs +112 -0
- package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
- package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
- package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
- package/esm2022/lib/contracts/sam.contract.mjs +12 -0
- package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
- package/esm2022/lib/contracts/viz-config.mjs +3 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
- package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
- package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
- package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
- package/esm2022/lib/models/bezier.mjs +120 -0
- package/esm2022/lib/models/class-preset.mjs +46 -0
- package/esm2022/lib/models/geometry.mjs +198 -0
- package/esm2022/lib/models/region.mjs +166 -0
- package/esm2022/lib/models/shape.mjs +53 -0
- package/esm2022/lib/plot.utilities.mjs +693 -0
- package/esm2022/lib/processing/image-converter.service.mjs +90 -0
- package/esm2022/lib/processing/image-crop.mjs +62 -0
- package/esm2022/lib/processing/processing-image.mjs +50 -0
- package/esm2022/lib/provide-visualization.mjs +63 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
- package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
- package/esm2022/lib/region-ops.service.mjs +301 -0
- package/esm2022/lib/render-orchestrator.mjs +87 -0
- package/esm2022/lib/routing-visualizer.service.mjs +533 -0
- package/esm2022/lib/store/class-color.util.mjs +52 -0
- package/esm2022/lib/store/region-store.service.mjs +1029 -0
- package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
- package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
- package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
- package/esm2022/lib/visualization.module.mjs +162 -0
- package/esm2022/lib/visualizer.component.mjs +1597 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
- package/fesm2022/mask.worker.js +989 -0
- package/fesm2022/onnx-sam.worker.js +202 -0
- package/index.d.ts +39 -0
- package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
- package/lib/contracts/capabilities.contract.d.ts +30 -0
- package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
- package/lib/contracts/colormap-lut.d.ts +21 -0
- package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
- package/lib/contracts/display-types.d.ts +41 -0
- package/lib/contracts/image.contract.d.ts +72 -0
- package/lib/contracts/intensity.d.ts +18 -0
- package/lib/contracts/plot-type.d.ts +108 -0
- package/lib/contracts/ports/image-state.port.d.ts +29 -0
- package/lib/contracts/ports/preferences.port.d.ts +19 -0
- package/lib/contracts/ports/region-io.port.d.ts +29 -0
- package/lib/contracts/ports/tile-access.port.d.ts +27 -0
- package/lib/contracts/region-editor-api.contract.d.ts +83 -0
- package/lib/contracts/region-overlay.contract.d.ts +47 -0
- package/lib/contracts/region-store.contract.d.ts +74 -0
- package/lib/contracts/sam.contract.d.ts +98 -0
- package/lib/contracts/toolbar-config.d.ts +24 -0
- package/lib/contracts/visualizer.contract.d.ts +346 -0
- package/lib/contracts/viz-config.d.ts +25 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
- package/lib/implementations/base-store-visualizer.d.ts +71 -0
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
- package/lib/implementations/osd/display-pipeline.d.ts +47 -0
- package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
- package/lib/implementations/osd/osd-coords.d.ts +16 -0
- package/lib/implementations/osd/osd-lib.d.ts +19 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
- package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
- package/lib/implementations/osd/slice-cache.d.ts +161 -0
- package/lib/implementations/osd/tile-client.d.ts +32 -0
- package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
- package/lib/implementations/plotly/plotly.service.d.ts +594 -0
- package/lib/implementations/simple-slice-access.service.d.ts +64 -0
- package/lib/models/bezier.d.ts +59 -0
- package/lib/models/class-preset.d.ts +39 -0
- package/lib/models/geometry.d.ts +66 -0
- package/lib/models/region.d.ts +132 -0
- package/lib/models/shape.d.ts +44 -0
- package/lib/plot.utilities.d.ts +107 -0
- package/lib/processing/image-converter.service.d.ts +28 -0
- package/lib/processing/image-crop.d.ts +18 -0
- package/lib/processing/processing-image.d.ts +17 -0
- package/lib/provide-visualization.d.ts +34 -0
- package/lib/region-editor/mask-raster.d.ts +61 -0
- package/lib/region-editor/mask-worker.d.ts +7 -0
- package/lib/region-editor/region-editor.component.d.ts +305 -0
- package/lib/region-ops.service.d.ts +92 -0
- package/lib/render-orchestrator.d.ts +59 -0
- package/lib/routing-visualizer.service.d.ts +227 -0
- package/lib/store/class-color.util.d.ts +26 -0
- package/lib/store/region-store.service.d.ts +315 -0
- package/lib/store/visualizer-store.service.d.ts +123 -0
- package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
- package/lib/toolbar/crop/slide-crop.d.ts +30 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
- package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
- package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
- package/lib/toolbar/toolbar.component.d.ts +167 -0
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
- package/lib/toolbar/wand/wand.service.d.ts +133 -0
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
- package/lib/visualization.module.d.ts +45 -0
- package/lib/visualizer.component.d.ts +378 -0
- package/package.json +73 -0
- package/src/lib/assets/3d-coordinates.svg +49 -0
- package/src/lib/assets/cells.svg +1 -0
- package/src/lib/assets/click.svg +1 -0
- package/src/lib/assets/colormap-luts.json +1 -0
- package/src/lib/assets/contour.svg +48 -0
- package/src/lib/assets/cube-3d.svg +1 -0
- package/src/lib/assets/edit-selection-white.svg +47 -0
- package/src/lib/assets/heatmap.svg +1 -0
- package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
- package/src/lib/assets/icons/colormap-accent.png +0 -0
- package/src/lib/assets/icons/colormap-afmhot.png +0 -0
- package/src/lib/assets/icons/colormap-autumn.png +0 -0
- package/src/lib/assets/icons/colormap-berlin.png +0 -0
- package/src/lib/assets/icons/colormap-binary.png +0 -0
- package/src/lib/assets/icons/colormap-blackbody.png +0 -0
- package/src/lib/assets/icons/colormap-bluered.png +0 -0
- package/src/lib/assets/icons/colormap-blues.png +0 -0
- package/src/lib/assets/icons/colormap-bone.png +0 -0
- package/src/lib/assets/icons/colormap-brbg.png +0 -0
- package/src/lib/assets/icons/colormap-brg.png +0 -0
- package/src/lib/assets/icons/colormap-bugn.png +0 -0
- package/src/lib/assets/icons/colormap-bupu.png +0 -0
- package/src/lib/assets/icons/colormap-bwr.png +0 -0
- package/src/lib/assets/icons/colormap-cividis.png +0 -0
- package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
- package/src/lib/assets/icons/colormap-cool.png +0 -0
- package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
- package/src/lib/assets/icons/colormap-copper.png +0 -0
- package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
- package/src/lib/assets/icons/colormap-dark2.png +0 -0
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-electric.png +0 -0
- package/src/lib/assets/icons/colormap-flag.png +0 -0
- package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
- package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
- package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
- package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
- package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
- package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
- package/src/lib/assets/icons/colormap-gnbu.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
- package/src/lib/assets/icons/colormap-gray.png +0 -0
- package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greens.png +0 -0
- package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greys.png +0 -0
- package/src/lib/assets/icons/colormap-hot.png +0 -0
- package/src/lib/assets/icons/colormap-hsv.png +0 -0
- package/src/lib/assets/icons/colormap-inferno.png +0 -0
- package/src/lib/assets/icons/colormap-jet.png +0 -0
- package/src/lib/assets/icons/colormap-magma.png +0 -0
- package/src/lib/assets/icons/colormap-managua.png +0 -0
- package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
- package/src/lib/assets/icons/colormap-ocean.png +0 -0
- package/src/lib/assets/icons/colormap-oranges.png +0 -0
- package/src/lib/assets/icons/colormap-orrd.png +0 -0
- package/src/lib/assets/icons/colormap-pastel2.png +0 -0
- package/src/lib/assets/icons/colormap-picnic.png +0 -0
- package/src/lib/assets/icons/colormap-pink.png +0 -0
- package/src/lib/assets/icons/colormap-piyg.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-plasma.png +0 -0
- package/src/lib/assets/icons/colormap-portland.png +0 -0
- package/src/lib/assets/icons/colormap-prgn.png +0 -0
- package/src/lib/assets/icons/colormap-prism.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/icons/colormap-pubugn.png +0 -0
- package/src/lib/assets/icons/colormap-puor.png +0 -0
- package/src/lib/assets/icons/colormap-purd.png +0 -0
- package/src/lib/assets/icons/colormap-purples.png +0 -0
- package/src/lib/assets/icons/colormap-rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-rdbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdgy.png +0 -0
- package/src/lib/assets/icons/colormap-rdpu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
- package/src/lib/assets/icons/colormap-reds.png +0 -0
- package/src/lib/assets/icons/colormap-seismic.png +0 -0
- package/src/lib/assets/icons/colormap-set1.png +0 -0
- package/src/lib/assets/icons/colormap-set2.png +0 -0
- package/src/lib/assets/icons/colormap-set3.png +0 -0
- package/src/lib/assets/icons/colormap-spectral.png +0 -0
- package/src/lib/assets/icons/colormap-spring.png +0 -0
- package/src/lib/assets/icons/colormap-summer.png +0 -0
- package/src/lib/assets/icons/colormap-tab10.png +0 -0
- package/src/lib/assets/icons/colormap-tab20.png +0 -0
- package/src/lib/assets/icons/colormap-tab20b.png +0 -0
- package/src/lib/assets/icons/colormap-tab20c.png +0 -0
- package/src/lib/assets/icons/colormap-terrain.png +0 -0
- package/src/lib/assets/icons/colormap-turbo.png +0 -0
- package/src/lib/assets/icons/colormap-twilight.png +0 -0
- package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
- package/src/lib/assets/icons/colormap-vanimo.png +0 -0
- package/src/lib/assets/icons/colormap-viridis.png +0 -0
- package/src/lib/assets/icons/colormap-winter.png +0 -0
- package/src/lib/assets/icons/colormap-wistia.png +0 -0
- package/src/lib/assets/icons/colormap-ylgn.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
- package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
- package/src/lib/assets/invert.svg +1 -0
- package/src/lib/assets/isosurface.svg +7 -0
- package/src/lib/assets/mask.svg +1 -0
- package/src/lib/assets/paintbrush.svg +1 -0
- package/src/lib/assets/picture-segmentation.svg +43 -0
- package/src/lib/assets/polygon-vertices.svg +13 -0
- package/src/lib/assets/polyline.svg +3 -0
- package/src/lib/assets/redo.svg +39 -0
- package/src/lib/assets/region-editor.svg +37 -0
- package/src/lib/assets/region-move.svg +7 -0
- package/src/lib/assets/smooth.svg +56 -0
- package/src/lib/assets/spline-chart.svg +7 -0
- package/src/lib/assets/surface.svg +37 -0
- package/src/lib/assets/test/download-379.svg +1 -0
- package/src/lib/assets/test/download-98.svg +1 -0
- package/src/lib/assets/test/json-1.svg +1 -0
- package/src/lib/assets/test/load-53.svg +1 -0
- package/src/lib/assets/test/mask-44.svg +1 -0
- package/src/lib/assets/test/mask-download-44.svg +15 -0
- package/src/lib/assets/test/mask-save-44.svg +11 -0
- package/src/lib/assets/test/overlay-1.svg +1 -0
- package/src/lib/assets/test/overlay-4.svg +1 -0
- package/src/lib/assets/test/region-26.svg +1 -0
- package/src/lib/assets/test/save-56.svg +1 -0
- package/src/lib/assets/test/upload-43.svg +1 -0
- package/src/lib/assets/to-bezier.svg +15 -0
- package/src/lib/assets/to-polygon.svg +11 -0
- package/src/lib/assets/undo.svg +38 -0
- package/src/lib/assets/vertex-add.svg +12 -0
- package/src/lib/assets/vertex-delete.svg +12 -0
- package/src/lib/assets/wand.svg +54 -0
- package/src/lib/assets/zoom-box.svg +10 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry of promptable SAM models for the browser segment tool.
|
|
3
|
+
*
|
|
4
|
+
* micro-sam (microscopy-finetuned, promptable) and patho-sam (histopathology-
|
|
5
|
+
* finetuned) are entries; SAM3 slots in here once its quantized ONNX export and
|
|
6
|
+
* a `variant: 'sam3'` decoder path are published. The
|
|
7
|
+
* automatic cellpose-SAM model is intentionally NOT here — it's not promptable
|
|
8
|
+
* and lives in the processing-pipeline's cellpose engine as the automatic tool.
|
|
9
|
+
*
|
|
10
|
+
* `encoderUrl` / `decoderUrl` point at the public HF-hosted ONNX pairs by
|
|
11
|
+
* default, so the segment tools work out of the box in any host (mirroring the
|
|
12
|
+
* cellpose default). A host can repoint them at its own hosting (e.g. a GCS
|
|
13
|
+
* bucket) at runtime via {@link setSamModelUrls}; an empty URL disables a model
|
|
14
|
+
* (the session throws a clear "not configured" error). Export/quantization
|
|
15
|
+
* tooling: the sibling `browser-onnx-tools` project; see docs/sam-segmentation-design.md.
|
|
16
|
+
*/
|
|
17
|
+
export const SAM_MODELS = [
|
|
18
|
+
{
|
|
19
|
+
id: 'microsam-vit-t-lm',
|
|
20
|
+
label: 'micro-sam ViT-T',
|
|
21
|
+
encoderUrl: 'https://huggingface.co/Ballon999/microsam-vit-t-lm-onnx/resolve/main/encoder.fp16.onnx',
|
|
22
|
+
decoderUrl: 'https://huggingface.co/Ballon999/microsam-vit-t-lm-onnx/resolve/main/decoder.onnx',
|
|
23
|
+
variant: 'sam1',
|
|
24
|
+
inputSize: 1024,
|
|
25
|
+
microscopy: true,
|
|
26
|
+
// TinyViT's fp16 attention overflows on the onnxruntime-web WebGPU EP and
|
|
27
|
+
// returns an empty mask ("No masks found"); it's numerically correct on
|
|
28
|
+
// WASM, and the encoder is tiny (~14 MB) so WASM is plenty fast.
|
|
29
|
+
encoderProviders: ['wasm'],
|
|
30
|
+
// Small enough to run in-process on the main thread — avoids the Web
|
|
31
|
+
// Worker's spawn / second-ORT-runtime / round-trip overhead, which made it
|
|
32
|
+
// noticeably slower to load and segment.
|
|
33
|
+
inProcess: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'microsam-vit-b-lm',
|
|
37
|
+
label: 'micro-sam ViT-B',
|
|
38
|
+
encoderUrl: 'https://huggingface.co/Ballon999/microsam-vit-b-lm-onnx/resolve/main/encoder.fp16.onnx',
|
|
39
|
+
decoderUrl: 'https://huggingface.co/Ballon999/microsam-vit-b-lm-onnx/resolve/main/decoder.onnx',
|
|
40
|
+
variant: 'sam1',
|
|
41
|
+
inputSize: 1024,
|
|
42
|
+
microscopy: true,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'patho-sam-vit-b',
|
|
46
|
+
label: 'patho-sam ViT-B',
|
|
47
|
+
encoderUrl: 'https://huggingface.co/Ballon999/patho-sam-vit-b-onnx/resolve/main/encoder.fp16.onnx',
|
|
48
|
+
decoderUrl: 'https://huggingface.co/Ballon999/patho-sam-vit-b-onnx/resolve/main/decoder.onnx',
|
|
49
|
+
variant: 'sam1',
|
|
50
|
+
inputSize: 1024,
|
|
51
|
+
microscopy: true,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'patho-sam-vit-b-int8',
|
|
55
|
+
label: 'patho-sam ViT-B (int8)',
|
|
56
|
+
encoderUrl: 'https://huggingface.co/Ballon999/patho-sam-vit-b-onnx/resolve/main/encoder.int8.onnx',
|
|
57
|
+
decoderUrl: 'https://huggingface.co/Ballon999/patho-sam-vit-b-onnx/resolve/main/decoder.onnx',
|
|
58
|
+
variant: 'sam1',
|
|
59
|
+
inputSize: 1024,
|
|
60
|
+
microscopy: true,
|
|
61
|
+
// int8 dynamic-quantized encoder (~100 MB vs ~180 MB fp16, IoU ~0.99 on the
|
|
62
|
+
// sanity test). onnxruntime-web's WebGPU EP doesn't support int8 matmul, so
|
|
63
|
+
// it runs on WASM — smaller download, slower encode than the fp16 entry.
|
|
64
|
+
encoderProviders: ['wasm'],
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
/** Initial default model id (overridden at runtime once the host configures a
|
|
68
|
+
* hosted model via {@link setSamModelUrls}). */
|
|
69
|
+
export const DEFAULT_SAM_MODEL_ID = SAM_MODELS[0].id;
|
|
70
|
+
/** The active default — updated when the host configures a model's ONNX URLs,
|
|
71
|
+
* so the tool uses the model that's actually hosted (not just the first entry). */
|
|
72
|
+
let activeDefaultId = DEFAULT_SAM_MODEL_ID;
|
|
73
|
+
/** Look up a model by id; falls back to the active default when id is
|
|
74
|
+
* unknown/absent. */
|
|
75
|
+
export function getSamModel(id) {
|
|
76
|
+
const wanted = id ?? activeDefaultId;
|
|
77
|
+
return SAM_MODELS.find((m) => m.id === wanted) ?? SAM_MODELS[0];
|
|
78
|
+
}
|
|
79
|
+
/** The active default model id (what the tools/picker use when unset). */
|
|
80
|
+
export function getDefaultSamModelId() {
|
|
81
|
+
return activeDefaultId;
|
|
82
|
+
}
|
|
83
|
+
/** Set the active default model id (must be a registered model). */
|
|
84
|
+
export function setDefaultSamModel(id) {
|
|
85
|
+
if (SAM_MODELS.some((m) => m.id === id))
|
|
86
|
+
activeDefaultId = id;
|
|
87
|
+
}
|
|
88
|
+
/** True when a model has both ONNX URLs configured (i.e. it can actually run). */
|
|
89
|
+
export function isSamModelReady(model) {
|
|
90
|
+
return !!model.encoderUrl && !!model.decoderUrl;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Point a registered model at its hosted ONNX pair (HF / GCS). Called by the
|
|
94
|
+
* host's composition root once hosting is decided, keeping deployment URLs out
|
|
95
|
+
* of the library.
|
|
96
|
+
*/
|
|
97
|
+
export function setSamModelUrls(id, encoderUrl, decoderUrl) {
|
|
98
|
+
const m = SAM_MODELS.find((x) => x.id === id);
|
|
99
|
+
if (m) {
|
|
100
|
+
m.encoderUrl = encoderUrl;
|
|
101
|
+
m.decoderUrl = decoderUrl;
|
|
102
|
+
// The configured (hosted) model becomes the active default, so the tools
|
|
103
|
+
// use it rather than the first registry entry (which may be unhosted).
|
|
104
|
+
if (encoderUrl && decoderUrl)
|
|
105
|
+
activeDefaultId = id;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FtLW1vZGVsLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90b29sYmFyL3NlZ21lbnRhdGlvbi9zYW0tbW9kZWwtcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFrQjtJQUN2QztRQUNFLEVBQUUsRUFBRSxtQkFBbUI7UUFDdkIsS0FBSyxFQUFFLGlCQUFpQjtRQUN4QixVQUFVLEVBQUUsd0ZBQXdGO1FBQ3BHLFVBQVUsRUFBRSxtRkFBbUY7UUFDL0YsT0FBTyxFQUFFLE1BQU07UUFDZixTQUFTLEVBQUUsSUFBSTtRQUNmLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLDBFQUEwRTtRQUMxRSx3RUFBd0U7UUFDeEUsaUVBQWlFO1FBQ2pFLGdCQUFnQixFQUFFLENBQUMsTUFBTSxDQUFDO1FBQzFCLHFFQUFxRTtRQUNyRSwyRUFBMkU7UUFDM0UseUNBQXlDO1FBQ3pDLFNBQVMsRUFBRSxJQUFJO0tBQ2hCO0lBQ0Q7UUFDRSxFQUFFLEVBQUUsbUJBQW1CO1FBQ3ZCLEtBQUssRUFBRSxpQkFBaUI7UUFDeEIsVUFBVSxFQUFFLHdGQUF3RjtRQUNwRyxVQUFVLEVBQUUsbUZBQW1GO1FBQy9GLE9BQU8sRUFBRSxNQUFNO1FBQ2YsU0FBUyxFQUFFLElBQUk7UUFDZixVQUFVLEVBQUUsSUFBSTtLQUNqQjtJQUNEO1FBQ0UsRUFBRSxFQUFFLGlCQUFpQjtRQUNyQixLQUFLLEVBQUUsaUJBQWlCO1FBQ3hCLFVBQVUsRUFBRSxzRkFBc0Y7UUFDbEcsVUFBVSxFQUFFLGlGQUFpRjtRQUM3RixPQUFPLEVBQUUsTUFBTTtRQUNmLFNBQVMsRUFBRSxJQUFJO1FBQ2YsVUFBVSxFQUFFLElBQUk7S0FDakI7SUFDRDtRQUNFLEVBQUUsRUFBRSxzQkFBc0I7UUFDMUIsS0FBSyxFQUFFLHdCQUF3QjtRQUMvQixVQUFVLEVBQUUsc0ZBQXNGO1FBQ2xHLFVBQVUsRUFBRSxpRkFBaUY7UUFDN0YsT0FBTyxFQUFFLE1BQU07UUFDZixTQUFTLEVBQUUsSUFBSTtRQUNmLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLDRFQUE0RTtRQUM1RSw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLGdCQUFnQixFQUFFLENBQUMsTUFBTSxDQUFDO0tBQzNCO0NBQ0YsQ0FBQztBQUVGO2lEQUNpRDtBQUNqRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBRXJEO29GQUNvRjtBQUNwRixJQUFJLGVBQWUsR0FBRyxvQkFBb0IsQ0FBQztBQUUzQztzQkFDc0I7QUFDdEIsTUFBTSxVQUFVLFdBQVcsQ0FBQyxFQUFXO0lBQ3JDLE1BQU0sTUFBTSxHQUFHLEVBQUUsSUFBSSxlQUFlLENBQUM7SUFDckMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLE1BQU0sQ0FBQyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsRSxDQUFDO0FBRUQsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxvQkFBb0I7SUFDbEMsT0FBTyxlQUFlLENBQUM7QUFDekIsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxNQUFNLFVBQVUsa0JBQWtCLENBQUMsRUFBVTtJQUMzQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQUUsZUFBZSxHQUFHLEVBQUUsQ0FBQztBQUNoRSxDQUFDO0FBRUQsa0ZBQWtGO0FBQ2xGLE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBa0I7SUFDaEQsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQztBQUNsRCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsRUFBVSxFQUFFLFVBQWtCLEVBQUUsVUFBa0I7SUFDaEYsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUM5QyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ04sQ0FBQyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDMUIsQ0FBQyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDMUIseUVBQXlFO1FBQ3pFLHVFQUF1RTtRQUN2RSxJQUFJLFVBQVUsSUFBSSxVQUFVO1lBQUUsZUFBZSxHQUFHLEVBQUUsQ0FBQztJQUNyRCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFNhbU1vZGVsRGVmIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NhbS5jb250cmFjdCc7XG5cbi8qKlxuICogUmVnaXN0cnkgb2YgcHJvbXB0YWJsZSBTQU0gbW9kZWxzIGZvciB0aGUgYnJvd3NlciBzZWdtZW50IHRvb2wuXG4gKlxuICogbWljcm8tc2FtIChtaWNyb3Njb3B5LWZpbmV0dW5lZCwgcHJvbXB0YWJsZSkgYW5kIHBhdGhvLXNhbSAoaGlzdG9wYXRob2xvZ3ktXG4gKiBmaW5ldHVuZWQpIGFyZSBlbnRyaWVzOyBTQU0zIHNsb3RzIGluIGhlcmUgb25jZSBpdHMgcXVhbnRpemVkIE9OTlggZXhwb3J0IGFuZFxuICogYSBgdmFyaWFudDogJ3NhbTMnYCBkZWNvZGVyIHBhdGggYXJlIHB1Ymxpc2hlZC4gVGhlXG4gKiBhdXRvbWF0aWMgY2VsbHBvc2UtU0FNIG1vZGVsIGlzIGludGVudGlvbmFsbHkgTk9UIGhlcmUg4oCUIGl0J3Mgbm90IHByb21wdGFibGVcbiAqIGFuZCBsaXZlcyBpbiB0aGUgcHJvY2Vzc2luZy1waXBlbGluZSdzIGNlbGxwb3NlIGVuZ2luZSBhcyB0aGUgYXV0b21hdGljIHRvb2wuXG4gKlxuICogYGVuY29kZXJVcmxgIC8gYGRlY29kZXJVcmxgIHBvaW50IGF0IHRoZSBwdWJsaWMgSEYtaG9zdGVkIE9OTlggcGFpcnMgYnlcbiAqIGRlZmF1bHQsIHNvIHRoZSBzZWdtZW50IHRvb2xzIHdvcmsgb3V0IG9mIHRoZSBib3ggaW4gYW55IGhvc3QgKG1pcnJvcmluZyB0aGVcbiAqIGNlbGxwb3NlIGRlZmF1bHQpLiBBIGhvc3QgY2FuIHJlcG9pbnQgdGhlbSBhdCBpdHMgb3duIGhvc3RpbmcgKGUuZy4gYSBHQ1NcbiAqIGJ1Y2tldCkgYXQgcnVudGltZSB2aWEge0BsaW5rIHNldFNhbU1vZGVsVXJsc307IGFuIGVtcHR5IFVSTCBkaXNhYmxlcyBhIG1vZGVsXG4gKiAodGhlIHNlc3Npb24gdGhyb3dzIGEgY2xlYXIgXCJub3QgY29uZmlndXJlZFwiIGVycm9yKS4gRXhwb3J0L3F1YW50aXphdGlvblxuICogdG9vbGluZzogdGhlIHNpYmxpbmcgYGJyb3dzZXItb25ueC10b29sc2AgcHJvamVjdDsgc2VlIGRvY3Mvc2FtLXNlZ21lbnRhdGlvbi1kZXNpZ24ubWQuXG4gKi9cbmV4cG9ydCBjb25zdCBTQU1fTU9ERUxTOiBTYW1Nb2RlbERlZltdID0gW1xuICB7XG4gICAgaWQ6ICdtaWNyb3NhbS12aXQtdC1sbScsXG4gICAgbGFiZWw6ICdtaWNyby1zYW0gVmlULVQnLFxuICAgIGVuY29kZXJVcmw6ICdodHRwczovL2h1Z2dpbmdmYWNlLmNvL0JhbGxvbjk5OS9taWNyb3NhbS12aXQtdC1sbS1vbm54L3Jlc29sdmUvbWFpbi9lbmNvZGVyLmZwMTYub25ueCcsXG4gICAgZGVjb2RlclVybDogJ2h0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vQmFsbG9uOTk5L21pY3Jvc2FtLXZpdC10LWxtLW9ubngvcmVzb2x2ZS9tYWluL2RlY29kZXIub25ueCcsXG4gICAgdmFyaWFudDogJ3NhbTEnLFxuICAgIGlucHV0U2l6ZTogMTAyNCxcbiAgICBtaWNyb3Njb3B5OiB0cnVlLFxuICAgIC8vIFRpbnlWaVQncyBmcDE2IGF0dGVudGlvbiBvdmVyZmxvd3Mgb24gdGhlIG9ubnhydW50aW1lLXdlYiBXZWJHUFUgRVAgYW5kXG4gICAgLy8gcmV0dXJucyBhbiBlbXB0eSBtYXNrIChcIk5vIG1hc2tzIGZvdW5kXCIpOyBpdCdzIG51bWVyaWNhbGx5IGNvcnJlY3Qgb25cbiAgICAvLyBXQVNNLCBhbmQgdGhlIGVuY29kZXIgaXMgdGlueSAofjE0IE1CKSBzbyBXQVNNIGlzIHBsZW50eSBmYXN0LlxuICAgIGVuY29kZXJQcm92aWRlcnM6IFsnd2FzbSddLFxuICAgIC8vIFNtYWxsIGVub3VnaCB0byBydW4gaW4tcHJvY2VzcyBvbiB0aGUgbWFpbiB0aHJlYWQg4oCUIGF2b2lkcyB0aGUgV2ViXG4gICAgLy8gV29ya2VyJ3Mgc3Bhd24gLyBzZWNvbmQtT1JULXJ1bnRpbWUgLyByb3VuZC10cmlwIG92ZXJoZWFkLCB3aGljaCBtYWRlIGl0XG4gICAgLy8gbm90aWNlYWJseSBzbG93ZXIgdG8gbG9hZCBhbmQgc2VnbWVudC5cbiAgICBpblByb2Nlc3M6IHRydWUsXG4gIH0sXG4gIHtcbiAgICBpZDogJ21pY3Jvc2FtLXZpdC1iLWxtJyxcbiAgICBsYWJlbDogJ21pY3JvLXNhbSBWaVQtQicsXG4gICAgZW5jb2RlclVybDogJ2h0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vQmFsbG9uOTk5L21pY3Jvc2FtLXZpdC1iLWxtLW9ubngvcmVzb2x2ZS9tYWluL2VuY29kZXIuZnAxNi5vbm54JyxcbiAgICBkZWNvZGVyVXJsOiAnaHR0cHM6Ly9odWdnaW5nZmFjZS5jby9CYWxsb245OTkvbWljcm9zYW0tdml0LWItbG0tb25ueC9yZXNvbHZlL21haW4vZGVjb2Rlci5vbm54JyxcbiAgICB2YXJpYW50OiAnc2FtMScsXG4gICAgaW5wdXRTaXplOiAxMDI0LFxuICAgIG1pY3Jvc2NvcHk6IHRydWUsXG4gIH0sXG4gIHtcbiAgICBpZDogJ3BhdGhvLXNhbS12aXQtYicsXG4gICAgbGFiZWw6ICdwYXRoby1zYW0gVmlULUInLFxuICAgIGVuY29kZXJVcmw6ICdodHRwczovL2h1Z2dpbmdmYWNlLmNvL0JhbGxvbjk5OS9wYXRoby1zYW0tdml0LWItb25ueC9yZXNvbHZlL21haW4vZW5jb2Rlci5mcDE2Lm9ubngnLFxuICAgIGRlY29kZXJVcmw6ICdodHRwczovL2h1Z2dpbmdmYWNlLmNvL0JhbGxvbjk5OS9wYXRoby1zYW0tdml0LWItb25ueC9yZXNvbHZlL21haW4vZGVjb2Rlci5vbm54JyxcbiAgICB2YXJpYW50OiAnc2FtMScsXG4gICAgaW5wdXRTaXplOiAxMDI0LFxuICAgIG1pY3Jvc2NvcHk6IHRydWUsXG4gIH0sXG4gIHtcbiAgICBpZDogJ3BhdGhvLXNhbS12aXQtYi1pbnQ4JyxcbiAgICBsYWJlbDogJ3BhdGhvLXNhbSBWaVQtQiAoaW50OCknLFxuICAgIGVuY29kZXJVcmw6ICdodHRwczovL2h1Z2dpbmdmYWNlLmNvL0JhbGxvbjk5OS9wYXRoby1zYW0tdml0LWItb25ueC9yZXNvbHZlL21haW4vZW5jb2Rlci5pbnQ4Lm9ubngnLFxuICAgIGRlY29kZXJVcmw6ICdodHRwczovL2h1Z2dpbmdmYWNlLmNvL0JhbGxvbjk5OS9wYXRoby1zYW0tdml0LWItb25ueC9yZXNvbHZlL21haW4vZGVjb2Rlci5vbm54JyxcbiAgICB2YXJpYW50OiAnc2FtMScsXG4gICAgaW5wdXRTaXplOiAxMDI0LFxuICAgIG1pY3Jvc2NvcHk6IHRydWUsXG4gICAgLy8gaW50OCBkeW5hbWljLXF1YW50aXplZCBlbmNvZGVyICh+MTAwIE1CIHZzIH4xODAgTUIgZnAxNiwgSW9VIH4wLjk5IG9uIHRoZVxuICAgIC8vIHNhbml0eSB0ZXN0KS4gb25ueHJ1bnRpbWUtd2ViJ3MgV2ViR1BVIEVQIGRvZXNuJ3Qgc3VwcG9ydCBpbnQ4IG1hdG11bCwgc29cbiAgICAvLyBpdCBydW5zIG9uIFdBU00g4oCUIHNtYWxsZXIgZG93bmxvYWQsIHNsb3dlciBlbmNvZGUgdGhhbiB0aGUgZnAxNiBlbnRyeS5cbiAgICBlbmNvZGVyUHJvdmlkZXJzOiBbJ3dhc20nXSxcbiAgfSxcbl07XG5cbi8qKiBJbml0aWFsIGRlZmF1bHQgbW9kZWwgaWQgKG92ZXJyaWRkZW4gYXQgcnVudGltZSBvbmNlIHRoZSBob3N0IGNvbmZpZ3VyZXMgYVxuICogIGhvc3RlZCBtb2RlbCB2aWEge0BsaW5rIHNldFNhbU1vZGVsVXJsc30pLiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0FNX01PREVMX0lEID0gU0FNX01PREVMU1swXS5pZDtcblxuLyoqIFRoZSBhY3RpdmUgZGVmYXVsdCDigJQgdXBkYXRlZCB3aGVuIHRoZSBob3N0IGNvbmZpZ3VyZXMgYSBtb2RlbCdzIE9OTlggVVJMcyxcbiAqICBzbyB0aGUgdG9vbCB1c2VzIHRoZSBtb2RlbCB0aGF0J3MgYWN0dWFsbHkgaG9zdGVkIChub3QganVzdCB0aGUgZmlyc3QgZW50cnkpLiAqL1xubGV0IGFjdGl2ZURlZmF1bHRJZCA9IERFRkFVTFRfU0FNX01PREVMX0lEO1xuXG4vKiogTG9vayB1cCBhIG1vZGVsIGJ5IGlkOyBmYWxscyBiYWNrIHRvIHRoZSBhY3RpdmUgZGVmYXVsdCB3aGVuIGlkIGlzXG4gKiAgdW5rbm93bi9hYnNlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FtTW9kZWwoaWQ/OiBzdHJpbmcpOiBTYW1Nb2RlbERlZiB7XG4gIGNvbnN0IHdhbnRlZCA9IGlkID8/IGFjdGl2ZURlZmF1bHRJZDtcbiAgcmV0dXJuIFNBTV9NT0RFTFMuZmluZCgobSkgPT4gbS5pZCA9PT0gd2FudGVkKSA/PyBTQU1fTU9ERUxTWzBdO1xufVxuXG4vKiogVGhlIGFjdGl2ZSBkZWZhdWx0IG1vZGVsIGlkICh3aGF0IHRoZSB0b29scy9waWNrZXIgdXNlIHdoZW4gdW5zZXQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRTYW1Nb2RlbElkKCk6IHN0cmluZyB7XG4gIHJldHVybiBhY3RpdmVEZWZhdWx0SWQ7XG59XG5cbi8qKiBTZXQgdGhlIGFjdGl2ZSBkZWZhdWx0IG1vZGVsIGlkIChtdXN0IGJlIGEgcmVnaXN0ZXJlZCBtb2RlbCkuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0RGVmYXVsdFNhbU1vZGVsKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKFNBTV9NT0RFTFMuc29tZSgobSkgPT4gbS5pZCA9PT0gaWQpKSBhY3RpdmVEZWZhdWx0SWQgPSBpZDtcbn1cblxuLyoqIFRydWUgd2hlbiBhIG1vZGVsIGhhcyBib3RoIE9OTlggVVJMcyBjb25maWd1cmVkIChpLmUuIGl0IGNhbiBhY3R1YWxseSBydW4pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2FtTW9kZWxSZWFkeShtb2RlbDogU2FtTW9kZWxEZWYpOiBib29sZWFuIHtcbiAgcmV0dXJuICEhbW9kZWwuZW5jb2RlclVybCAmJiAhIW1vZGVsLmRlY29kZXJVcmw7XG59XG5cbi8qKlxuICogUG9pbnQgYSByZWdpc3RlcmVkIG1vZGVsIGF0IGl0cyBob3N0ZWQgT05OWCBwYWlyIChIRiAvIEdDUykuIENhbGxlZCBieSB0aGVcbiAqIGhvc3QncyBjb21wb3NpdGlvbiByb290IG9uY2UgaG9zdGluZyBpcyBkZWNpZGVkLCBrZWVwaW5nIGRlcGxveW1lbnQgVVJMcyBvdXRcbiAqIG9mIHRoZSBsaWJyYXJ5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0U2FtTW9kZWxVcmxzKGlkOiBzdHJpbmcsIGVuY29kZXJVcmw6IHN0cmluZywgZGVjb2RlclVybDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IG0gPSBTQU1fTU9ERUxTLmZpbmQoKHgpID0+IHguaWQgPT09IGlkKTtcbiAgaWYgKG0pIHtcbiAgICBtLmVuY29kZXJVcmwgPSBlbmNvZGVyVXJsO1xuICAgIG0uZGVjb2RlclVybCA9IGRlY29kZXJVcmw7XG4gICAgLy8gVGhlIGNvbmZpZ3VyZWQgKGhvc3RlZCkgbW9kZWwgYmVjb21lcyB0aGUgYWN0aXZlIGRlZmF1bHQsIHNvIHRoZSB0b29sc1xuICAgIC8vIHVzZSBpdCByYXRoZXIgdGhhbiB0aGUgZmlyc3QgcmVnaXN0cnkgZW50cnkgKHdoaWNoIG1heSBiZSB1bmhvc3RlZCkuXG4gICAgaWYgKGVuY29kZXJVcmwgJiYgZGVjb2RlclVybCkgYWN0aXZlRGVmYXVsdElkID0gaWQ7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as ort from 'onnxruntime-web';
|
|
2
|
+
/**
|
|
3
|
+
* Shared, DOM-free SAM inference primitives used by BOTH inference backends:
|
|
4
|
+
* the in-process session (`OnnxSamSession`, main thread) and the dedicated
|
|
5
|
+
* Web Worker (`onnx-sam.worker`). Keeping these here avoids duplicating the
|
|
6
|
+
* preprocessing / decoder-prompt math and keeps the worker DOM-free (it can't
|
|
7
|
+
* import sam-prompt.ts, which pulls in DOM types).
|
|
8
|
+
*/
|
|
9
|
+
export const PIXEL_MEAN = [123.675, 116.28, 103.53];
|
|
10
|
+
export const PIXEL_STD = [58.395, 57.12, 57.375];
|
|
11
|
+
const MODEL_CACHE = 'sam-onnx';
|
|
12
|
+
/** Fetch a model as an ArrayBuffer, streaming progress and caching in the Cache
|
|
13
|
+
* API (so it isn't re-downloaded). Cache hit → progress jumps to 1. Works on
|
|
14
|
+
* the main thread and in a worker (both have `fetch` + `caches`). */
|
|
15
|
+
export async function fetchModel(url, onProgress) {
|
|
16
|
+
const cache = typeof caches !== 'undefined' ? await caches.open(MODEL_CACHE).catch(() => null) : null;
|
|
17
|
+
const hit = cache ? await cache.match(url) : null;
|
|
18
|
+
if (hit) {
|
|
19
|
+
onProgress?.(1);
|
|
20
|
+
return await hit.arrayBuffer();
|
|
21
|
+
}
|
|
22
|
+
const resp = await fetch(url);
|
|
23
|
+
if (!resp.ok)
|
|
24
|
+
throw new Error(`fetch ${url} failed: HTTP ${resp.status}`);
|
|
25
|
+
const total = Number(resp.headers.get('content-length')) || 0;
|
|
26
|
+
if (!resp.body || !total) {
|
|
27
|
+
const buf = await resp.arrayBuffer();
|
|
28
|
+
onProgress?.(1);
|
|
29
|
+
if (cache)
|
|
30
|
+
await cache.put(url, new Response(buf)).catch(() => undefined);
|
|
31
|
+
return buf;
|
|
32
|
+
}
|
|
33
|
+
const reader = resp.body.getReader();
|
|
34
|
+
const chunks = [];
|
|
35
|
+
let received = 0;
|
|
36
|
+
for (;;) {
|
|
37
|
+
const { done, value } = await reader.read();
|
|
38
|
+
if (done)
|
|
39
|
+
break;
|
|
40
|
+
chunks.push(value);
|
|
41
|
+
received += value.length;
|
|
42
|
+
onProgress?.(received / total);
|
|
43
|
+
}
|
|
44
|
+
const out = new Uint8Array(received);
|
|
45
|
+
let off = 0;
|
|
46
|
+
for (const c of chunks) {
|
|
47
|
+
out.set(c, off);
|
|
48
|
+
off += c.length;
|
|
49
|
+
}
|
|
50
|
+
if (cache) {
|
|
51
|
+
await cache.put(url, new Response(out.slice(), { headers: { 'content-length': String(received) } }))
|
|
52
|
+
.catch(() => undefined);
|
|
53
|
+
}
|
|
54
|
+
onProgress?.(1);
|
|
55
|
+
return out.buffer;
|
|
56
|
+
}
|
|
57
|
+
/** Resize (long side → size, bilinear), pad to size×size, SAM-normalize → CHW float32. */
|
|
58
|
+
export function preprocess(data, width, height, size, scale) {
|
|
59
|
+
const newW = Math.round(width * scale);
|
|
60
|
+
const newH = Math.round(height * scale);
|
|
61
|
+
const chw = new Float32Array(3 * size * size); // zero-padded
|
|
62
|
+
for (let y = 0; y < newH; y++) {
|
|
63
|
+
const sy = Math.min(height - 1, y / scale);
|
|
64
|
+
const y0 = Math.floor(sy);
|
|
65
|
+
const fy = sy - y0;
|
|
66
|
+
const y1 = Math.min(height - 1, y0 + 1);
|
|
67
|
+
for (let x = 0; x < newW; x++) {
|
|
68
|
+
const sx = Math.min(width - 1, x / scale);
|
|
69
|
+
const x0 = Math.floor(sx);
|
|
70
|
+
const fx = sx - x0;
|
|
71
|
+
const x1 = Math.min(width - 1, x0 + 1);
|
|
72
|
+
for (let c = 0; c < 3; c++) {
|
|
73
|
+
const p00 = data[(y0 * width + x0) * 4 + c];
|
|
74
|
+
const p01 = data[(y0 * width + x1) * 4 + c];
|
|
75
|
+
const p10 = data[(y1 * width + x0) * 4 + c];
|
|
76
|
+
const p11 = data[(y1 * width + x1) * 4 + c];
|
|
77
|
+
const top = p00 + (p01 - p00) * fx;
|
|
78
|
+
const bot = p10 + (p11 - p10) * fx;
|
|
79
|
+
const v = top + (bot - top) * fy;
|
|
80
|
+
chw[c * size * size + y * size + x] = (v - PIXEL_MEAN[c]) / PIXEL_STD[c];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return chw;
|
|
85
|
+
}
|
|
86
|
+
/** Assemble decoder `point_coords`/`point_labels` from a prompt, in encoder
|
|
87
|
+
* (resized) space. Box = two points labelled 2/3; points use 1/0; a points-only
|
|
88
|
+
* prompt pads the absent box slot with `[0,0]` labelled -1. */
|
|
89
|
+
export function buildDecoderPrompt(prompt, scale) {
|
|
90
|
+
const coords = [];
|
|
91
|
+
const labels = [];
|
|
92
|
+
for (const p of prompt.points ?? []) {
|
|
93
|
+
coords.push(p.x * scale, p.y * scale);
|
|
94
|
+
labels.push(p.label);
|
|
95
|
+
}
|
|
96
|
+
if (prompt.box) {
|
|
97
|
+
const b = prompt.box;
|
|
98
|
+
coords.push(b.x0 * scale, b.y0 * scale);
|
|
99
|
+
labels.push(2);
|
|
100
|
+
coords.push(b.x1 * scale, b.y1 * scale);
|
|
101
|
+
labels.push(3);
|
|
102
|
+
}
|
|
103
|
+
else if (labels.length > 0) {
|
|
104
|
+
coords.push(0, 0);
|
|
105
|
+
labels.push(-1);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
pointCoords: Float32Array.from(coords),
|
|
109
|
+
pointLabels: Float32Array.from(labels),
|
|
110
|
+
numPoints: labels.length,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** Binarize mask logits (`> threshold`) into a 0/1 mask. */
|
|
114
|
+
export function binarizeMask(logits, threshold = 0) {
|
|
115
|
+
const out = new Uint8Array(logits.length);
|
|
116
|
+
for (let i = 0; i < logits.length; i++)
|
|
117
|
+
out[i] = logits[i] > threshold ? 1 : 0;
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/** Index of the highest-scoring mask in a multimask decoder output. */
|
|
121
|
+
export function bestMaskIndex(iou) {
|
|
122
|
+
let best = 0;
|
|
123
|
+
for (let i = 1; i < iou.length; i++)
|
|
124
|
+
if (iou[i] > iou[best])
|
|
125
|
+
best = i;
|
|
126
|
+
return best;
|
|
127
|
+
}
|
|
128
|
+
/** Run the encoder on an RGBA image → a reusable embedding. */
|
|
129
|
+
export async function runEncoder(encoder, data, width, height, inputSize) {
|
|
130
|
+
const scale = inputSize / Math.max(width, height);
|
|
131
|
+
const input = preprocess(data, width, height, inputSize, scale);
|
|
132
|
+
const out = await encoder.run({
|
|
133
|
+
[encoder.inputNames[0]]: new ort.Tensor('float32', input, [1, 3, inputSize, inputSize]),
|
|
134
|
+
});
|
|
135
|
+
const emb = out[encoder.outputNames[0]];
|
|
136
|
+
return {
|
|
137
|
+
data: emb.data, dims: emb.dims,
|
|
138
|
+
scale, imageWidth: width, imageHeight: height,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** Run the decoder for one prompt against a cached embedding → a binary mask. */
|
|
142
|
+
export async function runDecoder(decoder, e, prompt) {
|
|
143
|
+
const { pointCoords, pointLabels, numPoints } = buildDecoderPrompt(prompt, e.scale);
|
|
144
|
+
const out = await decoder.run({
|
|
145
|
+
image_embeddings: new ort.Tensor('float32', e.data, e.dims),
|
|
146
|
+
point_coords: new ort.Tensor('float32', pointCoords, [1, numPoints, 2]),
|
|
147
|
+
point_labels: new ort.Tensor('float32', pointLabels, [1, numPoints]),
|
|
148
|
+
mask_input: new ort.Tensor('float32', new Float32Array(256 * 256), [1, 1, 256, 256]),
|
|
149
|
+
has_mask_input: new ort.Tensor('float32', Float32Array.from([0]), [1]),
|
|
150
|
+
orig_im_size: new ort.Tensor('float32', Float32Array.from([e.imageHeight, e.imageWidth]), [2]),
|
|
151
|
+
});
|
|
152
|
+
const masks = out['masks'] ?? out[decoder.outputNames[0]];
|
|
153
|
+
const iou = out['iou_predictions']?.data ?? Float32Array.from([1]);
|
|
154
|
+
const [, m, h, w] = masks.dims;
|
|
155
|
+
const idx = bestMaskIndex(iou.slice(0, m));
|
|
156
|
+
const logits = masks.data.subarray(idx * h * w, (idx + 1) * h * w);
|
|
157
|
+
return { mask: binarizeMask(logits), width: w, height: h, iou: iou[idx] ?? 1 };
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FtLW9ubngtY29yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24vc2FtLW9ubngtY29yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDO0FBSXZDOzs7Ozs7R0FNRztBQUVILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDcEQsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztBQUNqRCxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUM7QUFtQi9COztzRUFFc0U7QUFDdEUsTUFBTSxDQUFDLEtBQUssVUFBVSxVQUFVLENBQUMsR0FBVyxFQUFFLFVBQWdDO0lBQzVFLE1BQU0sS0FBSyxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3RHLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDbEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQUMsT0FBTyxNQUFNLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUFDLENBQUM7SUFFN0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQUUs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RyxLQUFLLENBQUMsQ0FBQztRQUMzQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzFCLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDbkIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDOUIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQztZQUMxQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzFCLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDbkIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN2QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzNCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUM1QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUssR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FB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TSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQy9GLENBQUMsQ0FBQztJQUNILE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELE1BQU0sR0FBRyxHQUFJLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLElBQXFCLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBZ0IsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQyxNQUFNLE1BQU0sR0FBSSxLQUFLLENBQUMsSUFBcUIsQ0FBQyxRQUFRLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLE9BQU8sRUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ2pGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcnQgZnJvbSAnb25ueHJ1bnRpbWUtd2ViJztcblxuaW1wb3J0IHR5cGUgeyBTYW1Qcm9tcHQgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvc2FtLmNvbnRyYWN0JztcblxuLyoqXG4gKiBTaGFyZWQsIERPTS1mcmVlIFNBTSBpbmZlcmVuY2UgcHJpbWl0aXZlcyB1c2VkIGJ5IEJPVEggaW5mZXJlbmNlIGJhY2tlbmRzOlxuICogdGhlIGluLXByb2Nlc3Mgc2Vzc2lvbiAoYE9ubnhTYW1TZXNzaW9uYCwgbWFpbiB0aHJlYWQpIGFuZCB0aGUgZGVkaWNhdGVkXG4gKiBXZWIgV29ya2VyIChgb25ueC1zYW0ud29ya2VyYCkuIEtlZXBpbmcgdGhlc2UgaGVyZSBhdm9pZHMgZHVwbGljYXRpbmcgdGhlXG4gKiBwcmVwcm9jZXNzaW5nIC8gZGVjb2Rlci1wcm9tcHQgbWF0aCBhbmQga2VlcHMgdGhlIHdvcmtlciBET00tZnJlZSAoaXQgY2FuJ3RcbiAqIGltcG9ydCBzYW0tcHJvbXB0LnRzLCB3aGljaCBwdWxscyBpbiBET00gdHlwZXMpLlxuICovXG5cbmV4cG9ydCBjb25zdCBQSVhFTF9NRUFOID0gWzEyMy42NzUsIDExNi4yOCwgMTAzLjUzXTtcbmV4cG9ydCBjb25zdCBQSVhFTF9TVEQgPSBbNTguMzk1LCA1Ny4xMiwgNTcuMzc1XTtcbmNvbnN0IE1PREVMX0NBQ0hFID0gJ3NhbS1vbm54JztcblxuLyoqIEVuY29kZXIgb3V0cHV0IGZvciBvbmUgaW1hZ2UsIHJldXNlZCBhY3Jvc3MgcHJvbXB0cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29yZUVtYmVkZGluZyB7XG4gIGRhdGE6IEZsb2F0MzJBcnJheTtcbiAgZGltczogbnVtYmVyW107XG4gIHNjYWxlOiBudW1iZXI7XG4gIGltYWdlV2lkdGg6IG51bWJlcjtcbiAgaW1hZ2VIZWlnaHQ6IG51bWJlcjtcbn1cblxuLyoqIERlY29kZXIgb3V0cHV0OiBhIGJpbmFyeSBtYXNrIGF0IG9yaWdpbmFsLWltYWdlIHJlc29sdXRpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIENvcmVNYXNrIHtcbiAgbWFzazogVWludDhBcnJheTtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG4gIGlvdTogbnVtYmVyO1xufVxuXG4vKiogRmV0Y2ggYSBtb2RlbCBhcyBhbiBBcnJheUJ1ZmZlciwgc3RyZWFtaW5nIHByb2dyZXNzIGFuZCBjYWNoaW5nIGluIHRoZSBDYWNoZVxuICogIEFQSSAoc28gaXQgaXNuJ3QgcmUtZG93bmxvYWRlZCkuIENhY2hlIGhpdCDihpIgcHJvZ3Jlc3MganVtcHMgdG8gMS4gV29ya3Mgb25cbiAqICB0aGUgbWFpbiB0aHJlYWQgYW5kIGluIGEgd29ya2VyIChib3RoIGhhdmUgYGZldGNoYCArIGBjYWNoZXNgKS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaE1vZGVsKHVybDogc3RyaW5nLCBvblByb2dyZXNzPzogKGY6IG51bWJlcikgPT4gdm9pZCk6IFByb21pc2U8QXJyYXlCdWZmZXI+IHtcbiAgY29uc3QgY2FjaGUgPSB0eXBlb2YgY2FjaGVzICE9PSAndW5kZWZpbmVkJyA/IGF3YWl0IGNhY2hlcy5vcGVuKE1PREVMX0NBQ0hFKS5jYXRjaCgoKSA9PiBudWxsKSA6IG51bGw7XG4gIGNvbnN0IGhpdCA9IGNhY2hlID8gYXdhaXQgY2FjaGUubWF0Y2godXJsKSA6IG51bGw7XG4gIGlmIChoaXQpIHsgb25Qcm9ncmVzcz8uKDEpOyByZXR1cm4gYXdhaXQgaGl0LmFycmF5QnVmZmVyKCk7IH1cblxuICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2godXJsKTtcbiAgaWYgKCFyZXNwLm9rKSB0aHJvdyBuZXcgRXJyb3IoYGZldGNoICR7dXJsfSBmYWlsZWQ6IEhUVFAgJHtyZXNwLnN0YXR1c31gKTtcbiAgY29uc3QgdG90YWwgPSBOdW1iZXIocmVzcC5oZWFkZXJzLmdldCgnY29udGVudC1sZW5ndGgnKSkgfHwgMDtcbiAgaWYgKCFyZXNwLmJvZHkgfHwgIXRvdGFsKSB7XG4gICAgY29uc3QgYnVmID0gYXdhaXQgcmVzcC5hcnJheUJ1ZmZlcigpO1xuICAgIG9uUHJvZ3Jlc3M/LigxKTtcbiAgICBpZiAoY2FjaGUpIGF3YWl0IGNhY2hlLnB1dCh1cmwsIG5ldyBSZXNwb25zZShidWYpKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIHJldHVybiBidWY7XG4gIH1cbiAgY29uc3QgcmVhZGVyID0gcmVzcC5ib2R5LmdldFJlYWRlcigpO1xuICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuICBsZXQgcmVjZWl2ZWQgPSAwO1xuICBmb3IgKDs7KSB7XG4gICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICBpZiAoZG9uZSkgYnJlYWs7XG4gICAgY2h1bmtzLnB1c2godmFsdWUpO1xuICAgIHJlY2VpdmVkICs9IHZhbHVlLmxlbmd0aDtcbiAgICBvblByb2dyZXNzPy4ocmVjZWl2ZWQgLyB0b3RhbCk7XG4gIH1cbiAgY29uc3Qgb3V0ID0gbmV3IFVpbnQ4QXJyYXkocmVjZWl2ZWQpO1xuICBsZXQgb2ZmID0gMDtcbiAgZm9yIChjb25zdCBjIG9mIGNodW5rcykgeyBvdXQuc2V0KGMsIG9mZik7IG9mZiArPSBjLmxlbmd0aDsgfVxuICBpZiAoY2FjaGUpIHtcbiAgICBhd2FpdCBjYWNoZS5wdXQodXJsLCBuZXcgUmVzcG9uc2Uob3V0LnNsaWNlKCksIHsgaGVhZGVyczogeyAnY29udGVudC1sZW5ndGgnOiBTdHJpbmcocmVjZWl2ZWQpIH0gfSkpXG4gICAgICAuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgfVxuICBvblByb2dyZXNzPy4oMSk7XG4gIHJldHVybiBvdXQuYnVmZmVyO1xufVxuXG4vKiogUmVzaXplIChsb25nIHNpZGUg4oaSIHNpemUsIGJpbGluZWFyKSwgcGFkIHRvIHNpemXDl3NpemUsIFNBTS1ub3JtYWxpemUg4oaSIENIVyBmbG9hdDMyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZXByb2Nlc3MoXG4gIGRhdGE6IFVpbnQ4Q2xhbXBlZEFycmF5LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgc2l6ZTogbnVtYmVyLCBzY2FsZTogbnVtYmVyLFxuKTogRmxvYXQzMkFycmF5IHtcbiAgY29uc3QgbmV3VyA9IE1hdGgucm91bmQod2lkdGggKiBzY2FsZSk7XG4gIGNvbnN0IG5ld0ggPSBNYXRoLnJvdW5kKGhlaWdodCAqIHNjYWxlKTtcbiAgY29uc3QgY2h3ID0gbmV3IEZsb2F0MzJBcnJheSgzICogc2l6ZSAqIHNpemUpOyAvLyB6ZXJvLXBhZGRlZFxuICBmb3IgKGxldCB5ID0gMDsgeSA8IG5ld0g7IHkrKykge1xuICAgIGNvbnN0IHN5ID0gTWF0aC5taW4oaGVpZ2h0IC0gMSwgeSAvIHNjYWxlKTtcbiAgICBjb25zdCB5MCA9IE1hdGguZmxvb3Ioc3kpO1xuICAgIGNvbnN0IGZ5ID0gc3kgLSB5MDtcbiAgICBjb25zdCB5MSA9IE1hdGgubWluKGhlaWdodCAtIDEsIHkwICsgMSk7XG4gICAgZm9yIChsZXQgeCA9IDA7IHggPCBuZXdXOyB4KyspIHtcbiAgICAgIGNvbnN0IHN4ID0gTWF0aC5taW4od2lkdGggLSAxLCB4IC8gc2NhbGUpO1xuICAgICAgY29uc3QgeDAgPSBNYXRoLmZsb29yKHN4KTtcbiAgICAgIGNvbnN0IGZ4ID0gc3ggLSB4MDtcbiAgICAgIGNvbnN0IHgxID0gTWF0aC5taW4od2lkdGggLSAxLCB4MCArIDEpO1xuICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCAzOyBjKyspIHtcbiAgICAgICAgY29uc3QgcDAwID0gZGF0YVsoeTAgKiB3aWR0aCArIHgwKSAqIDQgKyBjXTtcbiAgICAgICAgY29uc3QgcDAxID0gZGF0YVsoeTAgKiB3aWR0aCArIHgxKSAqIDQgKyBjXTtcbiAgICAgICAgY29uc3QgcDEwID0gZGF0YVsoeTEgKiB3aWR0aCArIHgwKSAqIDQgKyBjXTtcbiAgICAgICAgY29uc3QgcDExID0gZGF0YVsoeTEgKiB3aWR0aCArIHgxKSAqIDQgKyBjXTtcbiAgICAgICAgY29uc3QgdG9wID0gcDAwICsgKHAwMSAtIHAwMCkgKiBmeDtcbiAgICAgICAgY29uc3QgYm90ID0gcDEwICsgKHAxMSAtIHAxMCkgKiBmeDtcbiAgICAgICAgY29uc3QgdiA9IHRvcCArIChib3QgLSB0b3ApICogZnk7XG4gICAgICAgIGNod1tjICogc2l6ZSAqIHNpemUgKyB5ICogc2l6ZSArIHhdID0gKHYgLSBQSVhFTF9NRUFOW2NdKSAvIFBJWEVMX1NURFtjXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNodztcbn1cblxuLyoqIEFzc2VtYmxlIGRlY29kZXIgYHBvaW50X2Nvb3Jkc2AvYHBvaW50X2xhYmVsc2AgZnJvbSBhIHByb21wdCwgaW4gZW5jb2RlclxuICogIChyZXNpemVkKSBzcGFjZS4gQm94ID0gdHdvIHBvaW50cyBsYWJlbGxlZCAyLzM7IHBvaW50cyB1c2UgMS8wOyBhIHBvaW50cy1vbmx5XG4gKiAgcHJvbXB0IHBhZHMgdGhlIGFic2VudCBib3ggc2xvdCB3aXRoIGBbMCwwXWAgbGFiZWxsZWQgLTEuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGREZWNvZGVyUHJvbXB0KFxuICBwcm9tcHQ6IFNhbVByb21wdCwgc2NhbGU6IG51bWJlcixcbik6IHsgcG9pbnRDb29yZHM6IEZsb2F0MzJBcnJheTsgcG9pbnRMYWJlbHM6IEZsb2F0MzJBcnJheTsgbnVtUG9pbnRzOiBudW1iZXIgfSB7XG4gIGNvbnN0IGNvb3JkczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgbGFiZWxzOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHAgb2YgcHJvbXB0LnBvaW50cyA/PyBbXSkgeyBjb29yZHMucHVzaChwLnggKiBzY2FsZSwgcC55ICogc2NhbGUpOyBsYWJlbHMucHVzaChwLmxhYmVsKTsgfVxuICBpZiAocHJvbXB0LmJveCkge1xuICAgIGNvbnN0IGIgPSBwcm9tcHQuYm94O1xuICAgIGNvb3Jkcy5wdXNoKGIueDAgKiBzY2FsZSwgYi55MCAqIHNjYWxlKTsgbGFiZWxzLnB1c2goMik7XG4gICAgY29vcmRzLnB1c2goYi54MSAqIHNjYWxlLCBiLnkxICogc2NhbGUpOyBsYWJlbHMucHVzaCgzKTtcbiAgfSBlbHNlIGlmIChsYWJlbHMubGVuZ3RoID4gMCkge1xuICAgIGNvb3Jkcy5wdXNoKDAsIDApOyBsYWJlbHMucHVzaCgtMSk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBwb2ludENvb3JkczogRmxvYXQzMkFycmF5LmZyb20oY29vcmRzKSxcbiAgICBwb2ludExhYmVsczogRmxvYXQzMkFycmF5LmZyb20obGFiZWxzKSxcbiAgICBudW1Qb2ludHM6IGxhYmVscy5sZW5ndGgsXG4gIH07XG59XG5cbi8qKiBCaW5hcml6ZSBtYXNrIGxvZ2l0cyAoYD4gdGhyZXNob2xkYCkgaW50byBhIDAvMSBtYXNrLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJpbmFyaXplTWFzayhsb2dpdHM6IEZsb2F0MzJBcnJheSwgdGhyZXNob2xkID0gMCk6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBvdXQgPSBuZXcgVWludDhBcnJheShsb2dpdHMubGVuZ3RoKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsb2dpdHMubGVuZ3RoOyBpKyspIG91dFtpXSA9IGxvZ2l0c1tpXSA+IHRocmVzaG9sZCA/IDEgOiAwO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKiogSW5kZXggb2YgdGhlIGhpZ2hlc3Qtc2NvcmluZyBtYXNrIGluIGEgbXVsdGltYXNrIGRlY29kZXIgb3V0cHV0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJlc3RNYXNrSW5kZXgoaW91OiBGbG9hdDMyQXJyYXkgfCBudW1iZXJbXSk6IG51bWJlciB7XG4gIGxldCBiZXN0ID0gMDtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBpb3UubGVuZ3RoOyBpKyspIGlmIChpb3VbaV0gPiBpb3VbYmVzdF0pIGJlc3QgPSBpO1xuICByZXR1cm4gYmVzdDtcbn1cblxuLyoqIFJ1biB0aGUgZW5jb2RlciBvbiBhbiBSR0JBIGltYWdlIOKGkiBhIHJldXNhYmxlIGVtYmVkZGluZy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5FbmNvZGVyKFxuICBlbmNvZGVyOiBvcnQuSW5mZXJlbmNlU2Vzc2lvbiwgZGF0YTogVWludDhDbGFtcGVkQXJyYXksIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBpbnB1dFNpemU6IG51bWJlcixcbik6IFByb21pc2U8Q29yZUVtYmVkZGluZz4ge1xuICBjb25zdCBzY2FsZSA9IGlucHV0U2l6ZSAvIE1hdGgubWF4KHdpZHRoLCBoZWlnaHQpO1xuICBjb25zdCBpbnB1dCA9IHByZXByb2Nlc3MoZGF0YSwgd2lkdGgsIGhlaWdodCwgaW5wdXRTaXplLCBzY2FsZSk7XG4gIGNvbnN0IG91dCA9IGF3YWl0IGVuY29kZXIucnVuKHtcbiAgICBbZW5jb2Rlci5pbnB1dE5hbWVzWzBdXTogbmV3IG9ydC5UZW5zb3IoJ2Zsb2F0MzInLCBpbnB1dCwgWzEsIDMsIGlucHV0U2l6ZSwgaW5wdXRTaXplXSksXG4gIH0pO1xuICBjb25zdCBlbWIgPSBvdXRbZW5jb2Rlci5vdXRwdXROYW1lc1swXV07XG4gIHJldHVybiB7XG4gICAgZGF0YTogZW1iLmRhdGEgYXMgRmxvYXQzMkFycmF5LCBkaW1zOiBlbWIuZGltcyBhcyBudW1iZXJbXSxcbiAgICBzY2FsZSwgaW1hZ2VXaWR0aDogd2lkdGgsIGltYWdlSGVpZ2h0OiBoZWlnaHQsXG4gIH07XG59XG5cbi8qKiBSdW4gdGhlIGRlY29kZXIgZm9yIG9uZSBwcm9tcHQgYWdhaW5zdCBhIGNhY2hlZCBlbWJlZGRpbmcg4oaSIGEgYmluYXJ5IG1hc2suICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuRGVjb2RlcihcbiAgZGVjb2Rlcjogb3J0LkluZmVyZW5jZVNlc3Npb24sIGU6IENvcmVFbWJlZGRpbmcsIHByb21wdDogU2FtUHJvbXB0LFxuKTogUHJvbWlzZTxDb3JlTWFzaz4ge1xuICBjb25zdCB7IHBvaW50Q29vcmRzLCBwb2ludExhYmVscywgbnVtUG9pbnRzIH0gPSBidWlsZERlY29kZXJQcm9tcHQocHJvbXB0LCBlLnNjYWxlKTtcbiAgY29uc3Qgb3V0ID0gYXdhaXQgZGVjb2Rlci5ydW4oe1xuICAgIGltYWdlX2VtYmVkZGluZ3M6IG5ldyBvcnQuVGVuc29yKCdmbG9hdDMyJywgZS5kYXRhLCBlLmRpbXMpLFxuICAgIHBvaW50X2Nvb3JkczogbmV3IG9ydC5UZW5zb3IoJ2Zsb2F0MzInLCBwb2ludENvb3JkcywgWzEsIG51bVBvaW50cywgMl0pLFxuICAgIHBvaW50X2xhYmVsczogbmV3IG9ydC5UZW5zb3IoJ2Zsb2F0MzInLCBwb2ludExhYmVscywgWzEsIG51bVBvaW50c10pLFxuICAgIG1hc2tfaW5wdXQ6IG5ldyBvcnQuVGVuc29yKCdmbG9hdDMyJywgbmV3IEZsb2F0MzJBcnJheSgyNTYgKiAyNTYpLCBbMSwgMSwgMjU2LCAyNTZdKSxcbiAgICBoYXNfbWFza19pbnB1dDogbmV3IG9ydC5UZW5zb3IoJ2Zsb2F0MzInLCBGbG9hdDMyQXJyYXkuZnJvbShbMF0pLCBbMV0pLFxuICAgIG9yaWdfaW1fc2l6ZTogbmV3IG9ydC5UZW5zb3IoJ2Zsb2F0MzInLCBGbG9hdDMyQXJyYXkuZnJvbShbZS5pbWFnZUhlaWdodCwgZS5pbWFnZVdpZHRoXSksIFsyXSksXG4gIH0pO1xuICBjb25zdCBtYXNrcyA9IG91dFsnbWFza3MnXSA/PyBvdXRbZGVjb2Rlci5vdXRwdXROYW1lc1swXV07XG4gIGNvbnN0IGlvdSA9IChvdXRbJ2lvdV9wcmVkaWN0aW9ucyddPy5kYXRhIGFzIEZsb2F0MzJBcnJheSkgPz8gRmxvYXQzMkFycmF5LmZyb20oWzFdKTtcbiAgY29uc3QgWywgbSwgaCwgd10gPSBtYXNrcy5kaW1zIGFzIG51bWJlcltdO1xuICBjb25zdCBpZHggPSBiZXN0TWFza0luZGV4KGlvdS5zbGljZSgwLCBtKSk7XG4gIGNvbnN0IGxvZ2l0cyA9IChtYXNrcy5kYXRhIGFzIEZsb2F0MzJBcnJheSkuc3ViYXJyYXkoaWR4ICogaCAqIHcsIChpZHggKyAxKSAqIGggKiB3KTtcbiAgcmV0dXJuIHsgbWFzazogYmluYXJpemVNYXNrKGxvZ2l0cyksIHdpZHRoOiB3LCBoZWlnaHQ6IGgsIGlvdTogaW91W2lkeF0gPz8gMSB9O1xufVxuIl19
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { WandService } from '../wand/wand.service';
|
|
4
|
+
import { frameToRgba } from './sam-prompt';
|
|
5
|
+
import { getSamModel, isSamModelReady } from './sam-model-registry';
|
|
6
|
+
import { Region, Polygon } from '../../models/region';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "../wand/wand.service";
|
|
9
|
+
/** Interactive SAM point-prompt tool (jit-ui#90, P1).
|
|
10
|
+
*
|
|
11
|
+
* Each plain (positive) click segments the clicked object as its OWN new region
|
|
12
|
+
* — clicking a second fiber doesn't extend the first into it. Shift/Alt-click
|
|
13
|
+
* adds a negative (exclude) point that refines the CURRENT object, re-running
|
|
14
|
+
* the decoder against the (cached) image embedding and updating its live region.
|
|
15
|
+
* `commit()` (Enter) finalises early; `clear()` (Esc) discards the current
|
|
16
|
+
* prompt + its preview region. Mirrors the wand/brush on-canvas tool pattern and
|
|
17
|
+
* reuses WandService.maskToPolygons + the shared region store.
|
|
18
|
+
*
|
|
19
|
+
* Inference is behind {@link ISamSession} (lazy onnxruntime-web in production,
|
|
20
|
+
* a fake in tests).
|
|
21
|
+
*/
|
|
22
|
+
export class SamPointToolService {
|
|
23
|
+
constructor(wandService) {
|
|
24
|
+
this.wandService = wandService;
|
|
25
|
+
this.overlay = null;
|
|
26
|
+
this.session = null;
|
|
27
|
+
/** In-flight session load — dedupes a warm-up preload against the first click. */
|
|
28
|
+
this.sessionLoad = null;
|
|
29
|
+
this.model = getSamModel();
|
|
30
|
+
this.embedding = null;
|
|
31
|
+
this.embeddingKey = null;
|
|
32
|
+
/** Accumulated point prompts, in image (matrix) coords. */
|
|
33
|
+
this.points = [];
|
|
34
|
+
/** Id of the in-progress (preview) region being refined, if committed to store. */
|
|
35
|
+
this.regionId = null;
|
|
36
|
+
this.status$ = new BehaviorSubject('');
|
|
37
|
+
this.busy$ = new BehaviorSubject(false);
|
|
38
|
+
/** Encoder-download progress (0..1) on the first click; -1 when not downloading. */
|
|
39
|
+
this.progress$ = new BehaviorSubject(-1);
|
|
40
|
+
this.boundMouseDown = (e) => { void this.onMouseDown(e); };
|
|
41
|
+
}
|
|
42
|
+
bindHost(host) { this.host = host; }
|
|
43
|
+
setModel(id) {
|
|
44
|
+
const next = getSamModel(id);
|
|
45
|
+
if (next.id === this.model.id)
|
|
46
|
+
return;
|
|
47
|
+
this.model = next;
|
|
48
|
+
this.embedding = null;
|
|
49
|
+
this.embeddingKey = null;
|
|
50
|
+
// Drop the loaded session so the next run reloads the newly-picked model
|
|
51
|
+
// (ensureSession() returns the cached session as-is otherwise).
|
|
52
|
+
this.session?.dispose();
|
|
53
|
+
this.session = null;
|
|
54
|
+
this.sessionLoad = null;
|
|
55
|
+
}
|
|
56
|
+
/** Test seam: inject a fake/alternate session. */
|
|
57
|
+
useSession(session) { this.session = session; }
|
|
58
|
+
setMode(active) {
|
|
59
|
+
if (active) {
|
|
60
|
+
this.createOverlay();
|
|
61
|
+
// Warm up the model in the background as soon as the tool is armed, so the
|
|
62
|
+
// first click doesn't pay the (download +) session-build cost on its path.
|
|
63
|
+
this.preload();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this.destroyOverlay();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Eagerly load the model in the background (fire-and-forget). Safe to call
|
|
70
|
+
* repeatedly — it dedupes against an in-flight load and an existing session. */
|
|
71
|
+
preload() {
|
|
72
|
+
if (this.session || !isSamModelReady(this.model))
|
|
73
|
+
return;
|
|
74
|
+
void this.ensureSession().catch(() => undefined);
|
|
75
|
+
}
|
|
76
|
+
/** Finalise the current object: keep its region, start fresh next click. */
|
|
77
|
+
commit() {
|
|
78
|
+
this.points = [];
|
|
79
|
+
this.regionId = null;
|
|
80
|
+
this.status$.next('');
|
|
81
|
+
}
|
|
82
|
+
/** Discard the in-progress prompt + its preview region. */
|
|
83
|
+
clear() {
|
|
84
|
+
if (this.regionId != null) {
|
|
85
|
+
const regions = this.host.getRegions().filter((r) => r.id !== this.regionId);
|
|
86
|
+
this.host.setRegions(regions);
|
|
87
|
+
}
|
|
88
|
+
this.points = [];
|
|
89
|
+
this.regionId = null;
|
|
90
|
+
this.status$.next('');
|
|
91
|
+
}
|
|
92
|
+
// ── overlay lifecycle (mirrors the wand/brush tools) ────────────────────
|
|
93
|
+
createOverlay() {
|
|
94
|
+
const plotEl = this.host?.getOverlayContainer();
|
|
95
|
+
if (!plotEl || this.overlay)
|
|
96
|
+
return;
|
|
97
|
+
const canvas = document.createElement('canvas');
|
|
98
|
+
Object.assign(canvas.style, {
|
|
99
|
+
position: 'absolute', top: '0', left: '0', width: '100%', height: '100%',
|
|
100
|
+
cursor: 'crosshair', zIndex: '100',
|
|
101
|
+
});
|
|
102
|
+
canvas.width = plotEl.offsetWidth;
|
|
103
|
+
canvas.height = plotEl.offsetHeight;
|
|
104
|
+
plotEl.appendChild(canvas);
|
|
105
|
+
this.overlay = canvas;
|
|
106
|
+
canvas.addEventListener('mousedown', this.boundMouseDown);
|
|
107
|
+
}
|
|
108
|
+
destroyOverlay() {
|
|
109
|
+
if (!this.overlay)
|
|
110
|
+
return;
|
|
111
|
+
this.overlay.removeEventListener('mousedown', this.boundMouseDown);
|
|
112
|
+
this.overlay.remove();
|
|
113
|
+
this.overlay = null;
|
|
114
|
+
this.points = [];
|
|
115
|
+
this.regionId = null;
|
|
116
|
+
}
|
|
117
|
+
// ── per-click refinement ────────────────────────────────────────────────
|
|
118
|
+
async onMouseDown(e) {
|
|
119
|
+
if (e.button !== 0 || !this.overlay)
|
|
120
|
+
return;
|
|
121
|
+
// Re-entrancy guard: ignore clicks while a previous prompt is still
|
|
122
|
+
// downloading the model / encoding / decoding. Without it, clicking again
|
|
123
|
+
// during the slow first run (e.g. a ~172 MB ViT-B encode on WebGPU) launches
|
|
124
|
+
// concurrent downloads + GPU encodes that can overwhelm the GPU and freeze
|
|
125
|
+
// the tab. Each click is fast once the embedding is cached, so this only
|
|
126
|
+
// drops clicks made while genuinely busy.
|
|
127
|
+
if (this.busy$.value)
|
|
128
|
+
return;
|
|
129
|
+
const cached = this.host.getCachedImageData();
|
|
130
|
+
if (!cached || cached.frames.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
const transform = this.host.getCoordinateTransform();
|
|
133
|
+
if (!transform.isReady())
|
|
134
|
+
return;
|
|
135
|
+
const { x: dataX, y: dataY } = transform.clientToData(e.clientX, e.clientY);
|
|
136
|
+
if (!Number.isFinite(dataX) || !Number.isFinite(dataY))
|
|
137
|
+
return;
|
|
138
|
+
const rx = cached.ratios[0] || 1;
|
|
139
|
+
const ry = cached.ratios[0] || 1;
|
|
140
|
+
const ox = cached.originX ?? 0;
|
|
141
|
+
const oy = cached.originY ?? 0;
|
|
142
|
+
// Shift or Alt = negative (exclude) point.
|
|
143
|
+
const label = e.shiftKey || e.altKey ? 0 : 1;
|
|
144
|
+
// A plain positive click starts a NEW object: clicking another fiber must
|
|
145
|
+
// segment that fiber on its own, not accumulate with earlier points and
|
|
146
|
+
// grow the in-progress mask into the adjacent object (which would also
|
|
147
|
+
// overwrite a previously-segmented region). Only Shift/Alt (exclude) points
|
|
148
|
+
// refine the current object. This also clears any stale prompt left after a
|
|
149
|
+
// region was deleted, so the next click segments fresh instead of redrawing
|
|
150
|
+
// the old merged mask.
|
|
151
|
+
if (label === 1) {
|
|
152
|
+
this.points = [];
|
|
153
|
+
this.regionId = null;
|
|
154
|
+
}
|
|
155
|
+
this.points.push({ x: (dataX - ox) / rx, y: (dataY - oy) / ry, label });
|
|
156
|
+
// Mark busy BEFORE ensureSession: the first click downloads the encoder
|
|
157
|
+
// (~14–172 MB) and builds the session, which is the longest wait — without
|
|
158
|
+
// this the UI showed nothing running until that finished.
|
|
159
|
+
this.busy$.next(true);
|
|
160
|
+
try {
|
|
161
|
+
this.status$.next('Loading SAM model…');
|
|
162
|
+
const session = await this.ensureSession();
|
|
163
|
+
const key = [
|
|
164
|
+
this.host.getFileName() ?? '', this.host.getActiveFrameIndex(),
|
|
165
|
+
`${cached.width}x${cached.height}`, `${ox},${oy},${rx}`, this.model.id,
|
|
166
|
+
].join('|');
|
|
167
|
+
if (!this.embedding || this.embeddingKey !== key) {
|
|
168
|
+
this.status$.next('Encoding image…');
|
|
169
|
+
const rgba = frameToRgba(cached, this.host.getActiveFrameIndex());
|
|
170
|
+
this.embedding = await session.embed({ data: rgba, width: cached.width, height: cached.height });
|
|
171
|
+
this.embeddingKey = key;
|
|
172
|
+
}
|
|
173
|
+
this.status$.next('Segmenting…');
|
|
174
|
+
const prompt = { points: this.points.slice() };
|
|
175
|
+
const res = await session.decode(this.embedding, prompt);
|
|
176
|
+
const polys = this.wandService.maskToPolygons(res.mask, res.width, res.height, cached.width, cached.height, 0, 0);
|
|
177
|
+
if (polys.length === 0) {
|
|
178
|
+
this.status$.next('No mask for these points.');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const poly = polys[0];
|
|
182
|
+
this.upsertPreview(poly.xpoints.map((x) => ox + x * rx), poly.ypoints.map((y) => oy + y * ry));
|
|
183
|
+
this.status$.next('Segmented — click another fiber for a new region, Shift-click to refine, Esc to undo.');
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
this.status$.next(err instanceof Error ? err.message : 'SAM model unavailable.');
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
this.busy$.next(false);
|
|
190
|
+
this.progress$.next(-1);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** Replace (or insert) the in-progress preview region in the shared store. */
|
|
194
|
+
upsertPreview(xData, yData) {
|
|
195
|
+
if (xData.length < 3)
|
|
196
|
+
return;
|
|
197
|
+
const poly = new Polygon();
|
|
198
|
+
poly.npoints = xData.length;
|
|
199
|
+
poly.xpoints = xData;
|
|
200
|
+
poly.ypoints = yData;
|
|
201
|
+
poly.coordinates = xData.map((x, i) => [x, yData[i]]);
|
|
202
|
+
poly.closed = true;
|
|
203
|
+
const regions = this.host.getRegions();
|
|
204
|
+
const existing = this.regionId != null ? regions.find((r) => r.id === this.regionId) : null;
|
|
205
|
+
const region = new Region();
|
|
206
|
+
region.bounds = poly;
|
|
207
|
+
region.color = this.host.getShapeColor();
|
|
208
|
+
region.label = 'sam';
|
|
209
|
+
if (existing) {
|
|
210
|
+
region.id = existing.id;
|
|
211
|
+
region.name = existing.name;
|
|
212
|
+
const idx = regions.findIndex((r) => r.id === this.regionId);
|
|
213
|
+
if (idx >= 0)
|
|
214
|
+
regions[idx] = region;
|
|
215
|
+
else
|
|
216
|
+
regions.push(region);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
regions.push(region);
|
|
220
|
+
}
|
|
221
|
+
this.host.setRegions(regions);
|
|
222
|
+
this.regionId = region.id ?? this.regionId;
|
|
223
|
+
}
|
|
224
|
+
ensureSession() {
|
|
225
|
+
if (this.session)
|
|
226
|
+
return Promise.resolve(this.session);
|
|
227
|
+
if (this.sessionLoad)
|
|
228
|
+
return this.sessionLoad;
|
|
229
|
+
if (!isSamModelReady(this.model)) {
|
|
230
|
+
return Promise.reject(new Error(`SAM model "${this.model.id}" is not configured yet (no ONNX URLs). ` +
|
|
231
|
+
'Host it and call setSamModelUrls(), then retry.'));
|
|
232
|
+
}
|
|
233
|
+
this.sessionLoad = (async () => {
|
|
234
|
+
try {
|
|
235
|
+
const { OnnxSamSession } = await import('./onnx-sam-session');
|
|
236
|
+
const session = new OnnxSamSession();
|
|
237
|
+
this.progress$.next(0);
|
|
238
|
+
await session.loadModel(this.model, (f) => this.progress$.next(f));
|
|
239
|
+
this.session = session;
|
|
240
|
+
return session;
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
this.sessionLoad = null;
|
|
244
|
+
}
|
|
245
|
+
})();
|
|
246
|
+
return this.sessionLoad;
|
|
247
|
+
}
|
|
248
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SamPointToolService, deps: [{ token: i1.WandService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
249
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SamPointToolService, providedIn: 'root' }); }
|
|
250
|
+
}
|
|
251
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: SamPointToolService, decorators: [{
|
|
252
|
+
type: Injectable,
|
|
253
|
+
args: [{ providedIn: 'root' }]
|
|
254
|
+
}], ctorParameters: () => [{ type: i1.WandService }] });
|
|
255
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FtLXBvaW50LXRvb2wuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24vc2FtLXBvaW50LXRvb2wuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFdkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDM0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVwRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7QUFFdEQ7Ozs7Ozs7Ozs7OztHQVlHO0FBRUgsTUFBTSxPQUFPLG1CQUFtQjtJQXVCOUIsWUFBb0IsV0FBd0I7UUFBeEIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFyQnBDLFlBQU8sR0FBNkIsSUFBSSxDQUFDO1FBQ3pDLFlBQU8sR0FBdUIsSUFBSSxDQUFDO1FBQzNDLGtGQUFrRjtRQUMxRSxnQkFBVyxHQUFnQyxJQUFJLENBQUM7UUFDaEQsVUFBSyxHQUFnQixXQUFXLEVBQUUsQ0FBQztRQUVuQyxjQUFTLEdBQXdCLElBQUksQ0FBQztRQUN0QyxpQkFBWSxHQUFrQixJQUFJLENBQUM7UUFFM0MsMkRBQTJEO1FBQ25ELFdBQU0sR0FBNkMsRUFBRSxDQUFDO1FBQzlELG1GQUFtRjtRQUMzRSxhQUFRLEdBQWtCLElBQUksQ0FBQztRQUU5QixZQUFPLEdBQUcsSUFBSSxlQUFlLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDMUMsVUFBSyxHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3JELG9GQUFv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QUFJLENBQUM7WUFDMUIsQ0FBQztRQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDTCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQzs4R0ExT1UsbUJBQW1CO2tIQUFuQixtQkFBbUIsY0FETixNQUFNOzsyRkFDbkIsbUJBQW1CO2tCQUQvQixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBXYW5kU2VydmljZSB9IGZyb20gJy4uL3dhbmQvd2FuZC5zZXJ2aWNlJztcbmltcG9ydCB7IFdhbmRUb29sSG9zdCB9IGZyb20gJy4uL3dhbmQvd2FuZC10b29sLnNlcnZpY2UnO1xuaW1wb3J0IHsgZnJhbWVUb1JnYmEgfSBmcm9tICcuL3NhbS1wcm9tcHQnO1xuaW1wb3J0IHsgZ2V0U2FtTW9kZWwsIGlzU2FtTW9kZWxSZWFkeSB9IGZyb20gJy4vc2FtLW1vZGVsLXJlZ2lzdHJ5JztcbmltcG9ydCB7IElTYW1TZXNzaW9uLCBTYW1FbWJlZGRpbmcsIFNhbU1vZGVsRGVmLCBTYW1Qcm9tcHQgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvc2FtLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvbiwgUG9seWdvbiB9IGZyb20gJy4uLy4uL21vZGVscy9yZWdpb24nO1xuXG4vKiogSW50ZXJhY3RpdmUgU0FNIHBvaW50LXByb21wdCB0b29sIChqaXQtdWkjOTAsIFAxKS5cbiAqXG4gKiBFYWNoIHBsYWluIChwb3NpdGl2ZSkgY2xpY2sgc2VnbWVudHMgdGhlIGNsaWNrZWQgb2JqZWN0IGFzIGl0cyBPV04gbmV3IHJlZ2lvblxuICog4oCUIGNsaWNraW5nIGEgc2Vjb25kIGZpYmVyIGRvZXNuJ3QgZXh0ZW5kIHRoZSBmaXJzdCBpbnRvIGl0LiBTaGlmdC9BbHQtY2xpY2tcbiAqIGFkZHMgYSBuZWdhdGl2ZSAoZXhjbHVkZSkgcG9pbnQgdGhhdCByZWZpbmVzIHRoZSBDVVJSRU5UIG9iamVjdCwgcmUtcnVubmluZ1xuICogdGhlIGRlY29kZXIgYWdhaW5zdCB0aGUgKGNhY2hlZCkgaW1hZ2UgZW1iZWRkaW5nIGFuZCB1cGRhdGluZyBpdHMgbGl2ZSByZWdpb24uXG4gKiBgY29tbWl0KClgIChFbnRlcikgZmluYWxpc2VzIGVhcmx5OyBgY2xlYXIoKWAgKEVzYykgZGlzY2FyZHMgdGhlIGN1cnJlbnRcbiAqIHByb21wdCArIGl0cyBwcmV2aWV3IHJlZ2lvbi4gTWlycm9ycyB0aGUgd2FuZC9icnVzaCBvbi1jYW52YXMgdG9vbCBwYXR0ZXJuIGFuZFxuICogcmV1c2VzIFdhbmRTZXJ2aWNlLm1hc2tUb1BvbHlnb25zICsgdGhlIHNoYXJlZCByZWdpb24gc3RvcmUuXG4gKlxuICogSW5mZXJlbmNlIGlzIGJlaGluZCB7QGxpbmsgSVNhbVNlc3Npb259IChsYXp5IG9ubnhydW50aW1lLXdlYiBpbiBwcm9kdWN0aW9uLFxuICogYSBmYWtlIGluIHRlc3RzKS5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBTYW1Qb2ludFRvb2xTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBob3N0ITogV2FuZFRvb2xIb3N0O1xuICBwcml2YXRlIG92ZXJsYXk6IEhUTUxDYW52YXNFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgc2Vzc2lvbjogSVNhbVNlc3Npb24gfCBudWxsID0gbnVsbDtcbiAgLyoqIEluLWZsaWdodCBzZXNzaW9uIGxvYWQg4oCUIGRlZHVwZXMgYSB3YXJtLXVwIHByZWxvYWQgYWdhaW5zdCB0aGUgZmlyc3QgY2xpY2suICovXG4gIHByaXZhdGUgc2Vzc2lvbkxvYWQ6IFByb21pc2U8SVNhbVNlc3Npb24+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbW9kZWw6IFNhbU1vZGVsRGVmID0gZ2V0U2FtTW9kZWwoKTtcblxuICBwcml2YXRlIGVtYmVkZGluZzogU2FtRW1iZWRkaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZW1iZWRkaW5nS2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogQWNjdW11bGF0ZWQgcG9pbnQgcHJvbXB0cywgaW4gaW1hZ2UgKG1hdHJpeCkgY29vcmRzLiAqL1xuICBwcml2YXRlIHBvaW50czogeyB4OiBudW1iZXI7IHk6IG51bWJlcjsgbGFiZWw6IDAgfCAxIH1bXSA9IFtdO1xuICAvKiogSWQgb2YgdGhlIGluLXByb2dyZXNzIChwcmV2aWV3KSByZWdpb24gYmVpbmcgcmVmaW5lZCwgaWYgY29tbWl0dGVkIHRvIHN0b3JlLiAqL1xuICBwcml2YXRlIHJlZ2lvbklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICByZWFkb25seSBzdGF0dXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgcmVhZG9ubHkgYnVzeSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVuY29kZXItZG93bmxvYWQgcHJvZ3Jlc3MgKDAuLjEpIG9uIHRoZSBmaXJzdCBjbGljazsgLTEgd2hlbiBub3QgZG93bmxvYWRpbmcuICovXG4gIHJlYWRvbmx5IHByb2dyZXNzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigtMSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBib3VuZE1vdXNlRG93bjogKGU6IE1vdXNlRXZlbnQpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSB3YW5kU2VydmljZTogV2FuZFNlcnZpY2UpIHtcbiAgICB0aGlzLmJvdW5kTW91c2VEb3duID0gKGUpID0+IHsgdm9pZCB0aGlzLm9uTW91c2VEb3duKGUpOyB9O1xuICB9XG5cbiAgYmluZEhvc3QoaG9zdDogV2FuZFRvb2xIb3N0KTogdm9pZCB7IHRoaXMuaG9zdCA9IGhvc3Q7IH1cblxuICBzZXRNb2RlbChpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IGdldFNhbU1vZGVsKGlkKTtcbiAgICBpZiAobmV4dC5pZCA9PT0gdGhpcy5tb2RlbC5pZCkgcmV0dXJuO1xuICAgIHRoaXMubW9kZWwgPSBuZXh0O1xuICAgIHRoaXMuZW1iZWRkaW5nID0gbnVsbDtcbiAgICB0aGlzLmVtYmVkZGluZ0tleSA9IG51bGw7XG4gICAgLy8gRHJvcCB0aGUgbG9hZGVkIHNlc3Npb24gc28gdGhlIG5leHQgcnVuIHJlbG9hZHMgdGhlIG5ld2x5LXBpY2tlZCBtb2RlbFxuICAgIC8vIChlbnN1cmVTZXNzaW9uKCkgcmV0dXJucyB0aGUgY2FjaGVkIHNlc3Npb24gYXMtaXMgb3RoZXJ3aXNlKS5cbiAgICB0aGlzLnNlc3Npb24/LmRpc3Bvc2UoKTtcbiAgICB0aGlzLnNlc3Npb24gPSBudWxsO1xuICAgIHRoaXMuc2Vzc2lvbkxvYWQgPSBudWxsO1xuICB9XG5cbiAgLyoqIFRlc3Qgc2VhbTogaW5qZWN0IGEgZmFrZS9hbHRlcm5hdGUgc2Vzc2lvbi4gKi9cbiAgdXNlU2Vzc2lvbihzZXNzaW9uOiBJU2FtU2Vzc2lvbik6IHZvaWQgeyB0aGlzLnNlc3Npb24gPSBzZXNzaW9uOyB9XG5cbiAgc2V0TW9kZShhY3RpdmU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoYWN0aXZlKSB7XG4gICAgICB0aGlzLmNyZWF0ZU92ZXJsYXkoKTtcbiAgICAgIC8vIFdhcm0gdXAgdGhlIG1vZGVsIGluIHRoZSBiYWNrZ3JvdW5kIGFzIHNvb24gYXMgdGhlIHRvb2wgaXMgYXJtZWQsIHNvIHRoZVxuICAgICAgLy8gZmlyc3QgY2xpY2sgZG9lc24ndCBwYXkgdGhlIChkb3dubG9hZCArKSBzZXNzaW9uLWJ1aWxkIGNvc3Qgb24gaXRzIHBhdGguXG4gICAgICB0aGlzLnByZWxvYWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kZXN0cm95T3ZlcmxheSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBFYWdlcmx5IGxvYWQgdGhlIG1vZGVsIGluIHRoZSBiYWNrZ3JvdW5kIChmaXJlLWFuZC1mb3JnZXQpLiBTYWZlIHRvIGNhbGxcbiAgICogIHJlcGVhdGVkbHkg4oCUIGl0IGRlZHVwZXMgYWdhaW5zdCBhbiBpbi1mbGlnaHQgbG9hZCBhbmQgYW4gZXhpc3Rpbmcgc2Vzc2lvbi4gKi9cbiAgcHJlbG9hZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXNzaW9uIHx8ICFpc1NhbU1vZGVsUmVhZHkodGhpcy5tb2RlbCkpIHJldHVybjtcbiAgICB2b2lkIHRoaXMuZW5zdXJlU2Vzc2lvbigpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKiogRmluYWxpc2UgdGhlIGN1cnJlbnQgb2JqZWN0OiBrZWVwIGl0cyByZWdpb24sIHN0YXJ0IGZyZXNoIG5leHQgY2xpY2suICovXG4gIGNvbW1pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnBvaW50cyA9IFtdO1xuICAgIHRoaXMucmVnaW9uSWQgPSBudWxsO1xuICAgIHRoaXMuc3RhdHVzJC5uZXh0KCcnKTtcbiAgfVxuXG4gIC8qKiBEaXNjYXJkIHRoZSBpbi1wcm9ncmVzcyBwcm9tcHQgKyBpdHMgcHJldmlldyByZWdpb24uICovXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlZ2lvbklkICE9IG51bGwpIHtcbiAgICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLmhvc3QuZ2V0UmVnaW9ucygpLmZpbHRlcigocikgPT4gci5pZCAhPT0gdGhpcy5yZWdpb25JZCk7XG4gICAgICB0aGlzLmhvc3Quc2V0UmVnaW9ucyhyZWdpb25zKTtcbiAgICB9XG4gICAgdGhpcy5wb2ludHMgPSBbXTtcbiAgICB0aGlzLnJlZ2lvbklkID0gbnVsbDtcbiAgICB0aGlzLnN0YXR1cyQubmV4dCgnJyk7XG4gIH1cblxuICAvLyDilIDilIAgb3ZlcmxheSBsaWZlY3ljbGUgKG1pcnJvcnMgdGhlIHdhbmQvYnJ1c2ggdG9vbHMpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByaXZhdGUgY3JlYXRlT3ZlcmxheSgpOiB2b2lkIHtcbiAgICBjb25zdCBwbG90RWwgPSB0aGlzLmhvc3Q/LmdldE92ZXJsYXlDb250YWluZXIoKTtcbiAgICBpZiAoIXBsb3RFbCB8fCB0aGlzLm92ZXJsYXkpIHJldHVybjtcbiAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICBPYmplY3QuYXNzaWduKGNhbnZhcy5zdHlsZSwge1xuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsIHRvcDogJzAnLCBsZWZ0OiAnMCcsIHdpZHRoOiAnMTAwJScsIGhlaWdodDogJzEwMCUnLFxuICAgICAgY3Vyc29yOiAnY3Jvc3NoYWlyJywgekluZGV4OiAnMTAwJyxcbiAgICB9KTtcbiAgICBjYW52YXMud2lkdGggPSBwbG90RWwub2Zmc2V0V2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IHBsb3RFbC5vZmZzZXRIZWlnaHQ7XG4gICAgcGxvdEVsLmFwcGVuZENoaWxkKGNhbnZhcyk7XG4gICAgdGhpcy5vdmVybGF5ID0gY2FudmFzO1xuICAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmJvdW5kTW91c2VEb3duKTtcbiAgfVxuXG4gIHByaXZhdGUgZGVzdHJveU92ZXJsYXkoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLm92ZXJsYXkpIHJldHVybjtcbiAgICB0aGlzLm92ZXJsYXkucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5ib3VuZE1vdXNlRG93bik7XG4gICAgdGhpcy5vdmVybGF5LnJlbW92ZSgpO1xuICAgIHRoaXMub3ZlcmxheSA9IG51bGw7XG4gICAgdGhpcy5wb2ludHMgPSBbXTtcbiAgICB0aGlzLnJlZ2lvbklkID0gbnVsbDtcbiAgfVxuXG4gIC8vIOKUgOKUgCBwZXItY2xpY2sgcmVmaW5lbWVudCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcml2YXRlIGFzeW5jIG9uTW91c2VEb3duKGU6IE1vdXNlRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoZS5idXR0b24gIT09IDAgfHwgIXRoaXMub3ZlcmxheSkgcmV0dXJuO1xuICAgIC8vIFJlLWVudHJhbmN5IGd1YXJkOiBpZ25vcmUgY2xpY2tzIHdoaWxlIGEgcHJldmlvdXMgcHJvbXB0IGlzIHN0aWxsXG4gICAgLy8gZG93bmxvYWRpbmcgdGhlIG1vZGVsIC8gZW5jb2RpbmcgLyBkZWNvZGluZy4gV2l0aG91dCBpdCwgY2xpY2tpbmcgYWdhaW5cbiAgICAvLyBkdXJpbmcgdGhlIHNsb3cgZmlyc3QgcnVuIChlLmcuIGEgfjE3MiBNQiBWaVQtQiBlbmNvZGUgb24gV2ViR1BVKSBsYXVuY2hlc1xuICAgIC8vIGNvbmN1cnJlbnQgZG93bmxvYWRzICsgR1BVIGVuY29kZXMgdGhhdCBjYW4gb3ZlcndoZWxtIHRoZSBHUFUgYW5kIGZyZWV6ZVxuICAgIC8vIHRoZSB0YWIuIEVhY2ggY2xpY2sgaXMgZmFzdCBvbmNlIHRoZSBlbWJlZGRpbmcgaXMgY2FjaGVkLCBzbyB0aGlzIG9ubHlcbiAgICAvLyBkcm9wcyBjbGlja3MgbWFkZSB3aGlsZSBnZW51aW5lbHkgYnVzeS5cbiAgICBpZiAodGhpcy5idXN5JC52YWx1ZSkgcmV0dXJuO1xuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuaG9zdC5nZXRDYWNoZWRJbWFnZURhdGEoKTtcbiAgICBpZiAoIWNhY2hlZCB8fCBjYWNoZWQuZnJhbWVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IHRyYW5zZm9ybSA9IHRoaXMuaG9zdC5nZXRDb29yZGluYXRlVHJhbnNmb3JtKCk7XG4gICAgaWYgKCF0cmFuc2Zvcm0uaXNSZWFkeSgpKSByZXR1cm47XG4gICAgY29uc3QgeyB4OiBkYXRhWCwgeTogZGF0YVkgfSA9IHRyYW5zZm9ybS5jbGllbnRUb0RhdGEoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xuICAgIGlmICghTnVtYmVyLmlzRmluaXRlKGRhdGFYKSB8fCAhTnVtYmVyLmlzRmluaXRlKGRhdGFZKSkgcmV0dXJuO1xuXG4gICAgY29uc3QgcnggPSBjYWNoZWQucmF0aW9zWzBdIHx8IDE7XG4gICAgY29uc3QgcnkgPSBjYWNoZWQucmF0aW9zWzBdIHx8IDE7XG4gICAgY29uc3Qgb3ggPSBjYWNoZWQub3JpZ2luWCA/PyAwO1xuICAgIGNvbnN0IG95ID0gY2FjaGVkLm9yaWdpblkgPz8gMDtcbiAgICAvLyBTaGlmdCBvciBBbHQgPSBuZWdhdGl2ZSAoZXhjbHVkZSkgcG9pbnQuXG4gICAgY29uc3QgbGFiZWw6IDAgfCAxID0gZS5zaGlmdEtleSB8fCBlLmFsdEtleSA/IDAgOiAxO1xuICAgIC8vIEEgcGxhaW4gcG9zaXRpdmUgY2xpY2sgc3RhcnRzIGEgTkVXIG9iamVjdDogY2xpY2tpbmcgYW5vdGhlciBmaWJlciBtdXN0XG4gICAgLy8gc2VnbWVudCB0aGF0IGZpYmVyIG9uIGl0cyBvd24sIG5vdCBhY2N1bXVsYXRlIHdpdGggZWFybGllciBwb2ludHMgYW5kXG4gICAgLy8gZ3JvdyB0aGUgaW4tcHJvZ3Jlc3MgbWFzayBpbnRvIHRoZSBhZGphY2VudCBvYmplY3QgKHdoaWNoIHdvdWxkIGFsc29cbiAgICAvLyBvdmVyd3JpdGUgYSBwcmV2aW91c2x5LXNlZ21lbnRlZCByZWdpb24pLiBPbmx5IFNoaWZ0L0FsdCAoZXhjbHVkZSkgcG9pbnRzXG4gICAgLy8gcmVmaW5lIHRoZSBjdXJyZW50IG9iamVjdC4gVGhpcyBhbHNvIGNsZWFycyBhbnkgc3RhbGUgcHJvbXB0IGxlZnQgYWZ0ZXIgYVxuICAgIC8vIHJlZ2lvbiB3YXMgZGVsZXRlZCwgc28gdGhlIG5leHQgY2xpY2sgc2VnbWVudHMgZnJlc2ggaW5zdGVhZCBvZiByZWRyYXdpbmdcbiAgICAvLyB0aGUgb2xkIG1lcmdlZCBtYXNrLlxuICAgIGlmIChsYWJlbCA9PT0gMSkge1xuICAgICAgdGhpcy5wb2ludHMgPSBbXTtcbiAgICAgIHRoaXMucmVnaW9uSWQgPSBudWxsO1xuICAgIH1cbiAgICB0aGlzLnBvaW50cy5wdXNoKHsgeDogKGRhdGFYIC0gb3gpIC8gcngsIHk6IChkYXRhWSAtIG95KSAvIHJ5LCBsYWJlbCB9KTtcblxuICAgIC8vIE1hcmsgYnVzeSBCRUZPUkUgZW5zdXJlU2Vzc2lvbjogdGhlIGZpcnN0IGNsaWNrIGRvd25sb2FkcyB0aGUgZW5jb2RlclxuICAgIC8vICh+MTTigJMxNzIgTUIpIGFuZCBidWlsZHMgdGhlIHNlc3Npb24sIHdoaWNoIGlzIHRoZSBsb25nZXN0IHdhaXQg4oCUIHdpdGhvdXRcbiAgICAvLyB0aGlzIHRoZSBVSSBzaG93ZWQgbm90aGluZyBydW5uaW5nIHVudGlsIHRoYXQgZmluaXNoZWQuXG4gICAgdGhpcy5idXN5JC5uZXh0KHRydWUpO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnN0YXR1cyQubmV4dCgnTG9hZGluZyBTQU0gbW9kZWzigKYnKTtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCB0aGlzLmVuc3VyZVNlc3Npb24oKTtcbiAgICAgIGNvbnN0IGtleSA9IFtcbiAgICAgICAgdGhpcy5ob3N0LmdldEZpbGVOYW1lKCkgPz8gJycsIHRoaXMuaG9zdC5nZXRBY3RpdmVGcmFtZUluZGV4KCksXG4gICAgICAgIGAke2NhY2hlZC53aWR0aH14JHtjYWNoZWQuaGVpZ2h0fWAsIGAke294fSwke295fSwke3J4fWAsIHRoaXMubW9kZWwuaWQsXG4gICAgICBdLmpvaW4oJ3wnKTtcbiAgICAgIGlmICghdGhpcy5lbWJlZGRpbmcgfHwgdGhpcy5lbWJlZGRpbmdLZXkgIT09IGtleSkge1xuICAgICAgICB0aGlzLnN0YXR1cyQubmV4dCgnRW5jb2RpbmcgaW1hZ2XigKYnKTtcbiAgICAgICAgY29uc3QgcmdiYSA9IGZyYW1lVG9SZ2JhKGNhY2hlZCwgdGhpcy5ob3N0LmdldEFjdGl2ZUZyYW1lSW5kZXgoKSk7XG4gICAgICAgIHRoaXMuZW1iZWRkaW5nID0gYXdhaXQgc2Vzc2lvbi5lbWJlZCh7IGRhdGE6IHJnYmEsIHdpZHRoOiBjYWNoZWQud2lkdGgsIGhlaWdodDogY2FjaGVkLmhlaWdodCB9KTtcbiAgICAgICAgdGhpcy5lbWJlZGRpbmdLZXkgPSBrZXk7XG4gICAgICB9XG4gICAgICB0aGlzLnN0YXR1cyQubmV4dCgnU2VnbWVudGluZ+KApicpO1xuICAgICAgY29uc3QgcHJvbXB0OiBTYW1Qcm9tcHQgPSB7IHBvaW50czogdGhpcy5wb2ludHMuc2xpY2UoKSB9O1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgc2Vzc2lvbi5kZWNvZGUodGhpcy5lbWJlZGRpbmcsIHByb21wdCk7XG4gICAgICBjb25zdCBwb2x5cyA9IHRoaXMud2FuZFNlcnZpY2UubWFza1RvUG9seWdvbnMoXG4gICAgICAgIHJlcy5tYXNrLCByZXMud2lkdGgsIHJlcy5oZWlnaHQsIGNhY2hlZC53aWR0aCwgY2FjaGVkLmhlaWdodCwgMCwgMCxcbiAgICAgICk7XG4gICAgICBpZiAocG9seXMubGVuZ3RoID09PSAwKSB7IHRoaXMuc3RhdHVzJC5uZXh0KCdObyBtYXNrIGZvciB0aGVzZSBwb2ludHMuJyk7IHJldHVybjsgfVxuICAgICAgY29uc3QgcG9seSA9IHBvbHlzWzBdO1xuICAgICAgdGhpcy51cHNlcnRQcmV2aWV3KFxuICAgICAgICBwb2x5Lnhwb2ludHMubWFwKCh4KSA9PiBveCArIHggKiByeCksXG4gICAgICAgIHBvbHkueXBvaW50cy5tYXAoKHkpID0+IG95ICsgeSAqIHJ5KSxcbiAgICAgICk7XG4gICAgICB0aGlzLnN0YXR1cyQubmV4dChcbiAgICAgICAgJ1NlZ21lbnRlZCDigJQgY2xpY2sgYW5vdGhlciBmaWJlciBmb3IgYSBuZXcgcmVnaW9uLCBTaGlmdC1jbGljayB0byByZWZpbmUsIEVzYyB0byB1bmRvLicsXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5zdGF0dXMkLm5leHQoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6ICdTQU0gbW9kZWwgdW5hdmFpbGFibGUuJyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuYnVzeSQubmV4dChmYWxzZSk7XG4gICAgICB0aGlzLnByb2dyZXNzJC5uZXh0KC0xKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmVwbGFjZSAob3IgaW5zZXJ0KSB0aGUgaW4tcHJvZ3Jlc3MgcHJldmlldyByZWdpb24gaW4gdGhlIHNoYXJlZCBzdG9yZS4gKi9cbiAgcHJpdmF0ZSB1cHNlcnRQcmV2aWV3KHhEYXRhOiBudW1iZXJbXSwgeURhdGE6IG51bWJlcltdKTogdm9pZCB7XG4gICAgaWYgKHhEYXRhLmxlbmd0aCA8IDMpIHJldHVybjtcbiAgICBjb25zdCBwb2x5ID0gbmV3IFBvbHlnb24oKTtcbiAgICBwb2x5Lm5wb2ludHMgPSB4RGF0YS5sZW5ndGg7XG4gICAgcG9seS54cG9pbnRzID0geERhdGE7XG4gICAgcG9seS55cG9pbnRzID0geURhdGE7XG4gICAgcG9seS5jb29yZGluYXRlcyA9IHhEYXRhLm1hcCgoeCwgaSkgPT4gW3gsIHlEYXRhW2ldXSk7XG4gICAgcG9seS5jbG9zZWQgPSB0cnVlO1xuXG4gICAgY29uc3QgcmVnaW9ucyA9IHRoaXMuaG9zdC5nZXRSZWdpb25zKCk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLnJlZ2lvbklkICE9IG51bGwgPyByZWdpb25zLmZpbmQoKHIpID0+IHIuaWQgPT09IHRoaXMucmVnaW9uSWQpIDogbnVsbDtcbiAgICBjb25zdCByZWdpb24gPSBuZXcgUmVnaW9uKCk7XG4gICAgcmVnaW9uLmJvdW5kcyA9IHBvbHk7XG4gICAgcmVnaW9uLmNvbG9yID0gdGhpcy5ob3N0LmdldFNoYXBlQ29sb3IoKTtcbiAgICByZWdpb24ubGFiZWwgPSAnc2FtJztcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJlZ2lvbi5pZCA9IGV4aXN0aW5nLmlkO1xuICAgICAgcmVnaW9uLm5hbWUgPSBleGlzdGluZy5uYW1lO1xuICAgICAgY29uc3QgaWR4ID0gcmVnaW9ucy5maW5kSW5kZXgoKHIpID0+IHIuaWQgPT09IHRoaXMucmVnaW9uSWQpO1xuICAgICAgaWYgKGlkeCA+PSAwKSByZWdpb25zW2lkeF0gPSByZWdpb247IGVsc2UgcmVnaW9ucy5wdXNoKHJlZ2lvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlZ2lvbnMucHVzaChyZWdpb24pO1xuICAgIH1cbiAgICB0aGlzLmhvc3Quc2V0UmVnaW9ucyhyZWdpb25zKTtcbiAgICB0aGlzLnJlZ2lvbklkID0gcmVnaW9uLmlkID8/IHRoaXMucmVnaW9uSWQ7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZVNlc3Npb24oKTogUHJvbWlzZTxJU2FtU2Vzc2lvbj4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24pIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5zZXNzaW9uKTtcbiAgICBpZiAodGhpcy5zZXNzaW9uTG9hZCkgcmV0dXJuIHRoaXMuc2Vzc2lvbkxvYWQ7XG4gICAgaWYgKCFpc1NhbU1vZGVsUmVhZHkodGhpcy5tb2RlbCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoXG4gICAgICAgIGBTQU0gbW9kZWwgXCIke3RoaXMubW9kZWwuaWR9XCIgaXMgbm90IGNvbmZpZ3VyZWQgeWV0IChubyBPTk5YIFVSTHMpLiBgICtcbiAgICAgICAgJ0hvc3QgaXQgYW5kIGNhbGwgc2V0U2FtTW9kZWxVcmxzKCksIHRoZW4gcmV0cnkuJyxcbiAgICAgICkpO1xuICAgIH1cbiAgICB0aGlzLnNlc3Npb25Mb2FkID0gKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgT25ueFNhbVNlc3Npb24gfSA9IGF3YWl0IGltcG9ydCgnLi9vbm54LXNhbS1zZXNzaW9uJyk7XG4gICAgICAgIGNvbnN0IHNlc3Npb24gPSBuZXcgT25ueFNhbVNlc3Npb24oKTtcbiAgICAgICAgdGhpcy5wcm9ncmVzcyQubmV4dCgwKTtcbiAgICAgICAgYXdhaXQgc2Vzc2lvbi5sb2FkTW9kZWwodGhpcy5tb2RlbCwgKGYpID0+IHRoaXMucHJvZ3Jlc3MkLm5leHQoZikpO1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICByZXR1cm4gc2Vzc2lvbjtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbkxvYWQgPSBudWxsO1xuICAgICAgfVxuICAgIH0pKCk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbkxvYWQ7XG4gIH1cbn1cbiJdfQ==
|