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  }