Compare commits
No commits in common. "4fd7ffbcf996b655d359a96e70b4c76504c084a1" and "6573dd6f24e6da07328b6a8dfedb3ddf01e6a464" have entirely different histories.
4fd7ffbcf9
...
6573dd6f24
21
TODO.md
Normal file
21
TODO.md
Normal file
@ -0,0 +1,21 @@
|
||||
# @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 仅用于帧提取与基础合成。
|
||||
14
barcode.go
14
barcode.go
@ -74,17 +74,3 @@ 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()
|
||||
}
|
||||
|
||||
10
go.mod
10
go.mod
@ -3,9 +3,9 @@ module apigo.cc/go/vision
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
apigo.cc/go/cast v1.3.3
|
||||
apigo.cc/go/file v1.3.2
|
||||
apigo.cc/go/rand v1.3.1
|
||||
apigo.cc/go/cast v1.3.1
|
||||
apigo.cc/go/file v1.3.1
|
||||
apigo.cc/go/rand v1.3.0
|
||||
github.com/boombuler/barcode v1.1.0
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/flopp/go-findfont v0.1.0
|
||||
@ -16,8 +16,8 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
apigo.cc/go/encoding v1.3.1 // indirect
|
||||
apigo.cc/go/safe v1.3.1 // indirect
|
||||
apigo.cc/go/encoding v1.3.0 // indirect
|
||||
apigo.cc/go/safe v1.3.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
golang.org/x/crypto v0.51.0 // indirect
|
||||
|
||||
20
go.sum
20
go.sum
@ -1,13 +1,13 @@
|
||||
apigo.cc/go/cast v1.3.3 h1:aln5eDR5DZVWVzZ/y5SJh1gQNgWv2sT82I25NaO9g34=
|
||||
apigo.cc/go/cast v1.3.3/go.mod h1:lGlwImiOvHxG7buyMWhFzcdvQzmSaoKbmr7bcDfUpHk=
|
||||
apigo.cc/go/encoding v1.3.1 h1:y8O58KYAyulkThg1O2ji2BqjnFoSvk42sit9I3z+K7Y=
|
||||
apigo.cc/go/encoding v1.3.1/go.mod h1:xAJk5b83VZ31mXMTnyp0dfMoBKfT/AHDn0u+cQfojgY=
|
||||
apigo.cc/go/file v1.3.2 h1:pu4oiDyiqgj3/eykfnJf+/6+A9v/Z0b3ClP5XK+lwG4=
|
||||
apigo.cc/go/file v1.3.2/go.mod h1:vci4h0Pz94mV6dkniQkuyBYERVYeq7/LX4jJVuCg9hs=
|
||||
apigo.cc/go/rand v1.3.1 h1:7FvsI6PtQ5XrWER0dTiLVo0p7GIxRidT/TBKhVy93j8=
|
||||
apigo.cc/go/rand v1.3.1/go.mod h1:mZ/4Soa3bk+XvDaqPWJuUe1bfEi4eThBj1XmEAuYxsk=
|
||||
apigo.cc/go/safe v1.3.1 h1:irTCqPAC97gGsX/Lw5AzLelDt1xXLEZIAaVhLELWe9Q=
|
||||
apigo.cc/go/safe v1.3.1/go.mod h1:XdOpBhN2vkImalaykYXXmEpczqWa1y3ah6/Q72cdRqE=
|
||||
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/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=
|
||||
apigo.cc/go/file v1.3.1/go.mod h1:pYHBlB/XwsrnWpEh7GIFpbiqobrExfiB+rEN8V2d2kY=
|
||||
apigo.cc/go/rand v1.3.0 h1:k+UFAhMySwXf+dq8Om9TniZV6fm6gAE0evbrqMEdwQU=
|
||||
apigo.cc/go/rand v1.3.0/go.mod h1:mZ/4Soa3bk+XvDaqPWJuUe1bfEi4eThBj1XmEAuYxsk=
|
||||
apigo.cc/go/safe v1.3.0 h1:uctdAUsphT9p60Tk4oS5xPCe0NoIdOHfsYv4PNS0Rok=
|
||||
apigo.cc/go/safe v1.3.0/go.mod h1:tC9X14V+qh0BqIrVg4UkXbl+2pEN+lj2ZNI8IjDB6Fs=
|
||||
github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo=
|
||||
github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
|
||||
@ -24,20 +24,6 @@ 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()))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user