8000
Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

license mit
pipeline_tag mask-generation
tags
mask-generation
image-segmentation
logo

go-vision forks go-vision stars go-vision pull-requests

go-vision 基于 Golang + ONNX 构建的视觉库,支持 SAM2、YOLOv11-Det、YOLOv11-Seg、YOLOv11-Cls、YOLOv11-Pose、YOLOv11-OBB、YOLO26-Det、 YOLO26-Seg、YOLO26-Cls、YOLO26-Pose、YOLO26-OBB、DINOv2-Seg 等模型。

安装

# 下载包
go get -u github.com/getcharzp/go-vision

# 下载模型、动态链接库
git clone https://huggingface.co/getcharzp/go-vision

快速开始

sam2

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/sam2"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	engine, err := sam2.NewEngine(sam2.DefaultConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	imgCtx, err := engine.EncodeImage(img)
	if err != nil {
		log.Fatalf("图片 Encode 失败: %v", err)
	}
	defer imgCtx.Destroy()

	points := []sam2.Point{
		{X: 367, Y: 168, Label: sam2.LabelBoxTopLeft},  // 左上
		{X: 441, Y: 349, Label: sam2.LabelBoxBotRight}, // 右下
	}
	imgResult, score, err := imgCtx.Decode(points)
	if err != nil {
		log.Fatalf("Mask Decode 失败: %v", err)
	}

	fmt.Printf("Mask generated, score: %.4f\n", score)
	imageutil.Save("output_mask.png", imgResult, 100)
}
原图 Mask图

yolov11-det

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolov11"
	"github.com/up-zero/gotool/imageutil"
	"image"
	"image/color"
	"image/draw"
	"log"
)

func main() {
	engine, err := yolov11.NewDetEngine(yolov11.DefaultDetConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	targetImg := image.NewRGBA(img.Bounds())
	draw.Draw(targetImg, img.Bounds(), img, img.Bounds().Min, draw.Src)
	fmt.Printf("检测到目标: %d 个\n", len(results))
	for _, res := range results {
		fmt.Printf("Class: %d, Score: %.2f, Box: %v\n", res.ClassID, res.Score, res.Box)
		imageutil.DrawThickRectOutline(targetImg, res.Box, color.RGBA{R: 255, G: 0, B: 0, A: 255}, 3)
	}
	imageutil.Save("yolov11_det.jpg", targetImg, 50)
}
原图 检测结果

yolov11-seg

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolov11"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	engine, err := yolov11.NewSegEngine(yolov11.DefaultSegConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	fmt.Printf("检测到目标: %d 个\n", len(results))
	for idx, res := range results {
		fmt.Printf("Class: %d, Score: %.2f, Box: %v\n", res.ClassID, res.Score, res.Box)
		imageutil.Save(fmt.Sprintf("yolov11_seg_mask_%d.png", idx), res.Mask, 100)
	}
}
原图 Mask图

yolov11-cls

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolov11"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	engine, err := yolov11.NewClsEngine(yolov11.DefaultClsConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img, 5)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	for _, res := range results {
		fmt.Printf("Class: %d, Score: %.5f\n", res.ClassID, res.Score)
	}
}

// 输出:
//  Class: 656, Score: 0.70231
//  Class: 436, Score: 0.22404
//  Class: 511, Score: 0.02263
//  Class: 675, Score: 0.01796
//  Class: 717, Score: 0.00385

yolov11-pose

package main

import (
	"github.com/getcharzp/go-vision/yolov11"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	engine, err := yolov11.NewPoseEngine(yolov11.DefaultPoseConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./person.jpg")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	dst := yolov11.DrawPoseResult(img, results)
	imageutil.Save("yolov11_pose.jpg", dst, 50)
}
原图 姿态图

yolov11-obb

package main

import (
	"github.com/getcharzp/go-vision/yolov11"
	"github.com/up-zero/gotool/imageutil"
	"image"
	"image/color"
	"image/draw"
	"log"
)

func main() {
	engine, err := yolov11.NewOBBEngine(yolov11.DefaultOBBConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./ship.jpg")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	dst := image.NewRGBA(img.Bounds())
	draw.Draw(dst, img.Bounds(), img, img.Bounds().Min, draw.Src)
	for _, result := range results {
		imageutil.DrawThickPolygonOutline(dst, result.Corners[:], 3, color.RGBA{R: 255, G: 0, B: 0, A: 255})
	}
	imageutil.Save("yolov11_obb.jpg", dst, 50)
}
原图 OBB图

yolo26-det

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolo26"
	"github.com/up-zero/gotool/imageutil"
	"image"
	"image/color"
	"image/draw"
	"log"
)

func main() {
	engine, err := yolo26.NewDetEngine(yolo26.DefaultDetConfig())
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	targetImg := image.NewRGBA(img.Bounds())
	draw.Draw(targetImg, img.Bounds(), img, img.Bounds().Min, draw.Src)
	fmt.Printf("检测到目标: %d 个\n", len(results))
	for _, res := range results {
		fmt.Printf("Class: %d, Score: %.2f, Box: %v\n", res.ClassID, res.Score, res.Box)
		imageutil.DrawThickRectOutline(targetImg, res.Box, color.RGBA{R: 255, G: 0, B: 0, A: 255}, 3)
	}
	imageutil.Save("yolo26_det.jpg", targetImg, 50)
}
原图 检测结果

yolo26-seg

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolo26"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	cfg := yolo26.DefaultSegConfig()
	cfg.ModelPath = "../yolo26_weights/yolo26s-seg.onnx"
	cfg.OnnxRuntimeLibPath = "../lib/onnxruntime.dll"

	engine, err := yolo26.NewSegEngine(cfg)
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	fmt.Printf("检测到目标: %d 个\n", len(results))
	for idx, res := range results {
		fmt.Printf("Class: %d, Score: %.2f, Box: %v\n", res.ClassID, res.Score, res.Box)
		imageutil.Save(fmt.Sprintf("yolo26_seg_mask_%d.png", idx), res.Mask, 100)
	}
}
原图 Mask图

