npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

yolo-segdetect-js

v0.1.7

Published

Browser-side YOLOv8-seg instance segmentation on WebGPU — the browser counterpart to yolo-segdetect-worker, minus Temporal.

Downloads

1,284

Readme

yolo-segdetect-js

Browser-side YOLOv8-seg instance segmentation on WebGPU, running ONNX models exported by browser-onnx-tools.

It is the browser counterpart to yolo-segdetect-worker: same tiling strategy, same merge semantics, same thresholds — minus Temporal, Java and OpenCV.

Install

npm install yolo-segdetect-js onnxruntime-web

onnxruntime-web is a peer dependency, so the host controls its version and its asset pipeline.

Quickstart

import { YoloSegmenter, configureOrt } from 'yolo-segdetect-js';

// One-time: tell ORT where its WASM sidecars are served from. They must be
// same-origin — browsers block the cross-origin dynamic import ORT uses.
configureOrt({ wasmPaths: '/assets/ort/' });

const base = 'https://huggingface.co/Ballon999/yolov8x-seg-opticnerve-onnx/resolve/main';

const seg = await YoloSegmenter.fromPretrained(`${base}/model.fp16w.onnx`, {
  preload: true,
  onProgress: ({ loaded, total }) => console.log(`${loaded}/${total ?? '?'} bytes`),
  onStatus: (s) => console.log(s),
});

const ctx = canvas.getContext('2d')!;
const image = ctx.getImageData(0, 0, canvas.width, canvas.height);

const result = await seg.segment(image, {
  confThreshold: 0.6, // per-tile confidence
  iouThreshold: 0.5, // per-tile NMS
  threshold: 0.3, // cross-tile merge (IoS)
  overlapX: 60,
  overlapY: 60,
  onTileProgress: (done, total) => console.log(`tile ${done}/${total}`),
});

for (const d of result.detections) {
  console.log(d.className, d.score, d.polygons?.[0]?.exterior.length, 'vertices');
}

model.json is fetched automatically from alongside the weights; it carries the class names, class count and input size, so a newly exported model needs no code change.

Which model file to load

Every published repo contains model.onnx, model.fp16w.onnx and model.json.

Use model.fp16w.onnx. It stores weights in half precision and computes in fp32 — half the download, numerically identical results. A true-fp16 export (model.fp16.onnx) accumulates in fp16 on WebGPU, and on the x-scale models that degrades WebGPU/WASM agreement to a cosine of 0.967: a correct 0.859-confidence detection becomes a wrong box. Do not ship it.

Execution providers

Defaults to ['webgpu', 'wasm'], dropping WebGPU when the browser has no navigator.gpu.

Because fp16w computes in fp32, WASM produces the same numbers as WebGPU — just far slower (~5s/tile vs ~110ms/tile on an M1 Max). That makes it a real fallback, and a real reference:

const cpu = await YoloSegmenter.fromPretrained(url, { executionProviders: ['wasm'] });

Use it. WebGPU failures in this stack are silently wrong numbers, never exceptions — a wide Concat returning zeros, or fp16 accumulation drift. A same-machine CPU comparison is the cheapest way to catch one.

What runs where

The main thread does nothing but marshal. Crop, letterbox, inference, decode, NMS, cross-tile merge and contour tracing all happen inside the worker; only finished detections come back. cellpose-js learned this the hard way — with postprocessing on the main thread the UI froze for seconds per run, and mask assembly here is comparable work (32 multiply-adds per mask pixel).

Output

interface Detection {
  box: [number, number, number, number]; // sub-pixel, image coordinates
  score: number;
  classId: number;
  className?: string;
  polygons?: MaskPolygon[]; // { exterior, holes }, image coordinates
  mask: Uint8Array | null; // box-local; omitted unless includeMasks
  maskBox: [number, number, number, number] | null;
}

Masks are box-local — a small buffer covering the detection's own box. The Python allocates a full-image plane per detection, which is fine for a 512px crop and gigabytes at whole-slide scale. They are dropped from the result by default once contours are traced; pass includeMasks: true to keep them.

Polygon rings are closed implicitly (the last point is not a repeat of the first) and are simplified with Douglas-Peucker at a 1px tolerance, which collapses pixel staircases into clean diagonals. Pass traceOptions: { simplifyTolerance: 0 } for exact pixel boundaries.

Behaviour inherited from the Python

Kept deliberately, because divergence here means the browser preview disagrees with the server:

  • IoS, not IoU, for cross-tile merging. A detection clipped by a tile edge is contained in the full detection next door: low IoU, IoS ≈ 1. Plain IoU leaves a duplicate at every seam.
  • The "intelligent sorter". Confidence is binned (10 bins), then ties break by area, largest first — so within a bin the whole object beats the clipped fragment that scored marginally higher.
  • Two-stage suppression. Box overlap only nominates a pair; the decision is made on mask overlap. Adjacent structures can have overlapping boxes and disjoint masks.
  • 8-connected foreground when tracing contours, matching OpenCV's findContours, which is what Ultralytics uses.

Authenticated model hosting

fromPretrained accepts pre-fetched bytes or a custom HTTP client, so the model need not come from a public origin:

// Pre-fetched
await YoloSegmenter.fromPretrained(url, { modelBytes, meta });

// Or route every request through the host's stack (auth interceptors, proxies)
await YoloSegmenter.fromPretrained(url, { fetcher: myAuthenticatedFetch });

This is a deliberate departure from cellpose-js, which hardcodes a raw fetch. Behind an OAuth2 proxy a raw fetch bypasses the interceptor, 302s to a login page, and then fails CORS.

Caching

Weights and metadata are cached in IndexedDB, keyed by URL plus an ETag/Last-Modified probed via HEAD, so a re-uploaded model invalidates automatically. clearCachedModel(url) drops an entry.

Development

npm install
npm run build       # tsc — per-module ESM, so bundlers can find the worker
npm test            # vitest
npm run typecheck
npm run lint

The build is plain tsc on purpose. Per-module output is what lets new Worker(new URL('./inference.worker.js', import.meta.url)) resolve to a real file that webpack, Vite and the Angular CLI can each detect and emit as its own chunk. A bundled single-file build breaks that.

License

Copyright (C) 2026 The Jackson Laboratory.

AGPL-3.0-only. See LICENSE.

This is not an incidental choice. The tiling and cross-tile merge logic is a port of patched_yolo_infer (AGPL-3.0), which in turn builds on Ultralytics YOLOv8 (AGPL-3.0), and it deliberately reproduces that project's specific design decisions — the confidence-binned "intelligent sorter", the intersection-over-smaller metric, the two-stage box-then-mask suppression — because agreeing with the server result is the whole point. The published model weights are AGPL-3.0 as well, though they are fetched at runtime and are not redistributed here.

If you need this under a permissive license, the tiling/merge stage is the part that would have to be rewritten from documented behaviour rather than ported; the rest of the library (model cache, ORT session handling, worker harness, contour tracing) has no AGPL lineage.