imghash

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2021 License: MIT Imports: 4 Imported by: 1

README

imghash

Build Status Coverage Status GoDoc Go Report Card License MIT

Go implementation of multiple perceptual hash algorithms for images. Perceptual hash functions are analogous if features are similar, whereas cryptographic hashing relies on the avalanche effect of a small change in input value creating a drastic change in output value.

Installing

Using imghash is easy. First, use go get to install the latest version of the library. This command will install the library and its dependencies:

go get -u github.com/ajdnik/imghash

Next, include imghash in your application:

import "github.com/ajdnik/imghash"

Example

In the example below, we read an image from the filesystem and decode it. Afterwards we use the pHash to compute its perceptual hash. Next we load another image and compute its pHash, and lastly, we compare both hashes to get a difference score.

package main

import (
  "fmt"
  "image"
  _ "image/png"
  "os"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/similarity"
)

func main() {
  // Open the first image
  fimg1, err := os.Open("image1.png")
  if err != nil {
    panic(err)
  }
  defer fimg1.Close()

  // Decode the image
  img1, _, err := image.Decode(fimg1)
  if err != nil {
    panic(err)
  }

  // Create pHash object
  phash := imghash.NewPHash()
  
  // Compute the hash of the image
  h1 := phash.Calculate(img1)
  fmt.Printf("First hash: %v\n", h1)

  // Open the second image
  fimg2, err := os.Open("image2.png")
  if err != nil {
    panic(err)
  }
  defer fimg2.Close()

  // Decode the second image
  img2, _, err := image.Decode(fimg2)
  if err != nil {
    panic(err)
  }

  // Compute the hash of the second image
  h2 := phash.Calculate(img2)
  fmt.Printf("Second hash: %v\n", h2)

  // Compute hash similarity score
  d := similarity.Hamming(h1, h2)
  fmt.Printf("Hash similarity: %v\n", d)
}

Perceptual Hash Algorithms

The library supports 8 different perceptual hashing algorithms which were ported from OpenCV Contrib and consequentally tested against its OpenCV implementations.

Average Hash

One of the more basic perceptual hashing algorithms it produces a 64 bit binary hash which can be compared using the Hamming distance. The algorithm crushes the image into a grayscale 8x8 image and sets the 64 bits in the hash based on whether the pixel's value is greater than the average color for the image. You can read more about the implementation in the Looks Like It article.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 8
  resizeHeight := 8
  resizeType := imgproc.Bilinear

  ahash := imghash.NewAverageWithParams(resizeWidth, resizeHeight, resizeType)
  res := ahash.Calculate(img)
  fmt.Printf("Average Hash: %v\n", res)
}

If you want to create an Average hash with default parameters you can call the NewAverage instead of NewAverageWithParams.

Difference Hash

Difference hash is very similar in implementation then the average hash approach. Instead of computing averages it computes gradients instead. You can find a better explanation in the Kind Of Like That article.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 8
  resizeHeight := 8
  resizeType := imgproc.Bilinear

  dhash := imghash.NewDifferenceWithParams(resizeWidth, resizeHeight, resizeType)
  res := dhash.Calculate(img)
  fmt.Printf("Difference Hash: %v\n", res)
}

If you want to create a Difference hash with default parameters you can call the NewDifference instead of NewDifferenceWithParams.

Median Hash

The hash is almost identical to the average hash. Instead of using the average metric it uses the median metric when computing the hash bits.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 8
  resizeHeight := 8
  resizeType := imgproc.Bilinear

  mhash := imghash.NewMedianWithParams(resizeWidth, resizeHeight, resizeType)
  res := mhash.Calculate(img)
  fmt.Printf("Median Hash: %v\n", res)
}

If you want to create a Median hash with default parameters you can call the NewMedian instead of NewMedianWithParams.

Color Moments Hash

The algorithm is an implementation of the Perceptual hashing for color images using invariant moments article, which describes using color moments from YCbCr and HSV colorspaces to build a vector based perceptual hash. The vector consists of 42 floating point values.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 512
  resizeHeight := 512
  resizeType := imgproc.Bicubic
  gaussianKernelSize := 3
  gaussianKernelSigma := 0

  cmhash := imghash.NewColorMomentWithParams(resizeWidth, resizeHeight, resizeType, gaussianKernelSize, gaussianKernelSigma)
  res := cmhash.Calculate(img)
  fmt.Printf("Color Moment Hash: %v\n", res)
}

