@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,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser "slide crop": extract the box region (data coords) from a cached image
|
|
3
|
+
* frame as an RGBA image, clamped to the image bounds. Grayscale frames are
|
|
4
|
+
* replicated across R/G/B; RGB tuples are copied through. Returns null when the
|
|
5
|
+
* box is empty/outside the image.
|
|
6
|
+
*
|
|
7
|
+
* The output feeds an automatic segmenter (e.g. cellpose-SAM): run it on the
|
|
8
|
+
* crop, then offset the resulting masks by (matrixX0, matrixY0) to place them
|
|
9
|
+
* back on the full frame.
|
|
10
|
+
*/
|
|
11
|
+
export function cropImageRegion(cached, frameIndex, box) {
|
|
12
|
+
const rx = cached.ratios[0] || 1;
|
|
13
|
+
const ry = cached.ratios[0] || 1;
|
|
14
|
+
const ox = cached.originX ?? 0;
|
|
15
|
+
const oy = cached.originY ?? 0;
|
|
16
|
+
// data -> image (matrix) coords, normalized + clamped to the frame.
|
|
17
|
+
let mx0 = Math.round((Math.min(box.x0, box.x1) - ox) / rx);
|
|
18
|
+
let my0 = Math.round((Math.min(box.y0, box.y1) - oy) / ry);
|
|
19
|
+
let mx1 = Math.round((Math.max(box.x0, box.x1) - ox) / rx);
|
|
20
|
+
let my1 = Math.round((Math.max(box.y0, box.y1) - oy) / ry);
|
|
21
|
+
mx0 = Math.max(0, Math.min(cached.width, mx0));
|
|
22
|
+
my0 = Math.max(0, Math.min(cached.height, my0));
|
|
23
|
+
mx1 = Math.max(0, Math.min(cached.width, mx1));
|
|
24
|
+
my1 = Math.max(0, Math.min(cached.height, my1));
|
|
25
|
+
const cw = mx1 - mx0;
|
|
26
|
+
const ch = my1 - my0;
|
|
27
|
+
if (cw <= 0 || ch <= 0)
|
|
28
|
+
return null;
|
|
29
|
+
const frame = cached.frames[frameIndex] ?? cached.frames[0];
|
|
30
|
+
const data = new Uint8ClampedArray(cw * ch * 4);
|
|
31
|
+
for (let y = 0; y < ch; y++) {
|
|
32
|
+
const row = frame?.[my0 + y];
|
|
33
|
+
for (let x = 0; x < cw; x++) {
|
|
34
|
+
const o = (y * cw + x) * 4;
|
|
35
|
+
const px = row?.[mx0 + x];
|
|
36
|
+
if (px == null) {
|
|
37
|
+
data[o + 3] = 255;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (cached.isGrayscale) {
|
|
41
|
+
const v = px;
|
|
42
|
+
data[o] = v;
|
|
43
|
+
data[o + 1] = v;
|
|
44
|
+
data[o + 2] = v;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const t = px;
|
|
48
|
+
data[o] = t[0];
|
|
49
|
+
data[o + 1] = t[1];
|
|
50
|
+
data[o + 2] = t[2];
|
|
51
|
+
}
|
|
52
|
+
data[o + 3] = 255;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { data, width: cw, height: ch, matrixX0: mx0, matrixY0: my0 };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpZGUtY3JvcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9jcm9wL3NsaWRlLWNyb3AudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUJBOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQzdCLE1BQXVCLEVBQUUsVUFBa0IsRUFBRSxHQUFZO0lBRXpELE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQy9CLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDO0lBQy9CLG9FQUFvRTtJQUNwRSxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMzRCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMzRCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUMzRCxJQUFJLEdBQUcsR0FB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LENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztRQUNwQixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBQ3ZFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDYWNoZWRJbWFnZURhdGEgfSBmcm9tICcuLi93YW5kL3dhbmQtdG9vbC5zZXJ2aWNlJztcblxuLyoqIEEgY2xpZW50LXNpZGUgY3JvcCBvZiB0aGUgbG9hZGVkIGltYWdlIOKAlCB0aGUgYnJvd3NlciBlcXVpdmFsZW50IG9mIHRoZSBKSVRcbiAqICBzZXJ2ZXIgc2xpZGUtY3JvcCwgdGFrZW4gZnJvbSB0aGUgcGl4ZWxzIGFscmVhZHkgaW4gdGhlIHZpZXdlci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3JvcHBlZEltYWdlIHtcbiAgLyoqIFJHQkEgcGl4ZWxzIG9mIHRoZSBjcm9wLCByb3ctbWFqb3IuICovXG4gIGRhdGE6IFVpbnQ4Q2xhbXBlZEFycmF5O1xuICB3aWR0aDogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgLyoqIENyb3Agb3JpZ2luIGluIGltYWdlIChtYXRyaXgpIGNvb3JkcyDigJQgbGV0cyBtYXNrcyBtYXAgYmFjayB0byB0aGUgZnJhbWUuICovXG4gIG1hdHJpeFgwOiBudW1iZXI7XG4gIG1hdHJpeFkwOiBudW1iZXI7XG59XG5cbi8qKiBBIGJveCBpbiBpbWFnZSAqZGF0YSogY29vcmRpbmF0ZXMgKGFzIHN0b3JlZCBvbiBhIFJlY3RhbmdsZSByZWdpb24pLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhQm94IHsgeDA6IG51bWJlcjsgeTA6IG51bWJlcjsgeDE6IG51bWJlcjsgeTE6IG51bWJlcjsgfVxuXG4vKipcbiAqIEJyb3dzZXIgXCJzbGlkZSBjcm9wXCI6IGV4dHJhY3QgdGhlIGJveCByZWdpb24gKGRhdGEgY29vcmRzKSBmcm9tIGEgY2FjaGVkIGltYWdlXG4gKiBmcmFtZSBhcyBhbiBSR0JBIGltYWdlLCBjbGFtcGVkIHRvIHRoZSBpbWFnZSBib3VuZHMuIEdyYXlzY2FsZSBmcmFtZXMgYXJlXG4gKiByZXBsaWNhdGVkIGFjcm9zcyBSL0cvQjsgUkdCIHR1cGxlcyBhcmUgY29waWVkIHRocm91Z2guIFJldHVybnMgbnVsbCB3aGVuIHRoZVxuICogYm94IGlzIGVtcHR5L291dHNpZGUgdGhlIGltYWdlLlxuICpcbiAqIFRoZSBvdXRwdXQgZmVlZHMgYW4gYXV0b21hdGljIHNlZ21lbnRlciAoZS5nLiBjZWxscG9zZS1TQU0pOiBydW4gaXQgb24gdGhlXG4gKiBjcm9wLCB0aGVuIG9mZnNldCB0aGUgcmVzdWx0aW5nIG1hc2tzIGJ5IChtYXRyaXhYMCwgbWF0cml4WTApIHRvIHBsYWNlIHRoZW1cbiAqIGJhY2sgb24gdGhlIGZ1bGwgZnJhbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcm9wSW1hZ2VSZWdpb24oXG4gIGNhY2hlZDogQ2FjaGVkSW1hZ2VEYXRhLCBmcmFtZUluZGV4OiBudW1iZXIsIGJveDogRGF0YUJveCxcbik6IENyb3BwZWRJbWFnZSB8IG51bGwge1xuICBjb25zdCByeCA9IGNhY2hlZC5yYXRpb3NbMF0gfHwgMTtcbiAgY29uc3QgcnkgPSBjYWNoZWQucmF0aW9zWzBdIHx8IDE7XG4gIGNvbnN0IG94ID0gY2FjaGVkLm9yaWdpblggPz8gMDtcbiAgY29uc3Qgb3kgPSBjYWNoZWQub3JpZ2luWSA/PyAwO1xuICAvLyBkYXRhIC0+IGltYWdlIChtYXRyaXgpIGNvb3Jkcywgbm9ybWFsaXplZCArIGNsYW1wZWQgdG8gdGhlIGZyYW1lLlxuICBsZXQgbXgwID0gTWF0aC5yb3VuZCgoTWF0aC5taW4oYm94LngwLCBib3gueDEpIC0gb3gpIC8gcngpO1xuICBsZXQgbXkwID0gTWF0aC5yb3VuZCgoTWF0aC5taW4oYm94LnkwLCBib3gueTEpIC0gb3kpIC8gcnkpO1xuICBsZXQgbXgxID0gTWF0aC5yb3VuZCgoTWF0aC5tYXgoYm94LngwLCBib3gueDEpIC0gb3gpIC8gcngpO1xuICBsZXQgbXkxID0gTWF0aC5yb3VuZCgoTWF0aC5tYXgoYm94LnkwLCBib3gueTEpIC0gb3kpIC8gcnkpO1xuICBteDAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihjYWNoZWQud2lkdGgsIG14MCkpO1xuICBteTAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihjYWNoZWQuaGVpZ2h0LCBteTApKTtcbiAgbXgxID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oY2FjaGVkLndpZHRoLCBteDEpKTtcbiAgbXkxID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oY2FjaGVkLmhlaWdodCwgbXkxKSk7XG4gIGNvbnN0IGN3ID0gbXgxIC0gbXgwO1xuICBjb25zdCBjaCA9IG15MSAtIG15MDtcbiAgaWYgKGN3IDw9IDAgfHwgY2ggPD0gMCkgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgZnJhbWUgPSBjYWNoZWQuZnJhbWVzW2ZyYW1lSW5kZXhdID8/IGNhY2hlZC5mcmFtZXNbMF07XG4gIGNvbnN0IGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoY3cgKiBjaCAqIDQpO1xuICBmb3IgKGxldCB5ID0gMDsgeSA8IGNoOyB5KyspIHtcbiAgICBjb25zdCByb3cgPSBmcmFtZT8uW215MCArIHldO1xuICAgIGZvciAobGV0IHggPSAwOyB4IDwgY3c7IHgrKykge1xuICAgICAgY29uc3QgbyA9ICh5ICogY3cgKyB4KSAqIDQ7XG4gICAgICBjb25zdCBweCA9IHJvdz8uW214MCArIHhdO1xuICAgICAgaWYgKHB4ID09IG51bGwpIHsgZGF0YVtvICsgM10gPSAyNTU7IGNvbnRpbnVlOyB9XG4gICAgICBpZiAoY2FjaGVkLmlzR3JheXNjYWxlKSB7XG4gICAgICAgIGNvbnN0IHYgPSBweCBhcyBudW1iZXI7XG4gICAgICAgIGRhdGFbb10gPSB2OyBkYXRhW28gKyAxXSA9IHY7IGRhdGFbbyArIDJdID0gdjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHQgPSBweCBhcyBudW1iZXJbXTtcbiAgICAgICAgZGF0YVtvXSA9IHRbMF07IGRhdGFbbyArIDFdID0gdFsxXTsgZGF0YVtvICsgMl0gPSB0WzJdO1xuICAgICAgfVxuICAgICAgZGF0YVtvICsgM10gPSAyNTU7XG4gICAgfVxuICB9XG4gIHJldHVybiB7IGRhdGEsIHdpZHRoOiBjdywgaGVpZ2h0OiBjaCwgbWF0cml4WDA6IG14MCwgbWF0cml4WTA6IG15MCB9O1xufVxuIl19
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { WandService } from '../wand/wand.service';
|
|
4
|
+
import { cropImageRegion } from '../crop/slide-crop';
|
|
5
|
+
import { Region, Polygon, Rectangle } from '../../models/region';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "../wand/wand.service";
|
|
8
|
+
/** Yield to the event loop (a macrotask) so the toast can repaint the latest
|
|
9
|
+
* status / animate the spinner before the next main-thread-blocking step. */
|
|
10
|
+
const tick = () => new Promise((r) => setTimeout(r, 0));
|
|
11
|
+
/**
|
|
12
|
+
* Automatic cell segmentation inside drawn boxes (jit-ui#90). For each rectangle
|
|
13
|
+
* it client slide-crops the box from the loaded image, runs an automatic
|
|
14
|
+
* segmenter (cellpose-SAM, supplied by the host via {@link ICellSegmenter}) on
|
|
15
|
+
* the crop, and turns every cell instance into a region — offset back onto the
|
|
16
|
+
* frame. The prompt rectangle is replaced by its cell regions.
|
|
17
|
+
*
|
|
18
|
+
* This is the complement to the promptable SAM tool: cellpose-SAM can't take a
|
|
19
|
+
* box prompt, so the box just bounds the crop it segments automatically.
|
|
20
|
+
*/
|
|
21
|
+
export class CellSegmentToolService {
|
|
22
|
+
constructor(wandService) {
|
|
23
|
+
this.wandService = wandService;
|
|
24
|
+
this.status$ = new BehaviorSubject('');
|
|
25
|
+
this.busy$ = new BehaviorSubject(false);
|
|
26
|
+
this.progress$ = new BehaviorSubject(-1);
|
|
27
|
+
}
|
|
28
|
+
bindHost(host) { this.host = host; }
|
|
29
|
+
/**
|
|
30
|
+
* Crop + cellpose-segment every rectangle; append the cell regions and drop
|
|
31
|
+
* the prompt rectangles that produced cells. Returns the number of regions added.
|
|
32
|
+
*/
|
|
33
|
+
async segmentBoxes(segmenter) {
|
|
34
|
+
if (!this.host)
|
|
35
|
+
return 0;
|
|
36
|
+
const cached = this.host.getCachedImageData();
|
|
37
|
+
if (!cached || cached.frames.length === 0) {
|
|
38
|
+
this.status$.next('No image loaded.');
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
const regions = this.host.getRegions();
|
|
42
|
+
const rects = regions.filter((r) => r.bounds instanceof Rectangle);
|
|
43
|
+
if (rects.length === 0) {
|
|
44
|
+
this.status$.next('Draw one or more rectangles, then run Cellpose.');
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
const rx = cached.ratios[0] || 1;
|
|
48
|
+
const ry = cached.ratios[0] || 1;
|
|
49
|
+
const ox = cached.originX ?? 0;
|
|
50
|
+
const oy = cached.originY ?? 0;
|
|
51
|
+
const frameIdx = this.host.getActiveFrameIndex();
|
|
52
|
+
this.busy$.next(true);
|
|
53
|
+
try {
|
|
54
|
+
const masks = [];
|
|
55
|
+
const consumed = new Set();
|
|
56
|
+
let added = 0;
|
|
57
|
+
for (let i = 0; i < rects.length; i++) {
|
|
58
|
+
const b = rects[i].bounds;
|
|
59
|
+
// Prefix each phase with the box index when there's more than one.
|
|
60
|
+
const prefix = rects.length > 1 ? `Box ${i + 1}/${rects.length}: ` : '';
|
|
61
|
+
this.status$.next(`${prefix}Cropping…`);
|
|
62
|
+
await tick(); // let the status paint before the (main-thread) crop
|
|
63
|
+
const crop = cropImageRegion(cached, frameIdx, { x0: b.x, y0: b.y, x1: b.x + b.width, y1: b.y + b.height });
|
|
64
|
+
if (!crop)
|
|
65
|
+
continue;
|
|
66
|
+
const seg = await segmenter.segmentCells({ data: crop.data, width: crop.width, height: crop.height }, { onProgress: (f) => this.progress$.next(f), onStatus: (s) => this.status$.next(prefix + s) });
|
|
67
|
+
this.status$.next(`${prefix}Tracing cells…`);
|
|
68
|
+
await tick(); // paint before the (main-thread) contour tracing
|
|
69
|
+
const polys = this.wandService.labelsToPolygons(seg.labels, seg.width, seg.height, seg.width, seg.height, 0, 0);
|
|
70
|
+
if (polys.length === 0)
|
|
71
|
+
continue;
|
|
72
|
+
for (const poly of polys) {
|
|
73
|
+
// crop-pixel → frame-matrix (offset by crop origin) → data coords.
|
|
74
|
+
const xData = poly.xpoints.map((x) => ox + (crop.matrixX0 + x) * rx);
|
|
75
|
+
const yData = poly.ypoints.map((y) => oy + (crop.matrixY0 + y) * ry);
|
|
76
|
+
masks.push(this.makeRegion(xData, yData, rects[i].color)); // inherit the box's color
|
|
77
|
+
added++;
|
|
78
|
+
}
|
|
79
|
+
consumed.add(rects[i]);
|
|
80
|
+
}
|
|
81
|
+
this.host.setRegions(regions.filter((r) => !consumed.has(r)).concat(masks));
|
|
82
|
+
this.status$.next(added > 0 ? `Added ${added} cell region(s).` : 'No cells found.');
|
|
83
|
+
return added;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
this.status$.next(err instanceof Error ? err.message : 'Cellpose segmentation failed.');
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
this.busy$.next(false);
|
|
91
|
+
this.progress$.next(-1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
makeRegion(xData, yData, color) {
|
|
95
|
+
const poly = new Polygon();
|
|
96
|
+
poly.npoints = xData.length;
|
|
97
|
+
poly.xpoints = xData;
|
|
98
|
+
poly.ypoints = yData;
|
|
99
|
+
poly.coordinates = xData.map((x, i) => [x, yData[i]]);
|
|
100
|
+
poly.closed = true;
|
|
101
|
+
const region = new Region();
|
|
102
|
+
region.bounds = poly;
|
|
103
|
+
// Inherit the source box's color; fall back to the host default.
|
|
104
|
+
region.color = color || this.host.getShapeColor();
|
|
105
|
+
region.label = 'cell';
|
|
106
|
+
return region;
|
|
107
|
+
}
|
|
108
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellSegmentToolService, deps: [{ token: i1.WandService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
109
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellSegmentToolService, providedIn: 'root' }); }
|
|
110
|
+
}
|
|
111
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellSegmentToolService, decorators: [{
|
|
112
|
+
type: Injectable,
|
|
113
|
+
args: [{ providedIn: 'root' }]
|
|
114
|
+
}], ctorParameters: () => [{ type: i1.WandService }] });
|
|
115
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1zZWdtZW50LXRvb2wuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24vY2VsbC1zZWdtZW50LXRvb2wuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFdkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7O0FBRWpFOzhFQUM4RTtBQUM5RSxNQUFNLElBQUksR0FBRyxHQUFrQixFQUFFLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUV2RTs7Ozs7Ozs7O0dBU0c7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBT2pDLFlBQW9CLFdBQXdCO1FBQXhCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBSm5DLFlBQU8sR0FBRyxJQUFJLGVBQWUsQ0FBUyxFQUFFLENBQUMsQ0FBQztRQUMxQyxVQUFLLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFDNUMsY0FBUyxHQUFHLElBQUksZUFBZSxDQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFTixDQUFDO0lBRWhELFFBQVEsQ0FBQyxJQUFrQixJQUFVLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUV4RDs7O09BR0c7SUFDSCxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQXlCO1FBQzFDLElBQUks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QyxNQUFNLENBQUM7UUFDNUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixNQUFNLE1BQU0sR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQzVCLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLGlFQUFpRTtRQUNqRSxNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2xELE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1FBQ3RCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7OEdBNUZVLHNCQUFzQjtrSEFBdEIsc0JBQXNCLGNBRFQsTUFBTTs7MkZBQ25CLHNCQUFzQjtrQkFEbEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgV2FuZFNlcnZpY2UgfSBmcm9tICcuLi93YW5kL3dhbmQuc2VydmljZSc7XG5pbXBvcnQgeyBXYW5kVG9vbEhvc3QgfSBmcm9tICcuLi93YW5kL3dhbmQtdG9vbC5zZXJ2aWNlJztcbmltcG9ydCB7IGNyb3BJbWFnZVJlZ2lvbiB9IGZyb20gJy4uL2Nyb3Avc2xpZGUtY3JvcCc7XG5pbXBvcnQgeyBJQ2VsbFNlZ21lbnRlciB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jZWxsLXNlZ21lbnRlci5jb250cmFjdCc7XG5pbXBvcnQgeyBSZWdpb24sIFBvbHlnb24sIFJlY3RhbmdsZSB9IGZyb20gJy4uLy4uL21vZGVscy9yZWdpb24nO1xuXG4vKiogWWllbGQgdG8gdGhlIGV2ZW50IGxvb3AgKGEgbWFjcm90YXNrKSBzbyB0aGUgdG9hc3QgY2FuIHJlcGFpbnQgdGhlIGxhdGVzdFxuICogIHN0YXR1cyAvIGFuaW1hdGUgdGhlIHNwaW5uZXIgYmVmb3JlIHRoZSBuZXh0IG1haW4tdGhyZWFkLWJsb2NraW5nIHN0ZXAuICovXG5jb25zdCB0aWNrID0gKCk6IFByb21pc2U8dm9pZD4gPT4gbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgMCkpO1xuXG4vKipcbiAqIEF1dG9tYXRpYyBjZWxsIHNlZ21lbnRhdGlvbiBpbnNpZGUgZHJhd24gYm94ZXMgKGppdC11aSM5MCkuIEZvciBlYWNoIHJlY3RhbmdsZVxuICogaXQgY2xpZW50IHNsaWRlLWNyb3BzIHRoZSBib3ggZnJvbSB0aGUgbG9hZGVkIGltYWdlLCBydW5zIGFuIGF1dG9tYXRpY1xuICogc2VnbWVudGVyIChjZWxscG9zZS1TQU0sIHN1cHBsaWVkIGJ5IHRoZSBob3N0IHZpYSB7QGxpbmsgSUNlbGxTZWdtZW50ZXJ9KSBvblxuICogdGhlIGNyb3AsIGFuZCB0dXJucyBldmVyeSBjZWxsIGluc3RhbmNlIGludG8gYSByZWdpb24g4oCUIG9mZnNldCBiYWNrIG9udG8gdGhlXG4gKiBmcmFtZS4gVGhlIHByb21wdCByZWN0YW5nbGUgaXMgcmVwbGFjZWQgYnkgaXRzIGNlbGwgcmVnaW9ucy5cbiAqXG4gKiBUaGlzIGlzIHRoZSBjb21wbGVtZW50IHRvIHRoZSBwcm9tcHRhYmxlIFNBTSB0b29sOiBjZWxscG9zZS1TQU0gY2FuJ3QgdGFrZSBhXG4gKiBib3ggcHJvbXB0LCBzbyB0aGUgYm94IGp1c3QgYm91bmRzIHRoZSBjcm9wIGl0IHNlZ21lbnRzIGF1dG9tYXRpY2FsbHkuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQ2VsbFNlZ21lbnRUb29sU2VydmljZSB7XG4gIHByaXZhdGUgaG9zdCE6IFdhbmRUb29sSG9zdDtcblxuICByZWFkb25seSBzdGF0dXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgcmVhZG9ubHkgYnVzeSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgcmVhZG9ubHkgcHJvZ3Jlc3MkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KC0xKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHdhbmRTZXJ2aWNlOiBXYW5kU2VydmljZSkge31cblxuICBiaW5kSG9zdChob3N0OiBXYW5kVG9vbEhvc3QpOiB2b2lkIHsgdGhpcy5ob3N0ID0gaG9zdDsgfVxuXG4gIC8qKlxuICAgKiBDcm9wICsgY2VsbHBvc2Utc2VnbWVudCBldmVyeSByZWN0YW5nbGU7IGFwcGVuZCB0aGUgY2VsbCByZWdpb25zIGFuZCBkcm9wXG4gICAqIHRoZSBwcm9tcHQgcmVjdGFuZ2xlcyB0aGF0IHByb2R1Y2VkIGNlbGxzLiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgcmVnaW9ucyBhZGRlZC5cbiAgICovXG4gIGFzeW5jIHNlZ21lbnRCb3hlcyhzZWdtZW50ZXI6IElDZWxsU2VnbWVudGVyKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAoIXRoaXMuaG9zdCkgcmV0dXJuIDA7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5ob3N0LmdldENhY2hlZEltYWdlRGF0YSgpO1xuICAgIGlmICghY2FjaGVkIHx8IGNhY2hlZC5mcmFtZXMubGVuZ3RoID09PSAwKSB7IHRoaXMuc3RhdHVzJC5uZXh0KCdObyBpbWFnZSBsb2FkZWQuJyk7IHJldHVybiAwOyB9XG5cbiAgICBjb25zdCByZWdpb25zID0gdGhpcy5ob3N0LmdldFJlZ2lvbnMoKTtcbiAgICBjb25zdCByZWN0cyA9IHJlZ2lvbnMuZmlsdGVyKChyKSA9PiByLmJvdW5kcyBpbnN0YW5jZW9mIFJlY3RhbmdsZSk7XG4gICAgaWYgKHJlY3RzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5zdGF0dXMkLm5leHQoJ0RyYXcgb25lIG9yIG1vcmUgcmVjdGFuZ2xlcywgdGhlbiBydW4gQ2VsbHBvc2UuJyk7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBjb25zdCByeCA9IGNhY2hlZC5yYXRpb3NbMF0gfHwgMTtcbiAgICBjb25zdCByeSA9IGNhY2hlZC5yYXRpb3NbMF0gfHwgMTtcbiAgICBjb25zdCBveCA9IGNhY2hlZC5vcmlnaW5YID8/IDA7XG4gICAgY29uc3Qgb3kgPSBjYWNoZWQub3JpZ2luWSA/PyAwO1xuICAgIGNvbnN0IGZyYW1lSWR4ID0gdGhpcy5ob3N0LmdldEFjdGl2ZUZyYW1lSW5kZXgoKTtcblxuICAgIHRoaXMuYnVzeSQubmV4dCh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbWFza3M6IFJlZ2lvbltdID0gW107XG4gICAgICBjb25zdCBjb25zdW1lZCA9IG5ldyBTZXQ8UmVnaW9uPigpO1xuICAgICAgbGV0IGFkZGVkID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVjdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgYiA9IHJlY3RzW2ldLmJvdW5kcyBhcyBSZWN0YW5nbGU7XG4gICAgICAgIC8vIFByZWZpeCBlYWNoIHBoYXNlIHdpdGggdGhlIGJveCBpbmRleCB3aGVuIHRoZXJlJ3MgbW9yZSB0aGFuIG9uZS5cbiAgICAgICAgY29uc3QgcHJlZml4ID0gcmVjdHMubGVuZ3RoID4gMSA/IGBCb3ggJHtpICsgMX0vJHtyZWN0cy5sZW5ndGh9OiBgIDogJyc7XG4gICAgICAgIHRoaXMuc3RhdHVzJC5uZXh0KGAke3ByZWZpeH1Dcm9wcGluZ+KApmApO1xuICAgICAgICBhd2FpdCB0aWNrKCk7IC8vIGxldCB0aGUgc3RhdHVzIHBhaW50IGJlZm9yZSB0aGUgKG1haW4tdGhyZWFkKSBjcm9wXG4gICAgICAgIGNvbnN0IGNyb3AgPSBjcm9wSW1hZ2VSZWdpb24oXG4gICAgICAgICAgY2FjaGVkLCBmcmFtZUlkeCwgeyB4MDogYi54LCB5MDogYi55LCB4MTogYi54ICsgYi53aWR0aCwgeTE6IGIueSArIGIuaGVpZ2h0IH0sXG4gICAgICAgICk7XG4gICAgICAgIGlmICghY3JvcCkgY29udGludWU7XG4gICAgICAgIGNvbnN0IHNlZyA9IGF3YWl0IHNlZ21lbnRlci5zZWdtZW50Q2VsbHMoXG4gICAgICAgICAgeyBkYXRhOiBjcm9wLmRhdGEsIHdpZHRoOiBjcm9wLndpZHRoLCBoZWlnaHQ6IGNyb3AuaGVpZ2h0IH0sXG4gICAgICAgICAgeyBvblByb2dyZXNzOiAoZikgPT4gdGhpcy5wcm9ncmVzcyQubmV4dChmKSwgb25TdGF0dXM6IChzKSA9PiB0aGlzLnN0YXR1cyQubmV4dChwcmVmaXggKyBzKSB9LFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0YXR1cyQubmV4dChgJHtwcmVmaXh9VHJhY2luZyBjZWxsc+KApmApO1xuICAgICAgICBhd2FpdCB0aWNrKCk7IC8vIHBhaW50IGJlZm9yZSB0aGUgKG1haW4tdGhyZWFkKSBjb250b3VyIHRyYWNpbmdcbiAgICAgICAgY29uc3QgcG9seXMgPSB0aGlzLndhbmRTZXJ2aWNlLmxhYmVsc1RvUG9seWdvbnMoXG4gICAgICAgICAgc2VnLmxhYmVscywgc2VnLndpZHRoLCBzZWcuaGVpZ2h0LCBzZWcud2lkdGgsIHNlZy5oZWlnaHQsIDAsIDAsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChwb2x5cy5sZW5ndGggPT09IDApIGNvbnRpbnVlO1xuICAgICAgICBmb3IgKGNvbnN0IHBvbHkgb2YgcG9seXMpIHtcbiAgICAgICAgICAvLyBjcm9wLXBpeGVsIOKGkiBmcmFtZS1tYXRyaXggKG9mZnNldCBieSBjcm9wIG9yaWdpbikg4oaSIGRhdGEgY29vcmRzLlxuICAgICAgICAgIGNvbnN0IHhEYXRhID0gcG9seS54cG9pbnRzLm1hcCgoeCkgPT4gb3ggKyAoY3JvcC5tYXRyaXhYMCArIHgpICogcngpO1xuICAgICAgICAgIGNvbnN0IHlEYXRhID0gcG9seS55cG9pbnRzLm1hcCgoeSkgPT4gb3kgKyAoY3JvcC5tYXRyaXhZMCArIHkpICogcnkpO1xuICAgICAgICAgIG1hc2tzLnB1c2godGhpcy5tYWtlUmVnaW9uKHhEYXRhLCB5RGF0YSwgcmVjdHNbaV0uY29sb3IpKTsgLy8gaW5oZXJpdCB0aGUgYm94J3MgY29sb3JcbiAgICAgICAgICBhZGRlZCsrO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN1bWVkLmFkZChyZWN0c1tpXSk7XG4gICAgICB9XG4gICAgICB0aGlzLmhvc3Quc2V0UmVnaW9ucyhyZWdpb25zLmZpbHRlcigocikgPT4gIWNvbnN1bWVkLmhhcyhyKSkuY29uY2F0KG1hc2tzKSk7XG4gICAgICB0aGlzLnN0YXR1cyQubmV4dChhZGRlZCA+IDAgPyBgQWRkZWQgJHthZGRlZH0gY2VsbCByZWdpb24ocykuYCA6ICdObyBjZWxscyBmb3VuZC4nKTtcbiAgICAgIHJldHVybiBhZGRlZDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMuc3RhdHVzJC5uZXh0KGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiAnQ2VsbHBvc2Ugc2VnbWVudGF0aW9uIGZhaWxlZC4nKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmJ1c3kkLm5leHQoZmFsc2UpO1xuICAgICAgdGhpcy5wcm9ncmVzcyQubmV4dCgtMSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtYWtlUmVnaW9uKHhEYXRhOiBudW1iZXJbXSwgeURhdGE6IG51bWJlcltdLCBjb2xvcj86IHN0cmluZyk6IFJlZ2lvbiB7XG4gICAgY29uc3QgcG9seSA9IG5ldyBQb2x5Z29uKCk7XG4gICAgcG9seS5ucG9pbnRzID0geERhdGEubGVuZ3RoO1xuICAgIHBvbHkueHBvaW50cyA9IHhEYXRhO1xuICAgIHBvbHkueXBvaW50cyA9IHlEYXRhO1xuICAgIHBvbHkuY29vcmRpbmF0ZXMgPSB4RGF0YS5tYXAoKHgsIGkpID0+IFt4LCB5RGF0YVtpXV0pO1xuICAgIHBvbHkuY2xvc2VkID0gdHJ1ZTtcbiAgICBjb25zdCByZWdpb24gPSBuZXcgUmVnaW9uKCk7XG4gICAgcmVnaW9uLmJvdW5kcyA9IHBvbHk7XG4gICAgLy8gSW5oZXJpdCB0aGUgc291cmNlIGJveCdzIGNvbG9yOyBmYWxsIGJhY2sgdG8gdGhlIGhvc3QgZGVmYXVsdC5cbiAgICByZWdpb24uY29sb3IgPSBjb2xvciB8fCB0aGlzLmhvc3QuZ2V0U2hhcGVDb2xvcigpO1xuICAgIHJlZ2lvbi5sYWJlbCA9ICdjZWxsJztcbiAgICByZXR1cm4gcmVnaW9uO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { getOrtWasmBase } from './ort-runtime-config';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/** Hosted cellpose-SAM ONNX (CPSAM, fp16). Override via {@link setModelUrl}. */
|
|
5
|
+
const DEFAULT_MODEL_URL = 'https://huggingface.co/ballon999/cellpose-sam-onnx/resolve/main/cpsam_fp16.onnx';
|
|
6
|
+
/**
|
|
7
|
+
* Default in-library {@link ICellSegmenter} backed by cellpose-js (WebGPU/WASM
|
|
8
|
+
* ONNX) — so the toolbar's automatic **Cellpose** tool works out of the box in
|
|
9
|
+
* any app, with no host wiring (jit-ui#90). `cellpose-js` is a peer dependency
|
|
10
|
+
* and is **lazy-imported** on first use, so apps that never run Cellpose pay
|
|
11
|
+
* nothing for it. A host can still override the {@link CELL_SEGMENTER} token to
|
|
12
|
+
* supply a different implementation.
|
|
13
|
+
*
|
|
14
|
+
* Owns a single shared {@link Cellpose} instance (one model load, one WebGPU
|
|
15
|
+
* session, one worker). {@link getModel} exposes that instance so a host's
|
|
16
|
+
* processing pipeline can reuse it instead of loading the ~588 MB model twice.
|
|
17
|
+
*/
|
|
18
|
+
export class CellposeSegmenterService {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.instance = null;
|
|
21
|
+
this.loading = null;
|
|
22
|
+
this.modelUrl = DEFAULT_MODEL_URL;
|
|
23
|
+
}
|
|
24
|
+
/** Point the segmenter at a different hosted CPSAM ONNX (before first use). */
|
|
25
|
+
setModelUrl(url) {
|
|
26
|
+
this.modelUrl = url;
|
|
27
|
+
}
|
|
28
|
+
async segmentCells(image, progress) {
|
|
29
|
+
let announcedDownload = false;
|
|
30
|
+
const cp = await this.getModel((loaded, total) => {
|
|
31
|
+
if (total)
|
|
32
|
+
progress?.onProgress?.(loaded / total);
|
|
33
|
+
if (loaded > 0 && !announcedDownload) {
|
|
34
|
+
announcedDownload = true;
|
|
35
|
+
progress?.onStatus?.('Downloading Cellpose-SAM model…');
|
|
36
|
+
}
|
|
37
|
+
}, (status) => progress?.onStatus?.(status));
|
|
38
|
+
progress?.onStatus?.('Preprocessing image…');
|
|
39
|
+
const out = await cp.segment({ data: image.data, width: image.width, height: image.height, channels: 4 }, {
|
|
40
|
+
// cellpose-js runs inference in its worker (these fire between tiles) and
|
|
41
|
+
// averaging/dynamics on the main thread; surface both so the toast shows
|
|
42
|
+
// real progress instead of looking stuck.
|
|
43
|
+
onTileProgress: (done, total) => progress?.onStatus?.(done < total ? `Running inference (tile ${done}/${total})…` : 'Computing flow dynamics…'),
|
|
44
|
+
});
|
|
45
|
+
return { labels: out.masks, width: out.width, height: out.height, count: out.count };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The shared Cellpose instance, lazily created on first use and reused
|
|
49
|
+
* thereafter (deduped across concurrent callers). Exposed so a host pipeline
|
|
50
|
+
* engine can run richer `segment()` options on the same instance. `onProgress`
|
|
51
|
+
* reports raw downloaded/total bytes (`total` is null when unknown); `onStatus`
|
|
52
|
+
* reports worker-init phase strings.
|
|
53
|
+
*/
|
|
54
|
+
getModel(onProgress, onStatus) {
|
|
55
|
+
if (this.instance)
|
|
56
|
+
return Promise.resolve(this.instance);
|
|
57
|
+
if (!this.loading) {
|
|
58
|
+
this.loading = (async () => {
|
|
59
|
+
// Lazy: keep cellpose-js + its ORT runtime out of the initial bundle.
|
|
60
|
+
const { Cellpose, configureOrt } = await import('cellpose-js');
|
|
61
|
+
configureOrt({ wasmPaths: getOrtWasmBase() });
|
|
62
|
+
const cp = await Cellpose.fromPretrained(this.modelUrl, {
|
|
63
|
+
preload: true,
|
|
64
|
+
onProgress: ({ loaded, total }) => onProgress?.(loaded, total),
|
|
65
|
+
onStatus: (s) => onStatus?.(s),
|
|
66
|
+
});
|
|
67
|
+
this.instance = cp;
|
|
68
|
+
return cp;
|
|
69
|
+
})();
|
|
70
|
+
}
|
|
71
|
+
return this.loading;
|
|
72
|
+
}
|
|
73
|
+
/** Whether the shared model is already loaded (warm). */
|
|
74
|
+
isLoaded() {
|
|
75
|
+
return this.instance !== null;
|
|
76
|
+
}
|
|
77
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellposeSegmenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
78
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellposeSegmenterService, providedIn: 'root' }); }
|
|
79
|
+
}
|
|
80
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CellposeSegmenterService, decorators: [{
|
|
81
|
+
type: Injectable,
|
|
82
|
+
args: [{ providedIn: 'root' }]
|
|
83
|
+
}] });
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbHBvc2Utc2VnbWVudGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xiYXIvc2VnbWVudGF0aW9uL2NlbGxwb3NlLXNlZ21lbnRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDOztBQUt0RCxnRkFBZ0Y7QUFDaEYsTUFBTSxpQkFBaUIsR0FDckIsaUZBQWlGLENBQUM7QUFFcEY7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxNQUFNLE9BQU8sd0JBQXdCO0lBRHJDO1FBRVUsYUFBUSxHQUFvQixJQUFJLENBQUM7UUFDakMsWUFBTyxHQUE2QixJQUFJLENBQUM7UUFDekMsYUFBUSxHQUFHLGlCQUFpQixDQUFDO0tBc0V0QztJQXBFQywrRUFBK0U7SUFDL0UsV0FBVyxDQUFDLEdBQVc7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUM7SUFDdEIsQ0FBQztJQUVELEtBQUssQ0FBQyxZQUFZLENBQ2hCLEtBQWlFLEVBQ2pFLFFBQThCO1FBRTlCLElBQUksaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1FBQzlCLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDNUIsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDaEIsSUFBSSxLQUFLO2dCQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUM7WUFDbEQsSUFBSSxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDckMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO2dCQUN6QixRQUFRLEVBQUUsUUFBUSxFQUFFLENBQUMsaUNBQWlDLENBQUMsQ0FBQztZQUMxRCxDQUFDO1FBQ0gsQ0FBQyxFQUNELENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQ3pDLENBQUM7UUFDRixRQUFRLEVBQUUsUUFBUSxFQUFFLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUM3QyxNQUFNLEdBQUcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQzFCLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUMzRTtZQUNFLDBFQUEwRTtZQUMxRSx5RUFBeUU7WUFDekUsMENBQTBDO1lBQzFDLGNBQWMsRUFBRSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FDbkQsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsMkJBQTJCLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsMEJBQTBCLENBQ3pGO1NBQ0YsQ0FDRixDQUFDO1FBQ0YsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdkYsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILFFBQVEsQ0FDTixVQUEyRCxFQUMzRCxRQUFtQztRQUVuQyxJQUFJLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDekIsc0VBQXNFO2dCQUN0RSxNQUFNLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMvRCxZQUFZLENBQUMsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUM5QyxNQUFNLEVBQUUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtvQkFDdEQsT0FBTyxFQUFFLElBQUk7b0JBQ2IsVUFBVSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUM7b0JBQzlELFFBQVEsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUMvQixDQUFDLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7Z0JBQ25CLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNQLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVELHlEQUF5RDtJQUN6RCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQztJQUNoQyxDQUFDOzhHQXhFVSx3QkFBd0I7a0hBQXhCLHdCQUF3QixjQURYLE1BQU07OzJGQUNuQix3QkFBd0I7a0JBRHBDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZ2V0T3J0V2FzbUJhc2UgfSBmcm9tICcuL29ydC1ydW50aW1lLWNvbmZpZyc7XG5cbmltcG9ydCB0eXBlIHsgSUNlbGxTZWdtZW50ZXIsIENlbGxTZWdtZW50YXRpb24sIENlbGxTZWdtZW50UHJvZ3Jlc3MgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY2VsbC1zZWdtZW50ZXIuY29udHJhY3QnO1xuaW1wb3J0IHR5cGUgeyBDZWxscG9zZSB9IGZyb20gJ2NlbGxwb3NlLWpzJztcblxuLyoqIEhvc3RlZCBjZWxscG9zZS1TQU0gT05OWCAoQ1BTQU0sIGZwMTYpLiBPdmVycmlkZSB2aWEge0BsaW5rIHNldE1vZGVsVXJsfS4gKi9cbmNvbnN0IERFRkFVTFRfTU9ERUxfVVJMID1cbiAgJ2h0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vYmFsbG9uOTk5L2NlbGxwb3NlLXNhbS1vbm54L3Jlc29sdmUvbWFpbi9jcHNhbV9mcDE2Lm9ubngnO1xuXG4vKipcbiAqIERlZmF1bHQgaW4tbGlicmFyeSB7QGxpbmsgSUNlbGxTZWdtZW50ZXJ9IGJhY2tlZCBieSBjZWxscG9zZS1qcyAoV2ViR1BVL1dBU01cbiAqIE9OTlgpIOKAlCBzbyB0aGUgdG9vbGJhcidzIGF1dG9tYXRpYyAqKkNlbGxwb3NlKiogdG9vbCB3b3JrcyBvdXQgb2YgdGhlIGJveCBpblxuICogYW55IGFwcCwgd2l0aCBubyBob3N0IHdpcmluZyAoaml0LXVpIzkwKS4gYGNlbGxwb3NlLWpzYCBpcyBhIHBlZXIgZGVwZW5kZW5jeVxuICogYW5kIGlzICoqbGF6eS1pbXBvcnRlZCoqIG9uIGZpcnN0IHVzZSwgc28gYXBwcyB0aGF0IG5ldmVyIHJ1biBDZWxscG9zZSBwYXlcbiAqIG5vdGhpbmcgZm9yIGl0LiBBIGhvc3QgY2FuIHN0aWxsIG92ZXJyaWRlIHRoZSB7QGxpbmsgQ0VMTF9TRUdNRU5URVJ9IHRva2VuIHRvXG4gKiBzdXBwbHkgYSBkaWZmZXJlbnQgaW1wbGVtZW50YXRpb24uXG4gKlxuICogT3ducyBhIHNpbmdsZSBzaGFyZWQge0BsaW5rIENlbGxwb3NlfSBpbnN0YW5jZSAob25lIG1vZGVsIGxvYWQsIG9uZSBXZWJHUFVcbiAqIHNlc3Npb24sIG9uZSB3b3JrZXIpLiB7QGxpbmsgZ2V0TW9kZWx9IGV4cG9zZXMgdGhhdCBpbnN0YW5jZSBzbyBhIGhvc3Qnc1xuICogcHJvY2Vzc2luZyBwaXBlbGluZSBjYW4gcmV1c2UgaXQgaW5zdGVhZCBvZiBsb2FkaW5nIHRoZSB+NTg4IE1CIG1vZGVsIHR3aWNlLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIENlbGxwb3NlU2VnbWVudGVyU2VydmljZSBpbXBsZW1lbnRzIElDZWxsU2VnbWVudGVyIHtcbiAgcHJpdmF0ZSBpbnN0YW5jZTogQ2VsbHBvc2UgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsb2FkaW5nOiBQcm9taXNlPENlbGxwb3NlPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG1vZGVsVXJsID0gREVGQVVMVF9NT0RFTF9VUkw7XG5cbiAgLyoqIFBvaW50IHRoZSBzZWdtZW50ZXIgYXQgYSBkaWZmZXJlbnQgaG9zdGVkIENQU0FNIE9OTlggKGJlZm9yZSBmaXJzdCB1c2UpLiAqL1xuICBzZXRNb2RlbFVybCh1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubW9kZWxVcmwgPSB1cmw7XG4gIH1cblxuICBhc3luYyBzZWdtZW50Q2VsbHMoXG4gICAgaW1hZ2U6IHsgZGF0YTogVWludDhDbGFtcGVkQXJyYXk7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0sXG4gICAgcHJvZ3Jlc3M/OiBDZWxsU2VnbWVudFByb2dyZXNzLFxuICApOiBQcm9taXNlPENlbGxTZWdtZW50YXRpb24+IHtcbiAgICBsZXQgYW5ub3VuY2VkRG93bmxvYWQgPSBmYWxzZTtcbiAgICBjb25zdCBjcCA9IGF3YWl0IHRoaXMuZ2V0TW9kZWwoXG4gICAgICAobG9hZGVkLCB0b3RhbCkgPT4ge1xuICAgICAgICBpZiAodG90YWwpIHByb2dyZXNzPy5vblByb2dyZXNzPy4obG9hZGVkIC8gdG90YWwpO1xuICAgICAgICBpZiAobG9hZGVkID4gMCAmJiAhYW5ub3VuY2VkRG93bmxvYWQpIHtcbiAgICAgICAgICBhbm5vdW5jZWREb3dubG9hZCA9IHRydWU7XG4gICAgICAgICAgcHJvZ3Jlc3M/Lm9uU3RhdHVzPy4oJ0Rvd25sb2FkaW5nIENlbGxwb3NlLVNBTSBtb2RlbOKApicpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgKHN0YXR1cykgPT4gcHJvZ3Jlc3M/Lm9uU3RhdHVzPy4oc3RhdHVzKSxcbiAgICApO1xuICAgIHByb2dyZXNzPy5vblN0YXR1cz8uKCdQcmVwcm9jZXNzaW5nIGltYWdl4oCmJyk7XG4gICAgY29uc3Qgb3V0ID0gYXdhaXQgY3Auc2VnbWVudChcbiAgICAgIHsgZGF0YTogaW1hZ2UuZGF0YSwgd2lkdGg6IGltYWdlLndpZHRoLCBoZWlnaHQ6IGltYWdlLmhlaWdodCwgY2hhbm5lbHM6IDQgfSxcbiAgICAgIHtcbiAgICAgICAgLy8gY2VsbHBvc2UtanMgcnVucyBpbmZlcmVuY2UgaW4gaXRzIHdvcmtlciAodGhlc2UgZmlyZSBiZXR3ZWVuIHRpbGVzKSBhbmRcbiAgICAgICAgLy8gYXZlcmFnaW5nL2R5bmFtaWNzIG9uIHRoZSBtYWluIHRocmVhZDsgc3VyZmFjZSBib3RoIHNvIHRoZSB0b2FzdCBzaG93c1xuICAgICAgICAvLyByZWFsIHByb2dyZXNzIGluc3RlYWQgb2YgbG9va2luZyBzdHVjay5cbiAgICAgICAgb25UaWxlUHJvZ3Jlc3M6IChkb25lLCB0b3RhbCkgPT4gcHJvZ3Jlc3M/Lm9uU3RhdHVzPy4oXG4gICAgICAgICAgZG9uZSA8IHRvdGFsID8gYFJ1bm5pbmcgaW5mZXJlbmNlICh0aWxlICR7ZG9uZX0vJHt0b3RhbH0p4oCmYCA6ICdDb21wdXRpbmcgZmxvdyBkeW5hbWljc+KApicsXG4gICAgICAgICksXG4gICAgICB9LFxuICAgICk7XG4gICAgcmV0dXJuIHsgbGFiZWxzOiBvdXQubWFza3MsIHdpZHRoOiBvdXQud2lkdGgsIGhlaWdodDogb3V0LmhlaWdodCwgY291bnQ6IG91dC5jb3VudCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaGFyZWQgQ2VsbHBvc2UgaW5zdGFuY2UsIGxhemlseSBjcmVhdGVkIG9uIGZpcnN0IHVzZSBhbmQgcmV1c2VkXG4gICAqIHRoZXJlYWZ0ZXIgKGRlZHVwZWQgYWNyb3NzIGNvbmN1cnJlbnQgY2FsbGVycykuIEV4cG9zZWQgc28gYSBob3N0IHBpcGVsaW5lXG4gICAqIGVuZ2luZSBjYW4gcnVuIHJpY2hlciBgc2VnbWVudCgpYCBvcHRpb25zIG9uIHRoZSBzYW1lIGluc3RhbmNlLiBgb25Qcm9ncmVzc2BcbiAgICogcmVwb3J0cyByYXcgZG93bmxvYWRlZC90b3RhbCBieXRlcyAoYHRvdGFsYCBpcyBudWxsIHdoZW4gdW5rbm93bik7IGBvblN0YXR1c2BcbiAgICogcmVwb3J0cyB3b3JrZXItaW5pdCBwaGFzZSBzdHJpbmdzLlxuICAgKi9cbiAgZ2V0TW9kZWwoXG4gICAgb25Qcm9ncmVzcz86IChsb2FkZWQ6IG51bWJlciwgdG90YWw6IG51bWJlciB8IG51bGwpID0+IHZvaWQsXG4gICAgb25TdGF0dXM/OiAoc3RhdHVzOiBzdHJpbmcpID0+IHZvaWQsXG4gICk6IFByb21pc2U8Q2VsbHBvc2U+IHtcbiAgICBpZiAodGhpcy5pbnN0YW5jZSkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmluc3RhbmNlKTtcbiAgICBpZiAoIXRoaXMubG9hZGluZykge1xuICAgICAgdGhpcy5sb2FkaW5nID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gTGF6eToga2VlcCBjZWxscG9zZS1qcyArIGl0cyBPUlQgcnVudGltZSBvdXQgb2YgdGhlIGluaXRpYWwgYnVuZGxlLlxuICAgICAgICBjb25zdCB7IENlbGxwb3NlLCBjb25maWd1cmVPcnQgfSA9IGF3YWl0IGltcG9ydCgnY2VsbHBvc2UtanMnKTtcbiAgICAgICAgY29uZmlndXJlT3J0KHsgd2FzbVBhdGhzOiBnZXRPcnRXYXNtQmFzZSgpIH0pO1xuICAgICAgICBjb25zdCBjcCA9IGF3YWl0IENlbGxwb3NlLmZyb21QcmV0cmFpbmVkKHRoaXMubW9kZWxVcmwsIHtcbiAgICAgICAgICBwcmVsb2FkOiB0cnVlLFxuICAgICAgICAgIG9uUHJvZ3Jlc3M6ICh7IGxvYWRlZCwgdG90YWwgfSkgPT4gb25Qcm9ncmVzcz8uKGxvYWRlZCwgdG90YWwpLFxuICAgICAgICAgIG9uU3RhdHVzOiAocykgPT4gb25TdGF0dXM/LihzKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW5zdGFuY2UgPSBjcDtcbiAgICAgICAgcmV0dXJuIGNwO1xuICAgICAgfSkoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubG9hZGluZztcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSBzaGFyZWQgbW9kZWwgaXMgYWxyZWFkeSBsb2FkZWQgKHdhcm0pLiAqL1xuICBpc0xvYWRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbnN0YW5jZSAhPT0gbnVsbDtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as ort from 'onnxruntime-web';
|
|
2
|
+
import { fetchModel, runEncoder, runDecoder } from './sam-onnx-core';
|
|
3
|
+
import { getOrtWasmBase } from './ort-runtime-config';
|
|
4
|
+
export class OnnxSamSession {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.mode = null;
|
|
7
|
+
this.loaded = false;
|
|
8
|
+
this.model = null;
|
|
9
|
+
this.inputSize = 1024;
|
|
10
|
+
// ── worker mode ──
|
|
11
|
+
this.worker = null;
|
|
12
|
+
this.seq = 0;
|
|
13
|
+
this.pending = new Map();
|
|
14
|
+
// ── in-process mode ──
|
|
15
|
+
this.encoder = null;
|
|
16
|
+
this.decoder = null;
|
|
17
|
+
this.nextToken = 1;
|
|
18
|
+
this.embeddings = new Map();
|
|
19
|
+
}
|
|
20
|
+
async loadModel(model, onProgress) {
|
|
21
|
+
if (!model.encoderUrl || !model.decoderUrl) {
|
|
22
|
+
throw new Error(`SAM model "${model.id}" has no ONNX URLs configured.`);
|
|
23
|
+
}
|
|
24
|
+
this.model = model;
|
|
25
|
+
this.inputSize = model.inputSize;
|
|
26
|
+
const hasGpu = typeof navigator !== 'undefined' && 'gpu' in navigator;
|
|
27
|
+
const eps = model.encoderProviders ?? (hasGpu ? ['webgpu', 'wasm'] : ['wasm']);
|
|
28
|
+
const usesWebGpu = eps.includes('webgpu');
|
|
29
|
+
// WebGPU must run in the worker (else it freezes the main thread); small
|
|
30
|
+
// WASM models opt into the faster in-process path via `inProcess`.
|
|
31
|
+
this.mode = !usesWebGpu && model.inProcess ? 'inproc' : 'worker';
|
|
32
|
+
if (this.mode === 'inproc') {
|
|
33
|
+
ort.env.wasm.wasmPaths = getOrtWasmBase();
|
|
34
|
+
const encBuf = await fetchModel(model.encoderUrl, onProgress);
|
|
35
|
+
const decBuf = await fetchModel(model.decoderUrl);
|
|
36
|
+
this.encoder = await ort.InferenceSession.create(encBuf, { executionProviders: eps });
|
|
37
|
+
this.decoder = await ort.InferenceSession.create(decBuf, { executionProviders: ['wasm'] });
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
await this.call({
|
|
41
|
+
type: 'load',
|
|
42
|
+
encoderUrl: model.encoderUrl,
|
|
43
|
+
decoderUrl: model.decoderUrl,
|
|
44
|
+
wasmPaths: getOrtWasmBase(),
|
|
45
|
+
inputSize: model.inputSize,
|
|
46
|
+
encoderProviders: model.encoderProviders,
|
|
47
|
+
}, [], onProgress);
|
|
48
|
+
}
|
|
49
|
+
this.loaded = true;
|
|
50
|
+
}
|
|
51
|
+
isLoaded() {
|
|
52
|
+
return this.loaded;
|
|
53
|
+
}
|
|
54
|
+
async embed(image) {
|
|
55
|
+
if (this.mode === 'inproc') {
|
|
56
|
+
const e = await runEncoder(this.encoder, image.data, image.width, image.height, this.inputSize);
|
|
57
|
+
const token = this.nextToken++;
|
|
58
|
+
this.embeddings.set(token, e);
|
|
59
|
+
if (this.embeddings.size > 3)
|
|
60
|
+
this.embeddings.delete(this.embeddings.keys().next().value);
|
|
61
|
+
return {
|
|
62
|
+
data: new Float32Array(0), dims: e.dims, scale: e.scale,
|
|
63
|
+
imageWidth: e.imageWidth, imageHeight: e.imageHeight, token,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// worker: transfer the RGBA buffer (callers pass a fresh frame buffer).
|
|
67
|
+
const buffer = image.data.buffer;
|
|
68
|
+
const res = await this.call({ type: 'embed', width: image.width, height: image.height, buffer }, [buffer]);
|
|
69
|
+
return {
|
|
70
|
+
data: new Float32Array(0), dims: res.dims, scale: res.scale,
|
|
71
|
+
imageWidth: res.imageWidth, imageHeight: res.imageHeight, token: res.token,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async decode(embedding, prompt) {
|
|
75
|
+
if (this.mode === 'inproc') {
|
|
76
|
+
const e = this.embeddings.get(embedding.token);
|
|
77
|
+
if (!e)
|
|
78
|
+
throw new Error('SAM embedding expired; re-encode the image.');
|
|
79
|
+
return runDecoder(this.decoder, e, prompt);
|
|
80
|
+
}
|
|
81
|
+
const res = await this.call({ type: 'decode', token: embedding.token, prompt });
|
|
82
|
+
return { mask: new Uint8Array(res.buffer), width: res.width, height: res.height, iou: res.iou };
|
|
83
|
+
}
|
|
84
|
+
dispose() {
|
|
85
|
+
this.worker?.terminate();
|
|
86
|
+
this.worker = null;
|
|
87
|
+
this.pending.clear();
|
|
88
|
+
this.encoder?.release?.();
|
|
89
|
+
this.decoder?.release?.();
|
|
90
|
+
this.encoder = this.decoder = null;
|
|
91
|
+
this.embeddings.clear();
|
|
92
|
+
this.loaded = false;
|
|
93
|
+
this.mode = null;
|
|
94
|
+
}
|
|
95
|
+
// ── worker plumbing ──────────────────────────────────────────────────────
|
|
96
|
+
ensureWorker() {
|
|
97
|
+
if (this.worker)
|
|
98
|
+
return this.worker;
|
|
99
|
+
const worker = new Worker(new URL('./onnx-sam.worker', import.meta.url), { type: 'module' });
|
|
100
|
+
worker.onmessage = (ev) => {
|
|
101
|
+
const m = ev.data;
|
|
102
|
+
const p = this.pending.get(m.id);
|
|
103
|
+
if (!p)
|
|
104
|
+
return;
|
|
105
|
+
if (m.type === 'progress') {
|
|
106
|
+
p.onProgress?.(m.fraction);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.pending.delete(m.id);
|
|
110
|
+
if (m.type === 'error')
|
|
111
|
+
p.reject(new Error(m.error));
|
|
112
|
+
else
|
|
113
|
+
p.resolve(m);
|
|
114
|
+
};
|
|
115
|
+
worker.onerror = (ev) => {
|
|
116
|
+
const err = new Error(ev.message || 'SAM worker crashed.');
|
|
117
|
+
for (const p of this.pending.values())
|
|
118
|
+
p.reject(err);
|
|
119
|
+
this.pending.clear();
|
|
120
|
+
};
|
|
121
|
+
this.worker = worker;
|
|
122
|
+
return worker;
|
|
123
|
+
}
|
|
124
|
+
call(msg, transfer = [], onProgress) {
|
|
125
|
+
const id = ++this.seq;
|
|
126
|
+
const worker = this.ensureWorker();
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
this.pending.set(id, { resolve, reject, onProgress });
|
|
129
|
+
worker.postMessage({ ...msg, id }, transfer);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25ueC1zYW0tc2Vzc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvdG9vbGJhci9zZWdtZW50YXRpb24vb25ueC1zYW0tc2Vzc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDO0FBS3ZDLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBc0IsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUF3QnRELE1BQU0sT0FBTyxjQUFjO0lBQTNCO1FBQ1UsU0FBSSxHQUErQixJQUFJLENBQUM7UUFDeEMsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUNmLFVBQUssR0FBdUIsSUFBSSxDQUFDO1FBQ2pDLGNBQVMsR0FBRyxJQUFJLENBQUM7UUFFekIsb0JBQW9CO1FBQ1osV0FBTSxHQUFrQixJQUFJLENBQUM7UUFDN0IsUUFBRyxHQUFHLENBQUMsQ0FBQztRQUNDLFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBbUIsQ0FBQztRQUV0RCx3QkFBd0I7UUFDaEIsWUFBTyxHQUFnQyxJQUFJLENBQUM7UUFDNUMsWUFBTyxHQUFnQyxJQUFJLENBQUM7UUFDNUMsY0FBUyxHQUFHLENBQUMsQ0FBQztRQUNMLGVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQThHakUsQ0FBQztJQTVHQyxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQWtCLEVBQUUsVUFBdUM7UUFDekUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDM0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUFjLEtBQUssQ0FBQyxFQUFFLGdDQUFnQyxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25C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SSxDQUFDLEdBQVEsRUFBRSxXQUEyQixFQUFFLEVBQUUsVUFBZ0M7UUFDcEYsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ3RCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNuQyxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztZQUN0RCxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcnQgZnJvbSAnb25ueHJ1bnRpbWUtd2ViJztcblxuaW1wb3J0IHtcbiAgSVNhbVNlc3Npb24sIFNhbUVtYmVkZGluZywgU2FtTWFza1Jlc3VsdCwgU2FtTW9kZWxEZWYsIFNhbVByb21wdCxcbn0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NhbS5jb250cmFjdCc7XG5pbXBvcnQgeyBmZXRjaE1vZGVsLCBydW5FbmNvZGVyLCBydW5EZWNvZGVyLCB0eXBlIENvcmVFbWJlZGRpbmcgfSBmcm9tICcuL3NhbS1vbm54LWNvcmUnO1xuaW1wb3J0IHsgZ2V0T3J0V2FzbUJhc2UgfSBmcm9tICcuL29ydC1ydW50aW1lLWNvbmZpZyc7XG5cbi8qKlxuICogb25ueHJ1bnRpbWUtd2ViIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJU2FtU2Vzc2lvbn0gKGppdC11aSM5MCksIHdpdGggdHdvXG4gKiBleGVjdXRpb24gbW9kZXMgY2hvc2VuIHBlciBtb2RlbDpcbiAqXG4gKiAgLSAqKmluLXByb2Nlc3MqKiAobWFpbiB0aHJlYWQpIOKAlCBmb3Igc21hbGwgV0FTTSBtb2RlbHMgZmxhZ2dlZCBgaW5Qcm9jZXNzYFxuICogICAgKGUuZy4gbWljcm8tc2FtIFZpVC1UKS4gRmFzdCBsb2FkICsgaW5mZXJlbmNlIHdpdGggbm8gV2ViIFdvcmtlciBzcGF3biAvXG4gKiAgICBzZWNvbmQgT1JUIHJ1bnRpbWUgLyBtZXNzYWdlIHJvdW5kLXRyaXBzOyB0aGUgYnJpZWYgZW5jb2RlIHJ1bnMgb24gdGhlIG1haW5cbiAqICAgIHRocmVhZCAoZmluZSBmb3IgYSB0aW55IG1vZGVsKS5cbiAqICAtICoqd29ya2VyKiog4oCUIGZvciBXZWJHUFUgbW9kZWxzIChlLmcuIFZpVC1CLCBwYXRoby1zYW0gZnAxNikgd2hvc2UgaGVhdnlcbiAqICAgIGVuY29kZSB3b3VsZCBvdGhlcndpc2UgZnJlZXplIHRoZSB0YWIuIFJ1bnMgaW4ge0BsaW5rIC4vb25ueC1zYW0ud29ya2VyfSBzb1xuICogICAgdGhlIFVJIHN0YXlzIHJlc3BvbnNpdmUgKHRoZSBzcGlubmVyIGFuaW1hdGVzKS5cbiAqXG4gKiBCb3RoIG1vZGVzIHNoYXJlIHRoZWlyIGluZmVyZW5jZSBtYXRoIHZpYSB7QGxpbmsgLi9zYW0tb25ueC1jb3JlfS4gTGF6eS1pbXBvcnRlZFxuICogYnkgdGhlIFNBTSB0b29scyBzbyBvbm54cnVudGltZS13ZWIgLyB0aGUgd29ya2VyIG5ldmVyIGxvYWQgaW4gdW5pdCB0ZXN0cyBvclxuICogdGhlIGluaXRpYWwgYnVuZGxlLlxuICovXG50eXBlIFBlbmRpbmcgPSB7XG4gIHJlc29sdmU6IChtc2c6IGFueSkgPT4gdm9pZDtcbiAgcmVqZWN0OiAoZXJyOiBFcnJvcikgPT4gdm9pZDtcbiAgb25Qcm9ncmVzcz86IChmcmFjdGlvbjogbnVtYmVyKSA9PiB2b2lkO1xufTtcblxuZXhwb3J0IGNsYXNzIE9ubnhTYW1TZXNzaW9uIGltcGxlbWVudHMgSVNhbVNlc3Npb24ge1xuICBwcml2YXRlIG1vZGU6ICdpbnByb2MnIHwgJ3dvcmtlcicgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsb2FkZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBtb2RlbDogU2FtTW9kZWxEZWYgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBpbnB1dFNpemUgPSAxMDI0O1xuXG4gIC8vIOKUgOKUgCB3b3JrZXIgbW9kZSDilIDilIBcbiAgcHJpdmF0ZSB3b3JrZXI6IFdvcmtlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNlcSA9IDA7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZyA9IG5ldyBNYXA8bnVtYmVyLCBQZW5kaW5nPigpO1xuXG4gIC8vIOKUgOKUgCBpbi1wcm9jZXNzIG1vZGUg4pSA4pSAXG4gIHByaXZhdGUgZW5jb2Rlcjogb3J0LkluZmVyZW5jZVNlc3Npb24gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkZWNvZGVyOiBvcnQuSW5mZXJlbmNlU2Vzc2lvbiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG5leHRUb2tlbiA9IDE7XG4gIHByaXZhdGUgcmVhZG9ubHkgZW1iZWRkaW5ncyA9IG5ldyBNYXA8bnVtYmVyLCBDb3JlRW1iZWRkaW5nPigpO1xuXG4gIGFzeW5jIGxvYWRNb2RlbChtb2RlbDogU2FtTW9kZWxEZWYsIG9uUHJvZ3Jlc3M/OiAoZnJhY3Rpb246IG51bWJlcikgPT4gdm9pZCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghbW9kZWwuZW5jb2RlclVybCB8fCAhbW9kZWwuZGVjb2RlclVybCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTQU0gbW9kZWwgXCIke21vZGVsLmlkfVwiIGhhcyBubyBPTk5YIFVSTHMgY29uZmlndXJlZC5gKTtcbiAgICB9XG4gICAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuICAgIHRoaXMuaW5wdXRTaXplID0gbW9kZWwuaW5wdXRTaXplO1xuICAgIGNvbnN0IGhhc0dwdSA9IHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmICdncHUnIGluIG5hdmlnYXRvcjtcbiAgICBjb25zdCBlcHM6IHN0cmluZ1tdID0gbW9kZWwuZW5jb2RlclByb3ZpZGVycyA/PyAoaGFzR3B1ID8gWyd3ZWJncHUnLCAnd2FzbSddIDogWyd3YXNtJ10pO1xuICAgIGNvbnN0IHVzZXNXZWJHcHUgPSBlcHMuaW5jbHVkZXMoJ3dlYmdwdScpO1xuICAgIC8vIFdlYkdQVSBtdXN0IHJ1biBpbiB0aGUgd29ya2VyIChlbHNlIGl0IGZyZWV6ZXMgdGhlIG1haW4gdGhyZWFkKTsgc21hbGxcbiAgICAvLyBXQVNNIG1vZGVscyBvcHQgaW50byB0aGUgZmFzdGVyIGluLXByb2Nlc3MgcGF0aCB2aWEgYGluUHJvY2Vzc2AuXG4gICAgdGhpcy5tb2RlID0gIXVzZXNXZWJHcHUgJiYgbW9kZWwuaW5Qcm9jZXNzID8gJ2lucHJvYycgOiAnd29ya2VyJztcblxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdpbnByb2MnKSB7XG4gICAgICBvcnQuZW52Lndhc20ud2FzbVBhdGhzID0gZ2V0T3J0V2FzbUJhc2UoKTtcbiAgICAgIGNvbnN0IGVuY0J1ZiA9IGF3YWl0IGZldGNoTW9kZWwobW9kZWwuZW5jb2RlclVybCwgb25Qcm9ncmVzcyk7XG4gICAgICBjb25zdCBkZWNCdWYgPSBhd2FpdCBmZXRjaE1vZGVsKG1vZGVsLmRlY29kZXJVcmwpO1xuICAgICAgdGhpcy5lbmNvZGVyID0gYXdhaXQgb3J0LkluZmVyZW5jZVNlc3Npb24uY3JlYXRlKGVuY0J1ZiwgeyBleGVjdXRpb25Qcm92aWRlcnM6IGVwcyB9KTtcbiAgICAgIHRoaXMuZGVjb2RlciA9IGF3YWl0IG9ydC5JbmZlcmVuY2VTZXNzaW9uLmNyZWF0ZShkZWNCdWYsIHsgZXhlY3V0aW9uUHJvdmlkZXJzOiBbJ3dhc20nXSB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy5jYWxsKHtcbiAgICAgICAgdHlwZTogJ2xvYWQnLFxuICAgICAgICBlbmNvZGVyVXJsOiBtb2RlbC5lbmNvZGVyVXJsLFxuICAgICAgICBkZWNvZGVyVXJsOiBtb2RlbC5kZWNvZGVyVXJsLFxuICAgICAgICB3YXNtUGF0aHM6IGdldE9ydFdhc21CYXNlKCksXG4gICAgICAgIGlucHV0U2l6ZTogbW9kZWwuaW5wdXRTaXplLFxuICAgICAgICBlbmNvZGVyUHJvdmlkZXJzOiBtb2RlbC5lbmNvZGVyUHJvdmlkZXJzLFxuICAgICAgfSwgW10sIG9uUHJvZ3Jlc3MpO1xuICAgIH1cbiAgICB0aGlzLmxvYWRlZCA9IHRydWU7XG4gIH1cblxuICBpc0xvYWRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5sb2FkZWQ7XG4gIH1cblxuICBhc3luYyBlbWJlZChpbWFnZTogeyBkYXRhOiBVaW50OENsYW1wZWRBcnJheTsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSk6IFByb21pc2U8U2FtRW1iZWRkaW5nPiB7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2lucHJvYycpIHtcbiAgICAgIGNvbnN0IGUgPSBhd2FpdCBydW5FbmNvZGVyKHRoaXMuZW5jb2RlciEsIGltYWdlLmRhdGEsIGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQsIHRoaXMuaW5wdXRTaXplKTtcbiAgICAgIGNvbnN0IHRva2VuID0gdGhpcy5uZXh0VG9rZW4rKztcbiAgICAgIHRoaXMuZW1iZWRkaW5ncy5zZXQodG9rZW4sIGUpO1xuICAgICAgaWYgKHRoaXMuZW1iZWRkaW5ncy5zaXplID4gMykgdGhpcy5lbWJlZGRpbmdzLmRlbGV0ZSh0aGlzLmVtYmVkZGluZ3Mua2V5cygpLm5leHQoKS52YWx1ZSBhcyBudW1iZXIpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGF0YTogbmV3IEZsb2F0MzJBcnJheSgwKSwgZGltczogZS5kaW1zLCBzY2FsZTogZS5zY2FsZSxcbiAgICAgICAgaW1hZ2VXaWR0aDogZS5pbWFnZVdpZHRoLCBpbWFnZUhlaWdodDogZS5pbWFnZUhlaWdodCwgdG9rZW4sXG4gICAgICB9O1xuICAgIH1cbiAgICAvLyB3b3JrZXI6IHRyYW5zZmVyIHRoZSBSR0JBIGJ1ZmZlciAoY2FsbGVycyBwYXNzIGEgZnJlc2ggZnJhbWUgYnVmZmVyKS5cbiAgICBjb25zdCBidWZmZXIgPSBpbWFnZS5kYXRhLmJ1ZmZlcjtcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmNhbGwoeyB0eXBlOiAnZW1iZWQnLCB3aWR0aDogaW1hZ2Uud2lkdGgsIGhlaWdodDogaW1hZ2UuaGVpZ2h0LCBidWZmZXIgfSwgW2J1ZmZlcl0pO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBuZXcgRmxvYXQzMkFycmF5KDApLCBkaW1zOiByZXMuZGltcywgc2NhbGU6IHJlcy5zY2FsZSxcbiAgICAgIGltYWdlV2lkdGg6IHJlcy5pbWFnZVdpZHRoLCBpbWFnZUhlaWdodDogcmVzLmltYWdlSGVpZ2h0LCB0b2tlbjogcmVzLnRva2VuLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBkZWNvZGUoZW1iZWRkaW5nOiBTYW1FbWJlZGRpbmcsIHByb21wdDogU2FtUHJvbXB0KTogUHJvbWlzZTxTYW1NYXNrUmVzdWx0PiB7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2lucHJvYycpIHtcbiAgICAgIGNvbnN0IGUgPSB0aGlzLmVtYmVkZGluZ3MuZ2V0KGVtYmVkZGluZy50b2tlbiBhcyBudW1iZXIpO1xuICAgICAgaWYgKCFlKSB0aHJvdyBuZXcgRXJyb3IoJ1NBTSBlbWJlZGRpbmcgZXhwaXJlZDsgcmUtZW5jb2RlIHRoZSBpbWFnZS4nKTtcbiAgICAgIHJldHVybiBydW5EZWNvZGVyKHRoaXMuZGVjb2RlciEsIGUsIHByb21wdCk7XG4gICAgfVxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuY2FsbCh7IHR5cGU6ICdkZWNvZGUnLCB0b2tlbjogZW1iZWRkaW5nLnRva2VuLCBwcm9tcHQgfSk7XG4gICAgcmV0dXJuIHsgbWFzazogbmV3IFVpbnQ4QXJyYXkocmVzLmJ1ZmZlciksIHdpZHRoOiByZXMud2lkdGgsIGhlaWdodDogcmVzLmhlaWdodCwgaW91OiByZXMuaW91IH07XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMud29ya2VyPy50ZXJtaW5hdGUoKTtcbiAgICB0aGlzLndvcmtlciA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nLmNsZWFyKCk7XG4gICAgdGhpcy5lbmNvZGVyPy5yZWxlYXNlPy4oKTtcbiAgICB0aGlzLmRlY29kZXI/LnJlbGVhc2U/LigpO1xuICAgIHRoaXMuZW5jb2RlciA9IHRoaXMuZGVjb2RlciA9IG51bGw7XG4gICAgdGhpcy5lbWJlZGRpbmdzLmNsZWFyKCk7XG4gICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB0aGlzLm1vZGUgPSBudWxsO1xuICB9XG5cbiAgLy8g4pSA4pSAIHdvcmtlciBwbHVtYmluZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgcHJpdmF0ZSBlbnN1cmVXb3JrZXIoKTogV29ya2VyIHtcbiAgICBpZiAodGhpcy53b3JrZXIpIHJldHVybiB0aGlzLndvcmtlcjtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgV29ya2VyKG5ldyBVUkwoJy4vb25ueC1zYW0ud29ya2VyJywgaW1wb3J0Lm1ldGEudXJsKSwgeyB0eXBlOiAnbW9kdWxlJyB9KTtcbiAgICB3b3JrZXIub25tZXNzYWdlID0gKGV2OiBNZXNzYWdlRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IG0gPSBldi5kYXRhO1xuICAgICAgY29uc3QgcCA9IHRoaXMucGVuZGluZy5nZXQobS5pZCk7XG4gICAgICBpZiAoIXApIHJldHVybjtcbiAgICAgIGlmIChtLnR5cGUgPT09ICdwcm9ncmVzcycpIHsgcC5vblByb2dyZXNzPy4obS5mcmFjdGlvbik7IHJldHVybjsgfVxuICAgICAgdGhpcy5wZW5kaW5nLmRlbGV0ZShtLmlkKTtcbiAgICAgIGlmIChtLnR5cGUgPT09ICdlcnJvcicpIHAucmVqZWN0KG5ldyBFcnJvcihtLmVycm9yKSk7XG4gICAgICBlbHNlIHAucmVzb2x2ZShtKTtcbiAgICB9O1xuICAgIHdvcmtlci5vbmVycm9yID0gKGV2OiBFcnJvckV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBlcnIgPSBuZXcgRXJyb3IoZXYubWVzc2FnZSB8fCAnU0FNIHdvcmtlciBjcmFzaGVkLicpO1xuICAgICAgZm9yIChjb25zdCBwIG9mIHRoaXMucGVuZGluZy52YWx1ZXMoKSkgcC5yZWplY3QoZXJyKTtcbiAgICAgIHRoaXMucGVuZGluZy5jbGVhcigpO1xuICAgIH07XG4gICAgdGhpcy53b3JrZXIgPSB3b3JrZXI7XG4gICAgcmV0dXJuIHdvcmtlcjtcbiAgfVxuXG4gIHByaXZhdGUgY2FsbChtc2c6IGFueSwgdHJhbnNmZXI6IFRyYW5zZmVyYWJsZVtdID0gW10sIG9uUHJvZ3Jlc3M/OiAoZjogbnVtYmVyKSA9PiB2b2lkKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBpZCA9ICsrdGhpcy5zZXE7XG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5lbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5wZW5kaW5nLnNldChpZCwgeyByZXNvbHZlLCByZWplY3QsIG9uUHJvZ3Jlc3MgfSk7XG4gICAgICB3b3JrZXIucG9zdE1lc3NhZ2UoeyAuLi5tc2csIGlkIH0sIHRyYW5zZmVyKTtcbiAgICB9KTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared base URL/path for onnxruntime-web's WASM sidecar files
|
|
3
|
+
* (`ort-wasm-simd-threaded.wasm` / `.jsep.mjs`), used by every ONNX-model tool
|
|
4
|
+
* in the library: SAM (in-process and worker) and Cellpose-SAM.
|
|
5
|
+
*
|
|
6
|
+
* Defaults to `'/assets/ort/'` — a host that serves onnxruntime-web's `dist`
|
|
7
|
+
* WASM files there (as jit-ui does via its `project.json` asset glob) needs no
|
|
8
|
+
* configuration and behaves exactly as before this knob existed. A host that
|
|
9
|
+
* cannot serve them at that path — e.g. a static deployment behind an auth
|
|
10
|
+
* proxy, or one that prefers a CDN — calls {@link setOrtWasmBase} ONCE at app
|
|
11
|
+
* init to point the runtime elsewhere:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* // version MUST match the onnxruntime-web the library was built against
|
|
15
|
+
* setOrtWasmBase('https://cdn.jsdelivr.net/npm/onnxruntime-web@1.26.0/dist/');
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Must be set before the first segmentation runs; the value is read at use time
|
|
19
|
+
* by each tool (and passed into the SAM worker via its load message), so a
|
|
20
|
+
* single call at bootstrap covers SAM and Cellpose alike.
|
|
21
|
+
*/
|
|
22
|
+
let ortWasmBase = '/assets/ort/';
|
|
23
|
+
/** Override where onnxruntime-web loads its WASM sidecars from. See module docs. */
|
|
24
|
+
export function setOrtWasmBase(base) {
|
|
25
|
+
ortWasmBase = base;
|
|
26
|
+
}
|
|
27
|
+
/** The configured onnxruntime-web WASM base (default `'/assets/ort/'`). */
|
|
28
|
+
export function getOrtWasmBase() {
|
|
29
|
+
return ortWasmBase;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3J0LXJ1bnRpbWUtY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90b29sYmFyL3NlZ21lbnRhdGlvbi9vcnQtcnVudGltZS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsSUFBSSxXQUFXLEdBQUcsY0FBYyxDQUFDO0FBRWpDLG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsY0FBYyxDQUFDLElBQVk7SUFDekMsV0FBVyxHQUFHLElBQUksQ0FBQztBQUNyQixDQUFDO0FBRUQsMkVBQTJFO0FBQzNFLE1BQU0sVUFBVSxjQUFjO0lBQzVCLE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNoYXJlZCBiYXNlIFVSTC9wYXRoIGZvciBvbm54cnVudGltZS13ZWIncyBXQVNNIHNpZGVjYXIgZmlsZXNcbiAqIChgb3J0LXdhc20tc2ltZC10aHJlYWRlZC53YXNtYCAvIGAuanNlcC5tanNgKSwgdXNlZCBieSBldmVyeSBPTk5YLW1vZGVsIHRvb2xcbiAqIGluIHRoZSBsaWJyYXJ5OiBTQU0gKGluLXByb2Nlc3MgYW5kIHdvcmtlcikgYW5kIENlbGxwb3NlLVNBTS5cbiAqXG4gKiBEZWZhdWx0cyB0byBgJy9hc3NldHMvb3J0LydgIOKAlCBhIGhvc3QgdGhhdCBzZXJ2ZXMgb25ueHJ1bnRpbWUtd2ViJ3MgYGRpc3RgXG4gKiBXQVNNIGZpbGVzIHRoZXJlIChhcyBqaXQtdWkgZG9lcyB2aWEgaXRzIGBwcm9qZWN0Lmpzb25gIGFzc2V0IGdsb2IpIG5lZWRzIG5vXG4gKiBjb25maWd1cmF0aW9uIGFuZCBiZWhhdmVzIGV4YWN0bHkgYXMgYmVmb3JlIHRoaXMga25vYiBleGlzdGVkLiBBIGhvc3QgdGhhdFxuICogY2Fubm90IHNlcnZlIHRoZW0gYXQgdGhhdCBwYXRoIOKAlCBlLmcuIGEgc3RhdGljIGRlcGxveW1lbnQgYmVoaW5kIGFuIGF1dGhcbiAqIHByb3h5LCBvciBvbmUgdGhhdCBwcmVmZXJzIGEgQ0ROIOKAlCBjYWxscyB7QGxpbmsgc2V0T3J0V2FzbUJhc2V9IE9OQ0UgYXQgYXBwXG4gKiBpbml0IHRvIHBvaW50IHRoZSBydW50aW1lIGVsc2V3aGVyZTpcbiAqXG4gKiBgYGB0c1xuICogLy8gdmVyc2lvbiBNVVNUIG1hdGNoIHRoZSBvbm54cnVudGltZS13ZWIgdGhlIGxpYnJhcnkgd2FzIGJ1aWx0IGFnYWluc3RcbiAqIHNldE9ydFdhc21CYXNlKCdodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL29ubnhydW50aW1lLXdlYkAxLjI2LjAvZGlzdC8nKTtcbiAqIGBgYFxuICpcbiAqIE11c3QgYmUgc2V0IGJlZm9yZSB0aGUgZmlyc3Qgc2VnbWVudGF0aW9uIHJ1bnM7IHRoZSB2YWx1ZSBpcyByZWFkIGF0IHVzZSB0aW1lXG4gKiBieSBlYWNoIHRvb2wgKGFuZCBwYXNzZWQgaW50byB0aGUgU0FNIHdvcmtlciB2aWEgaXRzIGxvYWQgbWVzc2FnZSksIHNvIGFcbiAqIHNpbmdsZSBjYWxsIGF0IGJvb3RzdHJhcCBjb3ZlcnMgU0FNIGFuZCBDZWxscG9zZSBhbGlrZS5cbiAqL1xubGV0IG9ydFdhc21CYXNlID0gJy9hc3NldHMvb3J0Lyc7XG5cbi8qKiBPdmVycmlkZSB3aGVyZSBvbm54cnVudGltZS13ZWIgbG9hZHMgaXRzIFdBU00gc2lkZWNhcnMgZnJvbS4gU2VlIG1vZHVsZSBkb2NzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldE9ydFdhc21CYXNlKGJhc2U6IHN0cmluZyk6IHZvaWQge1xuICBvcnRXYXNtQmFzZSA9IGJhc2U7XG59XG5cbi8qKiBUaGUgY29uZmlndXJlZCBvbm54cnVudGltZS13ZWIgV0FTTSBiYXNlIChkZWZhdWx0IGAnL2Fzc2V0cy9vcnQvJ2ApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9ydFdhc21CYXNlKCk6IHN0cmluZyB7XG4gIHJldHVybiBvcnRXYXNtQmFzZTtcbn1cbiJdfQ==
|