Go 构建图像验证码识别 HTTP 服务
本教程展示如何使用 Go 搭建一个图像验证码识别服务,用户可以通过发送图片文件的 POST 请求,获取识别出的验证码内容。该服务将图像预处理、字符分割、模型推理打包成一个 RESTful API 接口。
一、项目结构概述
captcha-server/
├── main.go
├── model.onnx # 已训练好的字符识别模型
├── handler.go # HTTP 处理逻辑
└── utils.go # 图像处理与模型预测工具函数
二、服务接口说明
URL: /predict
方法: POST
更多内容访问ttocr.com或联系1436423940
参数: image,类型为 multipart/form-data
返回值: JSON,示例:
{ "result": "a9C7" }
三、核心代码实现
main.go
package main
import (
"log"
"net/http"
)
func main() {
LoadModel("model.onnx") // 加载 ONNX 模型
http.HandleFunc("/predict", HandleCaptcha)
log.Println("服务启动,监听端口 8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
handler.go
package main
import (
"encoding/json"
"fmt"
"gocv.io/x/gocv"
"io"
"net/http"
)
func HandleCaptcha(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20)
file, _, err := r.FormFile("image")
if err != nil {
http.Error(w, "上传图片失败", http.StatusBadRequest)
return
}
defer file.Close()
// 读取为图像
data, _ := io.ReadAll(file)
img, err := gocv.IMDecode(data, gocv.IMReadGrayScale)
if err != nil || img.Empty() {
http.Error(w, "图像解析失败", http.StatusBadRequest)
return
}
defer img.Close()
result := PredictCaptcha(img)
// 返回 JSON
resp := map[string]string{"result": result}
json.NewEncoder(w).Encode(resp)
}
utils.go
package main
import (
"gocv.io/x/gocv"
"github.com/microsoft/onnxruntime-go"
"image"
)
var (
modelSession *onnxruntime.Session
labels = "0123456789abcdefghijklmnopqrstuvwxyz"
)
func LoadModel(path string) {
env, _ := onnxruntime.NewEnvironment()
session, _ := env.NewSession(path)
modelSession = session
}
func PredictCaptcha(img gocv.Mat) string {
chars := splitImage(img)
result := ""
for _, ch := range chars {
data := preprocess(ch)
c := predictChar(data)
result += string(c)
ch.Close()
}
return result
}
func splitImage(img gocv.Mat) []gocv.Mat {
step := img.Cols() / 4
var out []gocv.Mat
for i := 0; i < 4; i++ {
crop := img.Region(image.Rect(istep, 0, (i+1)step, img.Rows()))
resized := gocv.NewMat()
gocv.Resize(crop, &resized, image.Pt(28, 28), 0, 0, gocv.InterpolationLinear)
out = append(out, resized.Clone())
crop.Close()
resized.Close()
}
return out
}
func preprocess(mat gocv.Mat) []float32 {
data := make([]float32, 2828)
for y := 0; y < 28; y++ {
for x := 0; x < 28; x++ {
data[y28+x] = float32(mat.GetUCharAt(y, x)) / 255.0
}
}
return data
}
func predictChar(data []float32) byte {
tensor, _ := onnxruntime.NewTensor([]int64{1, 1, 28, 28}, data)
outputs, _ := modelSession.Run(map[string]*onnxruntime.Tensor{"input": tensor})
maxIdx := 0
scores := outputs[0].Float32Data()
for i, s := range scores {
if s > scores[maxIdx] {
maxIdx = i
}
}
return labels[maxIdx]
}
四、测试请求
你可以使用 curl 或 Postman 进行测试:
curl -X POST http://localhost:8080/predict
-F "image=@captcha.png"
返回示例:
{"result":"a8K2"}
浙公网安备 33010602011771号