Help us shape the future of Go! Take the 2026 Go Developer Survey

withoutbg

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

withoutbg-go

withoutBG 开放权重模型(背景去除 / alpha matting)的纯 Go 封装,基于 pure-onnx(purego 调用 ONNX Runtime,无需 CGo)。

import withoutbg "github.com/lib-x/withoutbg-go"

r, err := withoutbg.New(withoutbg.Config{ModelPath: "withoutbg-open-weights.onnx"})
if err != nil { log.Fatal(err) }
defer r.Close()

cutout, err := r.Remove(img)  // *image.NRGBA:原尺寸,RGB 是原色,A 是蒙版
alpha, err := r.Alpha(img)    // *image.Gray:只要蒙版

// 也可以走 io.Reader / io.Writer,一行完成"读图 → 抠图 → 写 PNG"
err = r.Cutout(src, dst)      // src io.Reader, dst io.Writer

特性

  • 契约优先:模型自带的 sidecar JSON(<model>.onnx.json)是权威来源,画布尺寸、张量名、dtype 都从它读,并和 ONNX 图逐项校验,不匹配直接报错
  • 可选哈希校验:Config.VerifyModelSHA256 按 sidecar 里的 sha256 校验模型文件(455MB,默认关闭)
  • 两步输出:Alpha 给蒙版,Remove 给带 alpha 通道的抠图,都是原图尺寸;返回 *image.NRGBA,RGB 是原色、A 是蒙版(不是预乘的 *image.RGBA,原因见 docs/PARAMETERS.md)
  • 流式接口:RemoveReader / AlphaReader 直接吃 io.Reader,Cutout 一行完成读图到写 PNG,WritePNG 单独可用;PNG 和 JPEG 解码器已内置注册
  • 纯 Go 依赖:无 CGo;ONNX Runtime 共享库通过 ONNXRUNTIME_LIB_PATH 指定,或由 pure-onnx 自动下载并缓存

模型文件

从 withoutbg/withoutbg-openweights-onnx 下载两个文件,必须成对使用:

文件 大小 说明
withoutbg-open-weights.onnx 454,497,726 字节 推理图(DepthAnythingV2 + ConvNeXt 抠图头)
withoutbg-open-weights.onnx.json 721 字节 sidecar:canvas_size、张量名、形状、sha256

sidecar 里的 sha256 是 29930e48e9d5ecc56d6486c53c35a4c1470566c2a3359fa180b08c8d3c34ef0f,下载后可以直接核对:

sha256sum withoutbg-open-weights.onnx

运行环境

ONNX Runtime 共享库(1.24.1):

# 方式一:指定已有共享库
export ONNXRUNTIME_LIB_PATH=/path/to/libonnxruntime.so.1.24.1

# 方式二:不设置,由 pure-onnx bootstrap 自动下载到 ~/.cache/onnx-purego

模型契约

名称 形状 类型 取值范围
输入 rgb [1, 3, 448, 448] float32 [0,1],NCHW
输出 alpha [1, 1, 448, 448] float32 [0,1]

预处理:转 RGB → 长边缩放到 448(保持比例,双线性)→ 贴在 448×448 黑底画布左上角 → 除以 255 → HWC 转 CHW。后处理:把蒙版裁到缩放区域 → 双线性缩回原尺寸 → 量化成 8 位 alpha。

参数为什么是这些值、改了会怎样,见 docs/PARAMETERS.md。

CLI

go run ./cmd/withoutbg -model withoutbg-open-weights.onnx -o cutout.png photo.jpg
# 同时导出蒙版
go run ./cmd/withoutbg -model withoutbg-open-weights.onnx -o cutout.png -alpha mask.png photo.jpg

CLI 内部就是走 Cutout 的流式接口:文件句柄直接传给库,中间不落临时文件。

