package vision import ( "bytes" "image" "image/color" "image/jpeg" "testing" ) func solid(w, h int, c color.Gray) *image.Gray { img := image.NewGray(image.Rect(0, 0, w, h)) for y := 0; y < h; y++ { for x := 0; x < w; x++ { img.SetGray(x, y, c) } } return img } func TestFingerprintIdentical(t *testing.T) { a := solid(120, 80, color.Gray{Y: 40}) b := solid(120, 80, color.Gray{Y: 40}) if d := Of(a).Distance(Of(b)); d != 0 { t.Fatalf("相同画面应无差异,实际距离 %d", d) } if Of(a).Changed(Of(b), 5, 0.01) { t.Fatal("相同画面不应判定为变化") } } func TestFingerprintDetectsChange(t *testing.T) { base := solid(120, 80, color.Gray{Y: 20}) changed := image.NewGray(image.Rect(0, 0, 120, 80)) for y := 0; y < 80; y++ { for x := 60; x < 120; x++ { changed.SetGray(x, y, color.Gray{Y: 250}) } } if !Of(changed).Changed(Of(base), 5, 0.01) { t.Fatal("右半边变白应被判定为变化") } } func TestFingerprintDetectsSubtleLocalChange(t *testing.T) { // 整块画面背景一致,只有一小块文字/内容变了:8×8 感知哈希会被平均掉, // 但高分辨率细节网格的归一化平均差能可靠捕捉到。这正是"题目变了却检测 // 不出来"这类问题的修复目标。 base := solid(256, 256, color.Gray{Y: 200}) changed := solid(256, 256, color.Gray{Y: 200}) for y := 40; y < 90; y++ { for x := 40; x < 90; x++ { changed.SetGray(x, y, color.Gray{Y: 20}) } } if !Of(changed).Changed(Of(base), 5, 0.01) { t.Fatal("局部小区域变化应被细节网格判定为变化") } } func TestEncodeJPEGResizesLongEdge(t *testing.T) { src := solid(2000, 400, color.Gray{Y: 128}) raw, err := EncodeJPEG(src, 1280, 75) if err != nil { t.Fatalf("编码失败: %v", err) } if len(raw) == 0 { t.Fatal("编码结果为空") } img, err := jpeg.Decode(bytes.NewReader(raw)) if err != nil { t.Fatalf("解码失败: %v", err) } b := img.Bounds() if b.Dx() != 1280 { t.Fatalf("长边应缩放到 1280,实际宽 %d", b.Dx()) } if b.Dy() != 256 { t.Fatalf("等比缩放后高应为 256,实际 %d", b.Dy()) } } func TestEncodeJPEGKeepsSmallImage(t *testing.T) { src := solid(64, 32, color.Gray{Y: 200}) raw, err := EncodeJPEG(src, 1280, 75) if err != nil { t.Fatalf("编码失败: %v", err) } img, err := jpeg.Decode(bytes.NewReader(raw)) if err != nil { t.Fatalf("解码失败: %v", err) } if img.Bounds().Dx() != 64 { t.Fatalf("小图不应放大,实际宽 %d", img.Bounds().Dx()) } }