If you want to create a Color Moments hash with default parameters you can call the NewColorMoment instead of NewColorMomentWithParams.

Marr-Hildreth Hash

The algorithm is an implementation of the Marr-Hildreth Operator Based Hash from Rihamark: Perceptual image hash benchmarking. It uses a 2D wavelet transform to compute a 568 bit binary hash.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 512
  resizeHeight := 512
  resizeType := imgproc.Bicubic
  gaussianKernelSize := 7
  gaussianKernelSigma := 0
  marrHildrethScale := 1
  marrHildrethAlpha := 2

  mhhash := imghash.NewMarrHildrethWithParams(marrHildrethScale, marrHildrethAlpha, resizeWidth, resizeHeight, resizeType, gaussianKernelSize, gaussianKernelSigma)
  res := cmhash.Calculate(img)
  fmt.Printf("Marr Hildreth Hash: %v\n", res)
}

If you want to create a Marr-Hildreth hash with default parameters you can call the NewMarrHildreth instead of NewMarrHildrethWithParams.

Block Mean Value Hash

The algorithm is based on the implementation described in Block Mean Value Based Image Perceptual Hashing. It uses a similar approach as the Average Hash but instead of resizing the image it computes means using a sliding window and builds the hash based on those means an a global mean value. The result is a 256 bit binary hash.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 256
  resizeHeight := 256
  resizeType := imgproc.BilinearExact
  blockWidth := 16
  blockHeight := 16
  method := imghash.Direct

  bmhash := imghash.NewBlockMeanWithParams(resizeWidth, resizeHeight, resizeType, blockWidth, blockHeight, method)
  res := bmhash.Calculate(img)
  fmt.Printf("Block Mean Hash: %v\n", res)
}

If you want to create a Block Mean hash with default parameters you can call the NewBlockMean instead of NewBlockMeanWithParams.

pHash

The pHash algorithm is implemented from the Rihamark: Perceptual image hash benchmarking. It uses a discrete cosine transform to extract the relevant channels from the image and computes the hash based on the 8x8 DCT result. The hash is a vector of floating point values.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  resizeWidth := 32
  resizeHeight := 32
  resizeType := imgproc.BilinearExact

  phash := imghash.NewPHashWithParams(resizeWidth, resizeHeight, resizeType)
  res := phash.Calculate(img)
  fmt.Printf("pHash: %v\n", res)
}

If you want to create a pHash with default parameters you can call the NewPHash instead of NewPHashWithParams.

Radial Variance Hash

The algorithm is implemented from the article Robust image hashing based on radial variance of pixels. The algorithm uses a combination of radial projections and feature vector computations to generate a vector based hash containing floating point values.

package main

import (
  "fmt"

  "github.com/ajdnik/imghash"
  "github.com/ajdnik/imghash/imgproc"
)

func main() {
  img := ReadAndDecodeImage()

  // Default hash parameters
  gaussianKernelSigma := 1
  numberOfAngles := 180

  rvhash := imghash.NewRadialVarianceWithParams(gaussianKernelSigma, numberOfAngles)
  res := rvhash.Calculate(img)
  fmt.Printf("Radial Variance Hash: %v\n", res)
}

If you want to create a Radial Variance hash with default parameters you can call the NewRadialVariance instead of NewRadialVarianceWithParams.

License

Imghash is released under the MIT license. See LICENSE

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Average

type Average struct {
	// contains filtered or unexported fields
}

Average is a perceptual hash that uses the method described in Looks Like It by Dr. Neal Krawetz.

See https://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html for more information.

func NewAverage

func NewAverage() Average

NewAverage creates a new Average struct using default values.

func NewAverageWithParams

func NewAverageWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType) Average

NewAverageWithParams creates a new Average struct based on supplied parameters.

func (*Average) Calculate

func (ah *Average) Calculate(img image.Image) hashtype.Binary

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Average Hash using default parameters
avg := NewAverage()
// Calculate hash
hash := avg.Calculate(img)

fmt.Println(hash)
Output:

[255 255 15 7 1 0 0 0]

type BlockMean

type BlockMean struct {
	// contains filtered or unexported fields
}

BlockMean is a perceptual hash that uses the method described in Block Mean Value Based Image Perceptual Hashing; Yang et. al.

See https://ieeexplore.ieee.org/document/4041692 for more information.

func NewBlockMean

func NewBlockMean() BlockMean

NewBlockMean creates a new BlockMean struct using default values.

func NewBlockMeanWithParams

func NewBlockMeanWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType, blockWidth, blockHeight uint, blockMeanMethod BlockMeanMethod) BlockMean

NewBlockMeanWithParams creates a new BlockMean struct using the supplied parameters.

func (*BlockMean) Calculate

func (bh *BlockMean) Calculate(img image.Image) hashtype.Binary

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Block Mean Hash using default parameters
block := NewBlockMean()
// Calculate hash
hash := block.Calculate(img)

fmt.Println(hash)
Output:

[255 255 255 255 255 255 255 255 255 225 127 0 63 0 15 0 7 2 3 0 1 0 1 0 0 0 0 0 0 0 116 4]

type BlockMeanMethod

type BlockMeanMethod int

BlockMeanMethod represents the method used when computing the mean of blocks.

const (
	// Direct method constructs blocks with no overlap or rotation.
	Direct BlockMeanMethod = iota
	// Overlap method constructs blocks by overlapping them, the degree of overlap is set to be half of a block.
	Overlap
	// Rotation method uses the same approach as Direct but also rotates blocks.
	Rotation
	// RotationOverlap uses the same approach as Overlap but also rotates blocks.
	RotationOverlap
)

TODO: Add support for rotation based block mean hashes.

type ColorMoment

type ColorMoment struct {
	// contains filtered or unexported fields
}

ColorMoment is a perceptual hash that uses the method described in Perceptual Hashing for Color Images Using Invariant Moments; Tang et. al.

See https://www.researchgate.net/publication/286870507_Perceptual_hashing_for_color_images_using_invariant_moments for more information.

func NewColorMoment

func NewColorMoment() ColorMoment

NewColorMoment creates a new ColorMoment struct using default values.

func NewColorMomentWithParams

func NewColorMomentWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType, kernelSize int, sigma float64) ColorMoment

NewColorMomentWithParams creates a new ColorMoment struct based on supplied parameters.

func (*ColorMoment) Calculate

func (ch *ColorMoment) Calculate(img image.Image) hashtype.Float64

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Color Moment Hash using default parameters
color := NewColorMoment()
// Calculate hash
hash := color.Calculate(img)

fmt.Println(hash)
Output:

[0.007840559221738475 2.2034498359157744e-07 8.684939637320095e-09 1.3195340752596305e-08 1.361994698531565e-16 -3.128016142811829e-12 3.7465225373114406e-17 0.0016131824928845837 4.150246244542602e-08 7.635890095045098e-11 2.1849001025983358e-11 4.1135742177399834e-22 -4.4427924315240715e-15 7.91976998613191e-22 0.001045548809225742 2.772613007864512e-09 1.337261180170139e-11 1.6167463698622338e-11 7.006891104009164e-24 2.9211456863128017e-16 2.376195809939422e-22 0.0011816509074528167 2.9408079432297224e-09 3.061401364698586e-11 3.893655593746319e-11 2.84267196907831e-22 9.85794678916472e-16 1.3139013030470254e-21 0.0011755591858654255 1.4306034607639147e-10 5.391803318981961e-13 3.8112496595287077e-13 1.6424203326396093e-25 -2.0998441435316273e-18 5.360968121680658e-26 0.0015080347084822899 1.7821772814069935e-10 1.1621533470920317e-13 5.113034793145402e-13 -1.1298961074948206e-25 -2.3943853547045442e-18 5.261115642777516e-26]

type Difference

type Difference struct {
	// contains filtered or unexported fields
}

Difference is a perceptual hash that uses the method described in Kinf of Like That by Dr. Neal Krawetz.

See https://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html for more information.

func NewDifference

func NewDifference() Difference

NewDifference creates a new Difference struct using default values.

func NewDifferenceWithParams

func NewDifferenceWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType) Difference

NewDifferenceWithParams creates a new Difference struct based on supplied parameters.

func (*Difference) Calculate

func (dh *Difference) Calculate(img image.Image) hashtype.Binary

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Difference Hash using default parameters
diff := NewDifference()
// Calculate hash
hash := diff.Calculate(img)

fmt.Println(hash)
Output:

[6 2 194 64 124 60 16 16]

type MarrHildreth

type MarrHildreth struct {
	// contains filtered or unexported fields
}

MarrHildreth is a perceptual hash that uses the method described in Implementation and Benchmarking of Perceptual Image Hash Functions; Zauner et. al.

See https://www.researchgate.net/publication/252340846_Rihamark_Perceptual_image_hash_benchmarking for more information.

