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-onnx-web

v0.1.7

Published

YOLO and SAM 3 browser inference powered by onnxruntime-web

Readme

yolo-onnx-web

基于 onnxruntime-web 的浏览器端 YOLO 与 SAM 3 推理库。

本库可以在浏览器中加载 Ultralytics 风格的 ONNX 模型,解析模型元数据,根据模型版本和任务类型自动选择输出解析器,并提供分类、检测、分割、姿态估计、旋转框等任务的 Canvas 绘制方法。同时提供 Sam3,用于 SAM 3.1 multiplex 的文本概念分割(PCS)和交互式视觉分割(PVS)。

GitHub 仓库:https://github.com/freefer/yolo-onnx-web

在线 Demo:YOLO · SAM 3

English documentation: README.md

功能特性

  • 在浏览器中运行 ONNX 模型。
  • 支持 WebGPU、WASM、WebNN、WebGL、CPU 等执行后端,具体取决于浏览器和设备支持。
  • 自动解析 ONNX 自定义元数据:task、description、names。
  • 支持图片、Canvas、视频、摄像头等 CanvasImageSource 输入。
  • 提供高层任务 API:
    • 分类
    • 目标检测
    • 旋转框检测
    • 实例分割
    • 姿态估计
  • 为所有支持的任务提供通用绘制方法。
  • 支持 RF-DETR 目标检测和实例分割模型。
  • RF-DETR 的 WebGPU 预处理纹理和 buffer 会跨帧复用,yolo.dispose() 时释放。
  • 提供 Sam3,用于 SAM 3.1 multiplex:文本概念分割(PCS)和交互式视觉分割(PVS)。
  • 导出 DrawTool,可以脱离 Yolo 实例单独使用绘制工具。
  • YOLO、RF-DETR、SAM 3 共用一套多边形提取和 DrawTool.drawSegmentations() 绘制流程,同时保留原始 packed mask 与 polygon 两种绘制方式。

安装

npm install yolo-onnx-web

如果从当前仓库开发:

npm install
npm run build
npm start

浏览器示例使用 vite.config.ts 中配置的固定端口启动。

浏览器运行时配置

当前包依赖的 ONNX Runtime Web 版本是 [email protected]。

onnxruntime-web 需要找到 WASM 文件。创建模型前可以这样配置:

import { initializeOnnxRuntimeWeb } from 'yolo-onnx-web';

initializeOnnxRuntimeWeb({
  wasmPaths: '/examples/browser/ort-wasm/',
});

也可以直接传给 Yolo.create() 或 Sam3.create()。

快速开始

import { Yolo } from 'yolo-onnx-web';

const yolo = await Yolo.create({
  model: '/models/yolo26s.onnx',
  wasmPaths: '/ort-wasm/',
  executionProviders: ['webgpu', 'wasm'],
});

console.log(yolo.onnxModel.modelVersion); // 例如 V26、RTDETR、RFDETR

const image = document.querySelector('img')!;
const detections = await yolo.RunObjectDetection(image, 0.2, 0.7);

const canvas = document.querySelector('canvas')!;
yolo.drawObjectDetections(image, detections, canvas);

模型来源

model 支持以下类型:

type YoloModelSource = string | ArrayBufferLike | Uint8Array;

示例:

await Yolo.create({ model: '/models/yolov8n.onnx' });
await Yolo.create({ model: new Uint8Array(await file.arrayBuffer()) });

支持模型表

支持关系来自 ONNX 元数据:

  • task:classify、detect、obb、segment、pose
  • description:用于识别模型版本
  • names:标签映射