已知边界

  • 最大 448 像素:模型输入是固定 448×448,更大的图会先缩小,因此细发丝、细网格这类高频细节的蒙版精度受限;需要更高精度时按官方建议自行分块处理
  • 黑底 letterbox:填充是黑色(对应文档要求),不是镜像或边缘延展
  • 无 GPU 执行提供者:默认 CPU;pure-onnx 的接口没有暴露 EP 选择
  • 矢量图/卡通表现差:模型在照片上表现好(官方样图对比 IoU 0.97 / 0.99),但对平涂卡通这类训练分布外的输入会留下大片背景。做过对照实验:把黑边填充去掉(裁成正方形再推理)反而更差,所以这是模型特性,不是预处理问题
  • 只在官方 oss 导出(version 10.0.0)上验证过;换导出时 sidecar 会跟着换,契约校验会拦住不匹配的组合

验证

go test ./...:

  • 单元测试:sidecar 解析(含缺字段、dtype 不符的负例)、letterbox 几何、输入张量取值与黑底填充、蒙版裁剪与缩放、alpha 量化、NRGBA 合成、流式接口往返
  • golden 测试:拿官方示例三联图(输入 / 抠图 / 蒙版)对比,三个样本前景 IoU 0.869、0.973、0.991,MAE 0.038、0.016、0.082(示例是缩放过的发布件,边缘不会逐点一致,断言留了余量)
  • 样图回归:testdata 里三张测试照片(卡通、庆祝海报、猫)跑通并检查蒙版分布(有前景、有背景、边缘比中心透明)

模型缺失时相关测试自动跳过。

License

库代码 Apache-2.0。模型权重来自 withoutBG(Apache-2.0),其中包含的第三方组件遵循各自条款:ConvNeXt 骨干来自 DINOv3(DINOv3 License),深度模型来自 Depth Anything V2(Apache-2.0)。

Documentation

Overview

Package withoutbg removes image backgrounds with the withoutBG open-weights ONNX model (DepthAnythingV2 + ConvNeXt matting), driven through pure-onnx (purego, no CGO).

The model expects a letterboxed RGB tensor at a fixed canvas size and returns an alpha matte of the same canvas. The authoritative contract ships next to the model file as a sidecar JSON (canvas size, tensor names, shapes, SHA256); this package reads it, validates the ONNX graph against it, and uses it for the preprocessing defaults.

Typical use:

r, err := withoutbg.New(withoutbg.Config{ModelPath: "withoutbg-open-weights.onnx"})
if err != nil {
	log.Fatal(err)
}
defer r.Close()

cutout, err := r.Remove(img) // *image.RGBA, original size, alpha = matte

Index

Constants

View Source
const (
	// DefaultCanvasSize is used when neither the sidecar nor Config provide one.
	DefaultCanvasSize = 448
	// DefaultInputName and DefaultOutputName match the published export.
	DefaultInputName  = "rgb"
	DefaultOutputName = "alpha"
)

Variables

This section is empty.

Functions

func DecodeImage added in v0.2.0

func DecodeImage(rd io.Reader) (image.Image, string, error)

DecodeImage reads an image from rd. PNG and JPEG are supported out of the box; other formats work if the caller has registered them with image.

func SidecarPath

func SidecarPath(modelPath string) string

SidecarPath returns the conventional sidecar path for a model file ("model.onnx" -> "model.onnx.json"). The published export uses exactly this naming, so the sidecar is found automatically.

func WritePNG added in v0.2.0

func WritePNG(w io.Writer, img image.Image) error

WritePNG encodes img as PNG into w. The cutouts are RGBA, so the alpha channel is preserved.

Types

type Config

type Config struct {
	// ModelPath is the path to withoutbg-open-weights.onnx (required).
	ModelPath string

	// SidecarPath overrides the sidecar location. Empty means
	// ModelPath + ".json", which is how the published export ships.
	SidecarPath string

	// CanvasSize is the square letterbox canvas fed to the model. Empty/zero
	// means "take it from the sidecar".
	CanvasSize int

	// InputName / OutputName override the ONNX tensor names. Empty means
	// "take them from the sidecar", falling back to the graph itself.
	InputName  string
	OutputName string

	// VerifyModelSHA256 checks the model file against the sidecar's sha256
	// before loading. It reads the whole file (455 MB for the published
	// export), so it is off by default.
	VerifyModelSHA256 bool

	// LibraryPath optionally points to a prebuilt libonnxruntime.so. It is
	// used only when the runtime is not yet initialized; otherwise the
	// ONNXRUNTIME_LIB_PATH environment variable or the pure-onnx bootstrap
	// download applies.
	LibraryPath string
	// contains filtered or unexported fields
}

