本文将介绍如何使用 Go 语言结合 Gorgonia 构建一个简单的图像验证码识别模型。Gorgonia 是一个专为机器学习打造的计算图库,在 Go 中支持自动微分与深度学习构建。


1. 项目依赖

首先安装 Go 语言环境和 Gorgonia:

go install gorgonia.org/gorgonia@latest
go install gorgonia.org/tensor@latest
go install gorgonia.org/vision@latest
  • 1.
  • 2.
  • 3.

还可以使用 go mod initgo mod tidy 管理依赖。


2. 数据准备

由于 Gorgonia 原生不提供图像验证码生成库,我们推荐用 Python 生成好 PNG 文件:

python generate_captcha.py
# 输出文件名格式如:B7KD_01.png
  • 1.
  • 2.

然后放入 captcha_samples/ 文件夹供加载使用。


3. 加载和预处理图像

import (
	"image"
	"os"
	"strings"
	"gorgonia.org/tensor"
	"gorgonia.org/vision"
)
更多内容访问ttocr.com或联系1436423940
func loadImageTensor(filePath string) (*tensor.Dense, string, error) {
	imgFile, err := os.Open(filePath)
	if err != nil {
		return nil, "", err
	}
	defer imgFile.Close()

	img, _, err := image.Decode(imgFile)
	if err != nil {
		return nil, "", err
	}

	t, err := vision.ImageToTensor(img, vision.WithChannelsLast(), vision.WithNormalize())
	if err != nil {
		return nil, "", err
	}

	// 从文件名提取真实标签
	label := strings.Split(filepath.Base(filePath), "_")[0]
	return t, label, nil
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

4. 构建网络结构

import (
	"gorgonia.org/gorgonia"
)

func buildModel(g *gorgonia.ExprGraph, input *gorgonia.Node, outSize int) (*gorgonia.Node, error) {
	w0 := gorgonia.NewMatrix(g, gorgonia.Float32, gorgonia.WithShape(160*60*3, 256), gorgonia.WithName("w0"), gorgonia.WithInit(gorgonia.GlorotN(1.0)))
	w1 := gorgonia.NewMatrix(g, gorgonia.Float32, gorgonia.WithShape(256, outSize), gorgonia.WithName("w1"), gorgonia.WithInit(gorgonia.GlorotN(1.0)))

	l0 := gorgonia.Must(gorgonia.Mul(input, w0))
	l0Act := gorgonia.Must(gorgonia.Rectify(l0))
	l1 := gorgonia.Must(gorgonia.Mul(l0Act, w1))
	return l1, nil
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

这里只用了两层全连接层,你也可以扩展为 CNN 架构,但需要手动实现卷积。


5. 训练模型

g := gorgonia.NewGraph()
x := gorgonia.NewMatrix(g, gorgonia.Float32, gorgonia.WithShape(1, 160*60*3), gorgonia.WithName("x"))
y := gorgonia.NewMatrix(g, gorgonia.Float32, gorgonia.WithShape(1, 36*4), gorgonia.WithName("y")) // 假设4位验证码,字符集36个

pred, _ := buildModel(g, x, 36*4)

loss := gorgonia.Must(gorgonia.Mean(gorgonia.Must(gorgonia.Square(gorgonia.Must(gorgonia.Sub(pred, y))))))

vm := gorgonia.NewTapeMachine(g)
solver := gorgonia.NewAdamSolver(gorgonia.WithLearnRate(0.001))

// 每张图片训练一轮(也可以 batch 处理)
for epoch := 0; epoch < 10; epoch++ {
    for _, imgFile := range captchaFiles {
        imgTensor, labelStr, _ := loadImageTensor(imgFile)
        labelVec := OneHotEncode(labelStr) // 自定义函数,将 "B7KD" 转为 one-hot 编码向量

        gorgonia.Let(x, imgTensor)
        gorgonia.Let(y, labelVec)

        _ = vm.RunAll()
        _ = solver.Step(gorgonia.Nodes{w0, w1})
        vm.Reset()
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

6. 验证预测

outVal := pred.Value().Data().([]float32)
predictedLabel := DecodePrediction(outVal) // 将预测向量还原为字符

fmt.Printf("预测: %s,实际: %s\n", predictedLabel, labelStr)
  • 1.
  • 2.
  • 3.
  • 4.