Example (Calculate)
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Marr-Hildreth Hash using default parameters
marr := NewMarrHildreth()
// Calculate hash
hash := marr.Calculate(img)

fmt.Println(hash)
Output:

[51 1 228 237 182 92 200 237 102 109 182 60 12 178 88 222 73 182 108 124 27 36 183 79 226 73 182 76 134 68 237 229 163 242 73 182 36 159 11 115 118 76 152 151 180 100 248 11 97 121 38 145 169 45 45 146 91 31 13 33 60 95 38 47 131 201 32 253 160 108 188 27]

func NewMarrHildreth

func NewMarrHildreth() MarrHildreth

NewMarrHildreth creates a new MarrHildreth struct using default values.

func NewMarrHildrethWithParams

func NewMarrHildrethWithParams(scale, alpha float64, resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType, kernelSize int, sigma float64) MarrHildreth

NewMarrHildrethWithParams creates a new MarrHildreth struct using the supplied parameters.

func (*MarrHildreth) Calculate

func (mhh *MarrHildreth) Calculate(img image.Image) hashtype.Binary

Calculate returns a perceptual image hash.

type Median

type Median struct {
	// contains filtered or unexported fields
}

Median is a perceptual hash that uses a similar approach as Average hash. But instead of using mean it uses median to compute the average value. See https://github.com/Quickshot/DupImageLib/blob/3e914588958c4c1871d750de86b30446b9c07a3e/DupImageLib/ImageHashes.cs#L99 for more information.

func NewMedian

func NewMedian() Median

NewMedian creates a new Median struct using default values.

func NewMedianWithParams

func NewMedianWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType) Median

NewMedianWithParams creates a new Median struct using the supplied parameters.

func (*Median) Calculate

func (mh *Median) Calculate(img image.Image) hashtype.Binary

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Median Hash using default parameters
med := NewMedian()
// Calculate hash
hash := med.Calculate(img)

fmt.Println(hash)
Output:

[255 255 31 7 3 1 1 39]

type PHash

type PHash struct {
	// contains filtered or unexported fields
}

PHash is a perceptual hash that uses the method described in Implementation and Benchmarking of Perceptual Image Hash Functions; Zauner et. al.

See https://www.researchgate.net/publication/252340846_Rihamark_Perceptual_image_hash_benchmarking for more information.

func NewPHash

func NewPHash() PHash

NewPHash creates a new PHash struct using default values.

func NewPHashWithParams

func NewPHashWithParams(resizeWidth, resizeHeight uint, resizeType imgproc.ResizeType) PHash

NewPHashWithParams creates a new PHash struct using the supplied parameters.

func (*PHash) Calculate

func (ph *PHash) Calculate(img image.Image) hashtype.Binary

Calculate returns a percaptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new PHash using default parameters
ph := NewPHash()
// Calculate hash
hash := ph.Calculate(img)

fmt.Println(hash)
Output:

[170 211 65 29 10 2 38 84]

type RadialVariance

type RadialVariance struct {
	// contains filtered or unexported fields
}

RadialVariance is a perceptual hash that uses the method described in Robust image hashing based on radial variance of pixels; De Roover et. al.

See https://www.researchgate.net/publication/4186555_Robust_image_hashing_based_on_radial_variance_of_pixels for more information.

func NewRadialVariance

func NewRadialVariance() RadialVariance

NewRadialVariance creates a new RadialVariance struct using default values.

func NewRadialVarianceWithParams

func NewRadialVarianceWithParams(sigma float64, numOfAngleLines int) RadialVariance

NewRadialVarianceWithParams creates a new RadialVariance struct based on supplied parameters.

func (*RadialVariance) Calculate

func (rv *RadialVariance) Calculate(img image.Image) hashtype.UInt8

Calculate returns a perceptual image hash.

Example
// Read image from file
img, _ := imgproc.Read("assets/cat.jpg")
// Create new Radial Variance Hash using default parameters
rad := NewRadialVariance()
// Calculate hash
hash := rad.Calculate(img)

fmt.Println(hash)
Output:

[166 246 10 0 124 194 254 203 219 156 116 176 226 154 138 184 195 174 155 143 213 154 170 209 125 152 173 167 181 170 165 183 157 179 174 162 161 171 157 194]

Directories

Path Synopsis
Package hashtype implements data types used to represent hashes.
Package hashtype implements data types used to represent hashes.
Package similarity implements data types and methods used to calculate similarities between hashes.
Package similarity implements data types and methods used to calculate similarities between hashes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL