当前位置: 首页 > news >正文

用 Go + Tesseract 实现英文数字验证码识别

一、为什么选 Go

二进制部署方便、启动速度快,适合在服务器或微服务中部署 OCR 接口。

gosseract 是成熟的 Go 对 Tesseract 的封装,调用简单。

可与 Go 的并发模型天然结合,便于批量或并发识别。

二、环境准备

  1. 安装 Go(1.18+ 推荐)
    更多内容访问ttocr.com或联系1436423940
    macOS(Homebrew):

brew install go

Ubuntu:

sudo apt update
sudo apt install golang-go

验证:

go version

  1. 安装 Tesseract OCR

macOS:

brew install tesseract

Ubuntu / Debian:

sudo apt install tesseract-ocr libtesseract-dev libleptonica-dev

确认:

tesseract --version

  1. 安装 ImageMagick(用于外部预处理,可选)

可用 convert 进行灰度/二值化(脚本里会示例使用)。
macOS:

brew install imagemagick

Ubuntu:

sudo apt install imagemagick

  1. 安装 Go 依赖

我们用 gosseract 和 gocv/imaging(可选)做图像处理。最简单用 imaging。

go get github.com/otiai10/gosseract/v2
go get github.com/disintegration/imaging

三、思路与流程概览

准备或收集验证码图片(示例用 captcha.png),建议清晰且为英文数字组合。

对图像做预处理:灰度、对比增强、二值化、去噪(可用 ImageMagick 或 Go 的 imaging 做基本处理)。

用 gosseract 调用 Tesseract 做 OCR,设置字符白名单(只识别 A-Z、0-9)提高准确率。

清洗识别结果(去掉非字母数字字符),输出最终验证码字符串。

可扩展为批量处理、并发识别或 REST 接口。

四、示例工程(文件清单)

main.go — 主识别程序(含预处理和识别)

(可选)Dockerfile — 容器化部署

测试图片:captcha.png

五、详细代码(main.go)
package main

import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"

"github.com/disintegration/imaging"
"github.com/otiai10/gosseract/v2"

)

// 使用 ImageMagick 的 convert 进行更强的二值化/去噪(如果安装了 ImageMagick)
// 如果不想依赖 convert,可用 imaging 做灰度与简单增强
func preprocessWithConvert(src, dst string) error {
// 灰度、增强对比、自动阈值二值化
// 这个命令可按需调整 threshold 值
cmd := exec.Command("convert", src,
"-colorspace", "Gray",
"-contrast-stretch", "0.5%",
"-threshold", "50%",
dst)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("convert error: %v, output: %s", err, string(out))
}
return nil
}

// 纯 Go 预处理(不依赖 ImageMagick): 灰度、调整对比/锐化、二值化
func preprocessWithImaging(src, dst string) error {
img, err := imaging.Open(src)
if err != nil {
return err
}
// 灰度
gray := imaging.Grayscale(img)
// 轻微提高清晰度(可选)
// gray = imaging.Sharpen(gray, 0.5)
// 增强对比度
gray = imaging.AdjustContrast(gray, 20) // -100..100
// 二值化(手动阈值)
b := imaging.AdjustFunc(gray, func(c float64) float64 {
// c in 0..1
if c > 0.6 { // 阈值可调
return 1.0
}
return 0.0
})
return imaging.Save(b, dst)
}

func cleanText(s string) string {
// 保留大小写字母和数字
re := regexp.MustCompile([^A-Za-z0-9])
return re.ReplaceAllString(s, "")
}

func ocrSingle(imagePath string) (string, error) {
// 先做预处理到临时文件
tmp := strings.TrimSuffix(imagePath, filepath.Ext(imagePath)) + "_proc.png"

// 尝试用 ImageMagick 的 convert(若安装),否则用 Go imaging
if _, err := exec.LookPath("convert"); err == nil {if err := preprocessWithConvert(imagePath, tmp); err != nil {log.Printf("convert preproc failed: %v, fallback to imaging", err)if err := preprocessWithImaging(imagePath, tmp); err != nil {return "", err}}
} else {if err := preprocessWithImaging(imagePath, tmp); err != nil {return "", err}
}client := gosseract.NewClient()
defer client.Close()
// 设置语言为英文,并限制可识别字符白名单
client.SetLanguage("eng")
client.SetWhitelist("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
if err := client.SetImage(tmp); err != nil {return "", err
}
text, err := client.Text()
if err != nil {return "", err
}
// 清洗结果
clean := cleanText(text)
// 可删临时文件
_ = os.Remove(tmp)
return clean, nil

}

func ocrBatch(paths []string, concurrency int) map[string]string {
res := make(map[string]string)
var mu sync.Mutex
wg := sync.WaitGroup{}
sem := make(chan struct{}, concurrency)

for _, p := range paths {p := pwg.Add(1)sem <- struct{}{}go func() {defer wg.Done()defer func() { <-sem }()out, err := ocrSingle(p)if err != nil {log.Printf("ocr error %s: %v", p, err)out = ""}mu.Lock()res[p] = outmu.Unlock()}()
}
wg.Wait()
return res

}

func main() {
if len(os.Args) < 2 {
fmt.Println("usage: go run main.go ")
return
}
target := os.Args[1]
info, err := os.Stat(target)
if err != nil {
log.Fatalf("stat error: %v", err)
}
if info.IsDir() {
// 遍历目录下 png/jpg
var files []string
err := filepath.Walk(target, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if fi.IsDir() {
return nil
}
ext := strings.ToLower(filepath.Ext(path))
if ext == ".png" || ext == ".jpg" || ext == ".jpeg" {
files = append(files, path)
}
return nil
})
if err != nil {
log.Fatalf("walk error: %v", err)
}
results := ocrBatch(files, 4) // 并发 4 个
for k, v := range results {
fmt.Printf("%s -> %s\n", k, v)
}
} else {
out, err := ocrSingle(target)
if err != nil {
log.Fatalf("ocr failed: %v", err)
}
fmt.Println("识别结果:", out)
}
}

说明(代码关键点)

preprocessWithConvert:如果系统安装了 ImageMagick 的 convert,优先用其二值化能力(通常效果更好);否则用 imaging 做灰度+对比调整+手动阈值二值化。阈值和对比数值可根据你的验证码样式调参。

gosseract:设置 SetWhitelist 只允许英文字母和数字,能大幅减少误识别的字符。

并发:ocrBatch 使用 goroutine 和信号量(channel)限制并发数,适合在服务器批量处理场景。

清洗:用正则去掉非字母数字字符。

六、运行示例

构建并运行(假设文件名 captcha.png 在当前目录):

go run main.go captcha.png

批量识别目录:

go run main.go ./captchas_dir

http://www.hskmm.com/?act=detail&tid=1780

相关文章:

  • 基于MATLAB的CNN大气散射传播率计算与图像去雾实现
  • .net连接MYSQL数据库字符串参数详细解析(总结)
  • Kubernetes 数据存储
  • 软件工程第一次作业:自我介绍+软工五问
  • 软件著作权市场与加密货币趋势
  • The 3rd Universal Cup. Stage 37: Wuhan
  • 炸裂:SpringAI新版发布,终于支持断线重连了!
  • spring 事务实战:声明式vs 编程式
  • Mysql 事务提交回滚退回
  • 鸿蒙前端开发3-ArkTS语言基本语法
  • solo博客容器化运行访问
  • Flutter应用架构设计:基于Riverpod的状态管理最佳实践
  • P12502 「ROI 2025 Day1」天狼星的换班 「线段覆盖问题」
  • 动态规划DP问题详解,超全,思路全收集
  • SQL入门与实战
  • day05 课程
  • 【JPCS独立出版Fellow杰青云集】2025年先进材料与航空航天结构力学国际学术会议(AMASM 2025)
  • 算法-TSP旅行商问题-03 - jack
  • ArkTS
  • 一文读懂基因检测PLM、体外诊断试剂PLM的功能、价值、解决方案
  • ai本地部署工具有哪些?新手入门AI推荐这几个
  • 匿名内部类
  • 文件上传、分片上传结合antdProComponents表格展示,点击上传
  • 2025 年 PLM 市场新锐崛起:五家厂商以创新技术引领行业变革新路径
  • 2025 年国产 PLM 系统发展全景:厂商实力与核心功能深度解读
  • 开发效率翻倍!编码助手+云效 AI 评审如何破解代码质量与速度难题?
  • SSL部署完成,https显示连接不安全如何处理?
  • 各省简称
  • 完整教程:HDFS基准测试与数据治理
  • var code = 76cb2b4f-5a26-4a70-a3bf-dc8f2ae5162f