| 模型版本 | 分类 | 目标检测 | 旋转框检测 | 分割 | 姿态估计 | 说明 | | --- | --- | --- | --- | --- | --- | --- | | YOLOv5u (V5U) | 否 | 是 | 否 | 否 | 否 | 复用 YOLOv8 风格检测输出 | | YOLOv8 (V8) | 是 | 是 | 是 | 是 | 是 | 主要 YOLOv8 解析器 | | YOLOv8E (V8E) | 否 | 否 | 否 | 是 | 否 | 仅分割 | | YOLOv9 (V9) | 否 | 是 | 否 | 否 | 否 | 复用 YOLOv8 风格检测输出 | | YOLOv10 (V10) | 否 | 是 | 否 | 否 | 否 | 独立 YOLOv10 检测解析器 | | YOLO11 (V11) | 是 | 是 | 是 | 是 | 是 | 复用 YOLOv8 风格输出解析 | | YOLO11E (V11E) | 否 | 否 | 否 | 是 | 否 | 仅分割 | | YOLOv12 (V12) | 是 | 是 | 是 | 是 | 是 | 复用 YOLOv8 风格输出解析 | | YOLO26 (V26) | 是 | 是 | 是 | 是 | 是 | 独立 YOLO26 解析器 | | RT-DETR (RTDETR) | 否 | 是 | 否 | 否 | 否 | 独立 RT-DETR 检测解析器 | | RF-DETR (RFDETR) | 否 | 是 | 否 | 是 | 否 | 独立 RF-DETR 解析器,支持检测和分割 | | YOLO World V2 (WORLDV2) | 否 | 是 | 否 | 否 | 否 | 仅目标检测 |

模型加载完成后,可以读取当前 ONNX 模型的识别信息:

console.log(yolo.onnxModel.modelType);    // ObjectDetection、Segmentation 等
console.log(yolo.onnxModel.modelVersion); // V8、V26、RTDETR、RFDETR 等
console.log(yolo.onnxModel.modelDataType);

推理 API

分类

const results = await yolo.RunClassification(image, 5);
yolo.drawClassifications(image, results, canvas);

目标检测

const results = await yolo.RunObjectDetection(image, 0.2, 0.7);
yolo.drawObjectDetections(image, results, canvas);

旋转框检测

const results = await yolo.RunObbDetection(image, 0.2, 0.7);
yolo.drawObbDetections(image, results, canvas);

实例分割

const results = await yolo.RunSegmentation(image, 0.2, 0.65, 0.7);
yolo.drawSegmentations(image, results, canvas, {
  segmentationRenderMode: 'mask',
  drawSegmentationPixelMask: true,
  pixelMaskOpacity: 128,
  drawContour: true,
});

YOLO、RF-DETR、SAM 3 都使用 drawSegmentations()。设置 segmentationRenderMode: 'mask' 可绘制原始 packed mask;设置为 'polygon' 则让所有模型使用同一套多边形提取逻辑:

yolo.extractSegmentationPolygons()、DrawTool.extractSegmentationPolygons() 和同名独立导出都调用该提取器,并返回 Point[][]({ x, y }[][])。

const polygonsByResult = results.map(segmentation =>
  yolo.extractSegmentationPolygons(segmentation, {
    imageWidth: image.naturalWidth,
    imageHeight: image.naturalHeight,
    sourceWidth: image.naturalWidth,
    sourceHeight: image.naturalHeight,
  }),
);

yolo.drawSegmentations(image, results, canvas, {
  segmentationRenderMode: 'polygon',
  drawBoundingBoxes: true,
  drawLabel: true,
  drawSegmentationPixelMask: true,
  fillSegmentationEdgePoints: true,
  resultOpacity: 0.7,
});

姿态估计

const results = await yolo.RunPoseEstimation(image, 0.2, 0.7);
yolo.drawPoseEstimations(image, results, canvas, {
  poseConfidence: 0.25,
});

根据模型类型自动调用

async function runByModelType(yolo: Yolo, source: CanvasImageSource) {
  switch (yolo.onnxModel.modelType) {
    case 'Classification':
      return yolo.RunClassification(source);
    case 'ObjectDetection':
      return yolo.RunObjectDetection(source);
    case 'ObbDetection':
      return yolo.RunObbDetection(source);
    case 'Segmentation':
      return yolo.RunSegmentation(source);
    case 'PoseEstimation':
      return yolo.RunPoseEstimation(source);
  }
}

摄像头示例

const stream = await navigator.mediaDevices.getUserMedia({
  video: { width: { ideal: 640 }, height: { ideal: 640 } },
  audio: false,
});

const video = document.querySelector('video')!;
video.srcObject = stream;
await video.play();

const canvas = document.querySelector('canvas')!;

async function loop() {
  const results = await yolo.RunObjectDetection(video);
  yolo.drawObjectDetections(video, results, canvas, { drawSource: false });
  requestAnimationFrame(loop);
}

loop();

绘制选项

通用检测绘制选项:

yolo.drawObjectDetections(image, detections, canvas, {
  drawSource: true,
  drawLabel: true,
  drawConfidenceScore: true,
  drawLabelBackground: true,
  lineWidth: 2,
  font: '16px Arial',
  fontColor: '#f8fafc',
  boundingBoxHexColors: ['#22c55e', '#3b82f6'],
  boundingBoxOpacity: 255,
});

分割和姿态估计提供额外选项:

yolo.drawSegmentations(image, segmentations, canvas, {
  segmentationRenderMode: 'auto',
  drawSegmentationPixelMask: true,
  pixelMaskOpacity: 128,
  drawContour: true,
  contourThickness: 2,
});

yolo.drawPoseEstimations(image, poses, canvas, {
  poseConfidence: 0.25,
  defaultPoseColor: '#22c55e',
  keyPointRadius: 4,
});

分割绘制不再按模型家族拆分:

| segmentationRenderMode | 行为 | | --- | --- | | auto(默认) | 有 bitPackedPixelMask 时绘制 mask,否则把 segmentationEdgePoints 作为 polygon 填充 | | mask | 优先绘制原始 packed mask;没有 mask 时自动回退到 polygon | | polygon | packed mask 使用统一多边形提取器;仅有缓存边点时使用 segmentationEdgePoints |

已弃用的分割 API

  • DrawTool.drawSam3Segmentations() → 使用 DrawTool.drawSegmentations()。
  • DrawTool.drawSegmentationEdgePoints()、yolo.drawSegmentationEdgePoints() → 使用 drawSegmentations({ segmentationRenderMode: 'polygon' })。
  • 独立函数 maskToPolygon()、maskToPolygons() → 使用 extractSegmentationPolygon()、extractSegmentationPolygons()。

旧方法仍作为兼容包装保留,并已标记 @deprecated;它们不会再走独立的绘制或提取实现。

DrawTool 也可以作为独立绘制工具使用。适合推理和绘制分离、或者需要渲染缓存检测结果的场景:

import { DrawTool, Yolo } from 'yolo-onnx-web';

const yolo = await Yolo.create({
  model: '/models/rf-detr-seg.onnx',
  wasmPaths: '/ort-wasm/',
  executionProviders: ['webgpu', 'wasm'],
  modelVersion: 'RFDETR',
  modelType: 'Segmentation',
});

const image = document.querySelector('img')!;
const canvas = document.querySelector('canvas')!;
const segmentations = await yolo.RunSegmentation(image, 0.35, 0.5, 0.7);

const polygons = segmentations.map(segmentation =>
  DrawTool.extractSegmentationPolygons(segmentation, {
    imageWidth: image.naturalWidth,
    imageHeight: image.naturalHeight,
  }),
);

DrawTool.drawSegmentations(image, segmentations, canvas, {
  segmentationRenderMode: 'polygon',
  drawSource: true,
  drawBoundingBoxes: true,
  drawLabel: true,
  drawSegmentationPixelMask: true,
  fillSegmentationEdgePoints: true,
  resultOpacity: 0.7,
});

SAM 3

Sam3 与 Yolo 是独立 API。SAM 3.1 multiplex 使用四张 ONNX 图,会缓存图像嵌入,并按提示逐步交互。它不走 IYoloHandler。

导出 ONNX

python scripts/export_sam3_onnx.py --checkpoint sam3.1_multiplex.pt --output-dir ./sam3-onnx
python scripts/export_sam3_onnx.py --output-dir ./sam3-onnx --fold-existing --convert-fp16

--fold-existing 会去掉恒为假的 If 节点,否则 onnxruntime-web 会在形状推断时报错。--convert-fp16 会生成 *.fp16.onnx。浏览器请加载 fp16 视觉/文本编码器。

需要的文件:

| 文件 | 作用 | | --- | --- | | vision-encoder.fp16.onnx | 图像 → 检测 FPN + PVS 嵌入 | | text-encoder.fp16.onnx | CLIP token → 语言特征 | | grounding-decoder.onnx | PCS(按概念找出全部实例) | | prompt-decoder.onnx | PVS(只分割当前提示的那一件) | | clip_bpe.json | CLIP BPE tokenizer 表 |

