gitee.com/h79/goutils@v1.22.10/common/images/histogram.go (about) 1 package images 2 3 import ( 4 "bufio" 5 "image" 6 "io" 7 "math" 8 "os" 9 ) 10 11 // Histogram 相似图片识别(直方图) 12 type Histogram struct { 13 redBins int 14 greenBins int 15 blueBins int 16 histogram []float64 17 } 18 19 func NewHistogram() *Histogram { 20 binCount := 4 21 h := &Histogram{ 22 redBins: binCount, 23 greenBins: binCount, 24 blueBins: binCount, 25 histogram: make([]float64, binCount*binCount*binCount), 26 } 27 return h 28 } 29 30 func (hm *Histogram) OpenFile(filename string) error { 31 file, err := os.Open(filename) 32 if err != nil { 33 return err 34 } 35 return hm.Open(bufio.NewReader(file)) 36 } 37 38 func (hm *Histogram) Open(reader io.Reader) error { 39 40 img, _, err := image.Decode(reader) 41 if err != nil { 42 return err 43 } 44 return hm.OpenImage(img) 45 } 46 47 func (hm *Histogram) OpenImage(img image.Image) error { 48 49 width := img.Bounds().Dx() 50 height := img.Bounds().Dy() 51 52 img.ColorModel() 53 total := 0 54 for y := 0; y < height; y++ { 55 for x := 0; x < width; x++ { 56 r, g, b, _ := img.At(x, y).RGBA() 57 red := index(hm.redBins, r>>8, 255) 58 green := index(hm.greenBins, g>>8, 255) 59 blue := index(hm.blueBins, b>>8, 255) 60 idx := red + green*hm.redBins + blue*hm.redBins*hm.greenBins 61 hm.histogram[idx]++ 62 total += 1 63 } 64 } 65 66 // start to normalize the histogram data 67 for i := 0; i < len(hm.histogram); i++ { 68 hm.histogram[i] = hm.histogram[i] / float64(total) 69 } 70 return nil 71 } 72 73 func (hm *Histogram) Data() []float64 { 74 return hm.histogram 75 } 76 77 // Match 返回值大于等于0.8可以简单判断这两张图片内容一致 78 func (hm *Histogram) Match(dest *Histogram) float64 { 79 source := hm.Data() 80 candidate := dest.Data() 81 82 mixed := make([]float64, len(source)) 83 for i := 0; i < len(source); i++ { 84 mixed[i] = math.Sqrt(source[i] * candidate[i]) 85 } 86 similarity := 0.0 87 for i := 0; i < len(mixed); i++ { 88 similarity += mixed[i] 89 } 90 // The degree of similarity 91 return similarity 92 } 93 94 func index(binCount int, color uint32, maxColor uint32) int { 95 binIndex := int(float32(color) / float32(maxColor) * float32(binCount)) 96 if binIndex >= binCount { 97 binIndex = binCount - 1 98 } 99 return binIndex 100 }