Files
observer/server/common/image_hash.go
T
2026-09-02 16:28:02 +08:00

48 lines
1.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package common
import (
"bytes"
"image"
"image/color"
_ "image/jpeg" // 注册解码器(dHash 全量解码用)
_ "image/png"
)
// ImageDHash64 整图 64 位 dHash9x8 灰度采样,与 ffmpeg scale=9:8 同语义)。
// 两图相似度 = 哈希异或的位 1 数(汉明距离),≤ CleanHashHamming 阈值视为近重复
// (数据清洗桶内多样性保留用,见 consts.CleanBuckets)。
func ImageDHash64(data []byte) (uint64, error) {
src, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return 0, err
}
return hashOf(src)
}
// hashOf 图像 dHash:采样 9 列 x 8 行(全域拉伸),逐行比较相邻列明暗得 64 位
func hashOf(src image.Image) (uint64, error) {
b := src.Bounds()
w, h := b.Dx(), b.Dy()
if w < 1 || h < 1 {
return 0, image.ErrFormat
}
var gray color.Gray
shade := func(x, y int) uint32 {
gray = color.GrayModel.Convert(src.At(b.Min.X+x, b.Min.Y+y)).(color.Gray)
return uint32(gray.Y)
}
var h64 uint64
for r := 0; r < 8; r++ {
y := (h - 1) * r / 7
for c := 0; c < 8; c++ {
xl := (w - 1) * c / 8
xr := (w - 1) * (c + 1) / 8
h64 <<= 1
if shade(xl, y) < shade(xr, y) {
h64 |= 1
}
}
}
return h64, nil
}