Config controls model loading and preprocessing. Zero values fall back to the values from the sidecar (and then to the package defaults).

type Remover

type Remover struct {
	// contains filtered or unexported fields
}

Remover runs the withoutBG matting model.

func New

func New(cfg Config) (*Remover, error)

New loads the sidecar, validates the ONNX graph against it and prepares an inference session.

The sidecar is required: it carries the canvas size and tensor names, and the model repository documents it as the authoritative contract. Loading a model without it would mean guessing the preprocessing.

func (*Remover) Alpha

func (r *Remover) Alpha(img image.Image) (*image.Gray, error)

Alpha runs the model and returns the matte at the original image size. White (255) means "keep", black (0) means "background".

func (*Remover) AlphaReader added in v0.2.0

func (r *Remover) AlphaReader(rd io.Reader) (*image.Gray, error)

AlphaReader decodes an image from rd and returns the matte at its original size.

func (*Remover) Close

func (r *Remover) Close() error

Close releases the session. The ONNX Runtime environment is destroyed when the last Remover is closed.

func (*Remover) Cutout added in v0.2.0

func (r *Remover) Cutout(rd io.Reader, w io.Writer) error

Cutout is the whole stream pipeline in one call: decode an image from rd, remove its background, and write the PNG cutout to w. Use RemoveReader or AlphaReader when you want the images instead of encoded bytes.

func (*Remover) Remove

func (r *Remover) Remove(img image.Image) (*image.NRGBA, error)

Remove returns the input image with the matte attached as its alpha channel, ready to be saved as a PNG cutout. The result is an *image.NRGBA, so its RGB values are the original colours and A is the matte.

func (*Remover) RemoveReader added in v0.2.0

func (r *Remover) RemoveReader(rd io.Reader) (*image.NRGBA, error)

RemoveReader decodes an image from rd and returns the cutout.

func (*Remover) Sidecar

func (r *Remover) Sidecar() *Sidecar

Sidecar returns the loaded contract, useful for logging.

type Sidecar

type Sidecar struct {
	CanvasSize       int     `json:"canvas_size"`
	MattingInputSize int     `json:"matting_input_size"`
	OpsetVersion     int     `json:"opset_version"`
	Precision        string  `json:"precision"`
	Variant          string  `json:"variant"`
	DepthVariant     string  `json:"depth_variant"`
	ConvNeXtSize     string  `json:"convnext_size"`
	ModelVersion     string  `json:"model_version"`
	InputName        string  `json:"input_name"`
	OutputName       string  `json:"output_name"`
	InputDtype       string  `json:"input_dtype"`
	InputShape       []int   `json:"input_shape"`
	OutputShape      []int   `json:"output_shape"`
	SizeMB           float64 `json:"size_mb"`
	SHA256           string  `json:"sha256"`
	// MAE and MaxAbs describe how closely the ONNX export reproduces the
	// reference implementation on the exporter's validation set.
	MAE    float64 `json:"mae"`
	MaxAbs float64 `json:"max_abs"`
}

Sidecar is the metadata file that ships next to the ONNX export (<model>.onnx.json). It is the authoritative source for the canvas size, tensor names and shapes, precision and the model hash; the README of the model repository says to read it first, so this package does the same and validates the ONNX graph against it.

func LoadSidecar

func LoadSidecar(path string) (*Sidecar, error)

LoadSidecar reads and validates a sidecar file. A missing sidecar is an error: without it the canvas size and tensor names would be guesses.

func (*Sidecar) String

func (s *Sidecar) String() string

String summarises the contract for logs and error messages.

Directories

Path Synopsis
cmd
withoutbg command
Command withoutbg removes the background from an image with the withoutBG open-weights ONNX model.
Command withoutbg removes the background from an image with the withoutBG open-weights ONNX model.
internal
onnxmeta
Package onnxmeta reads the model contract (graph input/output names and shapes) directly from an ONNX protobuf file.
Package onnxmeta reads the model contract (graph input/output names and shapes) directly from an ONNX protobuf file.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL