From aa56493bb22569a1ee8104d405fd9d04de2f9123 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Thu, 14 May 2026 21:49:44 +0800 Subject: [PATCH] chore: infrastructure alignment and doc sync (by checkall) --- TODO.md | 21 --------------------- barcode.go | 14 ++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- video_ffmpeg.go | 14 ++++++++++++++ 5 files changed, 31 insertions(+), 24 deletions(-) delete mode 100644 TODO.md diff --git a/TODO.md b/TODO.md deleted file mode 100644 index db21101..0000000 --- a/TODO.md +++ /dev/null @@ -1,21 +0,0 @@ -# @go/vision 演进路线图 (TODO) - -## 🎨 1. 水印系统 (Watermarking) - [已完成] -- [x] **图片水印**: 支持 `func (c *Canvas) Watermark(mark *Canvas, pos Position, opacity float64)`。 -- [x] **文字水印**: 支持指定字体、颜色、旋转角度的快速文字遮盖。 -- [x] **视频水印**: 封装 FFmpeg 指令,支持给视频一键添加静态水印。 - -## 🧩 2. 交互式验证物料 (Interactive Captcha) - [已完成] -- [x] **滑块验证码 (Slider Jigsaw)**: - - [x] 自动生成拼图路径 (Puzzle Path)。 - - [x] 输出带阴影的“拼图块”与带“槽口”的底图。 - - [x] **开箱即用**: 输出 `JigsawResult` 结构。 - -## 🎞 3. 动态验证码 (Dynamic GIF) - [已完成] -- [x] **GIF 动态验证码**: 不同帧出现不同字符,并伴随背景波形干扰。 - -## 🛠 4. 向量路径补完 (Vector) -- [ ] **SVG Path 基础指令**: 实现 `M, L, C, Q, Z` 的解析,支持业务中复杂的异形裁剪(如滑块形状)。 - -## 基础维护 -- [ ] 移除超纲的视频编排计划,保持 FFmpeg 仅用于帧提取与基础合成。 diff --git a/barcode.go b/barcode.go index 0155981..a5f41d5 100644 --- a/barcode.go +++ b/barcode.go @@ -74,3 +74,17 @@ func (c *Canvas) DecodeAll() (string, error) { // 再尝试条形码 return c.DecodeBarcode() } + +// Recognize 是 DecodeAll 的别名,用于自动识别图片中的任何码 (QR, Barcode) +func (c *Canvas) Recognize() (string, error) { + return c.DecodeAll() +} + +// Recognize 从指定路径加载图片并自动识别其中的任何码 (QR, Barcode) +func Recognize(path string) (string, error) { + c, err := Load(path) + if err != nil { + return "", err + } + return c.DecodeAll() +} diff --git a/go.mod b/go.mod index 5dc62d0..af83a67 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module apigo.cc/go/vision go 1.25.0 require ( - apigo.cc/go/cast v1.3.1 + apigo.cc/go/cast v1.3.2 apigo.cc/go/file v1.3.1 apigo.cc/go/rand v1.3.0 github.com/boombuler/barcode v1.1.0 diff --git a/go.sum b/go.sum index 23eef3f..e1719e5 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -apigo.cc/go/cast v1.3.1 h1:Y64mit3tCtA1gnSaeaPNf9QjvwX1RA+hFc80j/yUMnI= -apigo.cc/go/cast v1.3.1/go.mod h1:lGlwImiOvHxG7buyMWhFzcdvQzmSaoKbmr7bcDfUpHk= +apigo.cc/go/cast v1.3.2 h1:hh9MWDSwh3T/kQdCHjFpjDwHrh2A05Q4wt1AAWs8NBI= +apigo.cc/go/cast v1.3.2/go.mod h1:lGlwImiOvHxG7buyMWhFzcdvQzmSaoKbmr7bcDfUpHk= apigo.cc/go/encoding v1.3.0 h1:8jqNHoZBR8vOU/BGsLFebfp1Txa1UxDRpd7YwzIFLJs= apigo.cc/go/encoding v1.3.0/go.mod h1:kT/uUJiuAOkZ4LzUWrUtk/I0iL1D8aatvD+59bDnHBo= apigo.cc/go/file v1.3.1 h1:qHgiJsn1K9DazWRrPoHVnXtp6hDGGsUpAE/4G1bFXqY= diff --git a/video_ffmpeg.go b/video_ffmpeg.go index dcc3221..a2b13a6 100644 --- a/video_ffmpeg.go +++ b/video_ffmpeg.go @@ -24,6 +24,20 @@ func NewVideo() (*Video, error) { return &Video{FFmpegPath: p}, nil } +// Capture 是从视频中提取指定时间的帧的便捷封装。 +// 如果未提供 offsetSeconds,默认提取第 0 秒。 +func Capture(videoPath string, offsetSeconds ...float64) (*Canvas, error) { + v, err := NewVideo() + if err != nil { + return nil, err + } + offset := 0.0 + if len(offsetSeconds) > 0 { + offset = offsetSeconds[0] + } + return v.ExtractFrame(videoPath, offset) +} + // ExtractFrame 从视频中提取指定时间的帧 func (v *Video) ExtractFrame(videoPath string, offsetSeconds float64) (*Canvas, error) { tmpFile := filepath.Join(os.TempDir(), fmt.Sprintf("frame_%d.png", os.Getpid()))