图像会缩放到 1008×1008,mean/std 为 0.5。请优先使用 WebGPU,并设置 numThreads: 1。

快速开始

import { Sam3 } from 'yolo-onnx-web';

const sam3 = await Sam3.create({
  visionEncoder: visionBytes,
  textEncoder: textBytes,
  groundingDecoder: groundingBytes,
  promptDecoder: promptBytes,
  tokenizer: '/models/clip_bpe.json',
  wasmPaths: '/ort-wasm/',
  executionProviders: ['webgpu'],
  numThreads: 1,
  confidenceThreshold: 0.5,
  onLoadProgress: message => console.log(message),
});

const image = document.querySelector('img')!;
const canvas = document.querySelector('canvas')!;
await sam3.setImage(image);

const pcs = await sam3.setTextPrompt('person, car, dog', 'wearing a red hat');
sam3.drawSegmentations(image, pcs, canvas);

const pvs = await sam3.addPoint({ x: 120, y: 80 }, 1);
sam3.drawSegmentations(image, pvs.masks, canvas);

await sam3.dispose();

模型来源与 Yolo.create() 相同,可以是 URL、ArrayBuffer 或 Uint8Array。

概念分割(PCS)

类别名只按逗号拆分(person, car, dog / 猫, 狗),不要用空格拆词。可选的详细描述会拼进查询(person, wearing a red hat),界面标签仍用类别名。

PCS 里的框和点是范例:模型会在全图找出同类实例,而不是只分割当前画出的那一件。

await sam3.setTextPrompt('person, car');
await sam3.addGeometricPrompt({ x: 10, y: 20, width: 80, height: 120 }, true);
await sam3.addGeometricPoint({ x: 40, y: 60 }, true);
sam3.resetPrompts();

视觉分割(PVS)

PVS 只分割当前提示的那一件。点标签:1 前景,0 背景。PVS 需要 promptDecoder。iou_predictions 是未校准回归,可能大于 1;展示时请把分数限制在 [0, 1]。

const byPoint = await sam3.addPoint({ x: 120, y: 80 }, 1);
const byBox = await sam3.addBox({ x: 40, y: 50, width: 200, height: 160 });
sam3.resetVisualPrompts();

绘制

PCS 后处理会按 bbox 裁剪 mask,并填写 segmentationEdgePoints。sam3.drawSegmentations() 与 YOLO、RF-DETR 使用同一绘制流程,可通过 segmentationRenderMode 选择 auto、mask 或 polygon。

sam3.drawSegmentations(image, masks, canvas, {
  segmentationRenderMode: 'auto',
  drawSource: true,
  drawBoundingBoxes: true,
  drawLabel: true,
  drawSegmentationPixelMask: true,
  fillSegmentationEdgePoints: true,
  resultOpacity: 0.7,
});

浏览器示例

在线 Demo:

本地启动:

npm start

打开:

https://localhost:5173/
https://localhost:5173/examples/browser/
https://localhost:5173/examples/browser/sam3.html

YOLO 示例页默认使用摄像头模式。如果没有选择本地模型,也没有填写模型 URL,则默认使用:

/examples/model/yolo26s.onnx

SAM 3 示例不会托管数 GB 的 ONNX。请选择本地导出目录,或分别选择各个模型文件,再点「加载模型」。

构建

npm run build
npm run build:pages

库构建结果输出到 dist/。GitHub Pages Demo 构建到 dist-example/(含 YOLO 与 SAM 3 页面,不含 SAM 3 权重)。

注意事项

  • YOLO 模型需要包含 Ultralytics 兼容的 ONNX metadata。
  • SAM 3 图来自 scripts/export_sam3_onnx.py。浏览器请加载 fp16 视觉/文本编码器;全精度编码器很容易触发 WASM bad_alloc。
  • 更换模型或卸载页面时请调用 yolo.dispose(),以便释放 RF-DETR WebGPU 预处理纹理和 buffer。
  • WebGPU、WebNN、WebGL 等后端是否可用取决于浏览器和设备。
  • WebGPU 通常需要 HTTPS 或 localhost 环境。
  • GitHub Pages 不托管数 GB 的 SAM 3 权重。在线 SAM 3 Demo 需要你选择本地导出目录。