yolo26-cls

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/yolo26"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	cfg := yolo26.DefaultClsConfig()
	cfg.ModelPath = "../yolo26_weights/yolo26m-cls.onnx"
	cfg.OnnxRuntimeLibPath = "../lib/onnxruntime.dll"

	engine, err := yolo26.NewClsEngine(cfg)
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	results, err := engine.Predict(img, 5)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	for _, res := range results {
		fmt.Printf("Class: %d, Score: %.5f\n", res.ClassID, res.Score)
	}
}

// 输出:
//  Class: 656, Score: 0.99169
//  Class: 436, Score: 0.00258
//  Class: 511, Score: 0.00242
//  Class: 654, Score: 0.00054
//  Class: 675, Score: 0.00053

yolo26-pose

package main

import (
	"github.com/getcharzp/go-vision/yolo26"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	cfg := yolo26.DefaultPoseConfig()
	cfg.ModelPath = "../yolo26_weights/yolo26m-pose.onnx"
	cfg.OnnxRuntimeLibPath = "../lib/onnxruntime.dll"

	engine, err := yolo26.NewPoseEngine(cfg)
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./person.jpg")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	dst := yolo26.DrawPoseResult(img, results)
	imageutil.Save("yolo26_pose.jpg", dst, 50)
}
原图 姿态图

yolo26-obb

package main

import (
	"github.com/getcharzp/go-vision/yolo26"
	"github.com/up-zero/gotool/imageutil"
	"image"
	"image/color"
	"image/draw"
	"log"
)

func main() {
	cfg := yolo26.DefaultOBBConfig()
	cfg.ModelPath = "../yolo26_weights/yolo26m-obb.onnx"
	cfg.OnnxRuntimeLibPath = "../lib/onnxruntime.dll"

	engine, err := yolo26.NewOBBEngine(cfg)
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./ship.jpg")
	results, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	dst := image.NewRGBA(img.Bounds())
	draw.Draw(dst, img.Bounds(), img, img.Bounds().Min, draw.Src)
	for _, result := range results {
		imageutil.DrawThickPolygonOutline(dst, result.Corners[:], 3, color.RGBA{R: 255, G: 0, B: 0, A: 255})
	}
	imageutil.Save("yolo26_obb.jpg", dst, 50)
}
原图 OBB图

dinov2-seg

DINOv2 输出的是 Patch 特征 (last_hidden_state), 通过 k-means 聚类将特征相似的区域划分为同一个分割区域, 属于无监督分割

package main

import (
	"fmt"
	"github.com/getcharzp/go-vision/dinov2"
	"github.com/up-zero/gotool/imageutil"
	"log"
)

func main() {
	cfg := dinov2.DefaultConfig()
	cfg.ModelPath = "../dinov2_weights/model.onnx"
	cfg.OnnxRuntimeLibPath = "../lib/onnxruntime.dll"
	cfg.NumClusters = 3 // 分割区域数量

	engine, err := dinov2.NewEngine(cfg)
	if err != nil {
		log.Fatalf("初始化引擎失败: %v", err)
	}
	defer engine.Destroy()

	img, _ := imageutil.Open("./test.png")
	result, err := engine.Predict(img)
	if err != nil {
		log.Fatalf("预测失败: %v", err)
	}

	fmt.Printf("原图尺寸: %d x %d, 分割区域: %d 个\n", result.Width, result.Height, len(result.Masks))
	for idx, mask := range result.Masks {
		imageutil.Save(fmt.Sprintf("dinov2_seg_mask_%d.png", idx), mask, 100)
	}

	dst := dinov2.DrawResult(img, result)
	imageutil.Save("dinov2_seg.jpg", dst, 90)
}
原图 分割结果

About

go-vision 基于 Golang + ONNX 构建的视觉库,支持 SAM2、YOLOv11-Det、YOLOv11-Seg、YOLOv11-Cls、YOLOv11-Pose、YOLOv11-OBB、YOLO26-Det、YOLO26-Seg、YOLO26-Cls、YOLO26-Pose、YOLO26-OBB、DINOv2-Seg 等模型

Topics

Resources

Stars

59 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

0