imagehash: Create a new API Bits() (#25)
This commit is contained in:
parent
84eb1859d0
commit
47321c08d3
13
README.md
13
README.md
@ -39,6 +39,19 @@ func main() {
|
|||||||
hash2, _ = goimagehash.DifferenceHash(img2)
|
hash2, _ = goimagehash.DifferenceHash(img2)
|
||||||
distance, _ = hash1.Distance(hash2)
|
distance, _ = hash1.Distance(hash2)
|
||||||
fmt.Printf("Distance between images: %v\n", distance)
|
fmt.Printf("Distance between images: %v\n", distance)
|
||||||
|
hash3, _ = goimagehash.AverageHashExtend(img1, 16)
|
||||||
|
hash4, _ = goimagehash.AverageHashExtend(img2, 16)
|
||||||
|
distance, _ = hash3.Distance(hash4)
|
||||||
|
fmt.Printf("Distance between images: %v\n", distance)
|
||||||
|
fmt.Printf("hash3 bit size: %v\n", hash3.Bits())
|
||||||
|
fmt.Printf("hash4 bit size: %v\n", hash4.Bits())
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
foo := bufio.NewWriter(&b)
|
||||||
|
_ = hash4.Dump(foo)
|
||||||
|
foo.Flush()
|
||||||
|
bar := bufio.NewReader(&b)
|
||||||
|
hash5, _ := goimagehash.LoadImageHashExtend(bar)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -29,4 +29,6 @@ func main() {
|
|||||||
hash2, _ = goimagehash.PerceptionHash(img2)
|
hash2, _ = goimagehash.PerceptionHash(img2)
|
||||||
distance, _ = hash1.Distance(hash2)
|
distance, _ = hash1.Distance(hash2)
|
||||||
fmt.Printf("Distance between images: %v\n", distance)
|
fmt.Printf("Distance between images: %v\n", distance)
|
||||||
|
fmt.Println(hash1.Bits())
|
||||||
|
fmt.Println(hash2.Bits())
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/corona10/goimagehash"
|
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/corona10/goimagehash"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -20,9 +21,9 @@ func main() {
|
|||||||
img2, _ := jpeg.Decode(file2)
|
img2, _ := jpeg.Decode(file2)
|
||||||
hash1, _ := goimagehash.AverageHashExtend(img1, 15)
|
hash1, _ := goimagehash.AverageHashExtend(img1, 15)
|
||||||
hash2, _ := goimagehash.AverageHashExtend(img2, 15)
|
hash2, _ := goimagehash.AverageHashExtend(img2, 15)
|
||||||
|
hash1024, _ := goimagehash.AverageHashExtend(img2, 32)
|
||||||
distance, _ := hash1.Distance(hash2)
|
distance, _ := hash1.Distance(hash2)
|
||||||
fmt.Printf("Distance between images: %v\n", distance)
|
fmt.Printf("Distance between images: %v\n", distance)
|
||||||
|
|
||||||
err := hash1.Dump(foo)
|
err := hash1.Dump(foo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -33,6 +34,8 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
distance, err = hash1.Distance(hash1024)
|
||||||
|
fmt.Println(err)
|
||||||
distance, _ = hash1.Distance(hash3)
|
distance, _ = hash1.Distance(hash3)
|
||||||
fmt.Printf("Distance between hash1 and hash3: %v\n", distance)
|
fmt.Printf("Distance between hash1 and hash3: %v\n", distance)
|
||||||
distance, _ = hash2.Distance(hash3)
|
distance, _ = hash2.Distance(hash3)
|
||||||
@ -40,4 +43,7 @@ func main() {
|
|||||||
fmt.Println(hash1.ToString())
|
fmt.Println(hash1.ToString())
|
||||||
fmt.Println(hash2.ToString())
|
fmt.Println(hash2.ToString())
|
||||||
fmt.Println(hash3.ToString())
|
fmt.Println(hash3.ToString())
|
||||||
|
fmt.Println(hash1.Bits())
|
||||||
|
fmt.Println(hash2.Bits())
|
||||||
|
fmt.Println(hash3.Bits())
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ func PerceptionHashExtend(img image.Image, hashSize int) (*ExtImageHash, error)
|
|||||||
phash[indexOfArray] |= 1 << uint(indexOfBit)
|
phash[indexOfArray] |= 1 << uint(indexOfBit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewExtImageHash(phash, PHash), nil
|
return NewExtImageHash(phash, PHash, imgSize), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AverageHashExtend function returns ahash of which the size can be set larger than uint64
|
// AverageHashExtend function returns ahash of which the size can be set larger than uint64
|
||||||
@ -142,7 +142,7 @@ func AverageHashExtend(img image.Image, hashSize int) (*ExtImageHash, error) {
|
|||||||
ahash[indexOfArray] |= 1 << uint(indexOfBit)
|
ahash[indexOfArray] |= 1 << uint(indexOfBit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewExtImageHash(ahash, AHash), nil
|
return NewExtImageHash(ahash, AHash, imgSize), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DifferenceHashExtend function returns dhash of which the size can be set larger than uint64
|
// DifferenceHashExtend function returns dhash of which the size can be set larger than uint64
|
||||||
@ -175,5 +175,5 @@ func DifferenceHashExtend(img image.Image, hashSize int) (*ExtImageHash, error)
|
|||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewExtImageHash(dhash, DHash), nil
|
return NewExtImageHash(dhash, DHash, imgSize), nil
|
||||||
}
|
}
|
||||||
|
30
imagehash.go
30
imagehash.go
@ -26,6 +26,7 @@ type ImageHash struct {
|
|||||||
type ExtImageHash struct {
|
type ExtImageHash struct {
|
||||||
hash []uint64
|
hash []uint64
|
||||||
kind Kind
|
kind Kind
|
||||||
|
bits int
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -46,6 +47,11 @@ func NewImageHash(hash uint64, kind Kind) *ImageHash {
|
|||||||
return &ImageHash{hash: hash, kind: kind}
|
return &ImageHash{hash: hash, kind: kind}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bits method returns an actual hash bit size
|
||||||
|
func (h *ImageHash) Bits() int {
|
||||||
|
return 64
|
||||||
|
}
|
||||||
|
|
||||||
// Distance method returns a distance between two hashes.
|
// Distance method returns a distance between two hashes.
|
||||||
func (h *ImageHash) Distance(other *ImageHash) (int, error) {
|
func (h *ImageHash) Distance(other *ImageHash) (int, error) {
|
||||||
if h.GetKind() != other.GetKind() {
|
if h.GetKind() != other.GetKind() {
|
||||||
@ -146,8 +152,13 @@ func (h *ImageHash) ToString() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewExtImageHash function creates a new big hash
|
// NewExtImageHash function creates a new big hash
|
||||||
func NewExtImageHash(hash []uint64, kind Kind) *ExtImageHash {
|
func NewExtImageHash(hash []uint64, kind Kind, bits int) *ExtImageHash {
|
||||||
return &ExtImageHash{hash: hash, kind: kind}
|
return &ExtImageHash{hash: hash, kind: kind, bits: bits}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bits method returns an actual hash bit size
|
||||||
|
func (h *ExtImageHash) Bits() int {
|
||||||
|
return h.bits
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distance method returns a distance between two big hashes
|
// Distance method returns a distance between two big hashes
|
||||||
@ -156,13 +167,18 @@ func (h *ExtImageHash) Distance(other *ExtImageHash) (int, error) {
|
|||||||
return -1, errors.New("Extended Image hashes's kind should be identical")
|
return -1, errors.New("Extended Image hashes's kind should be identical")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.Bits() != other.Bits() {
|
||||||
|
msg := fmt.Sprintf("Extended image hash should has an identical bit size but got %v vs %v", h.Bits(), other.Bits())
|
||||||
|
return -1, errors.New(msg)
|
||||||
|
}
|
||||||
|
|
||||||
lHash := h.GetHash()
|
lHash := h.GetHash()
|
||||||
rHash := other.GetHash()
|
rHash := other.GetHash()
|
||||||
if len(lHash) != len(rHash) {
|
if len(lHash) != len(rHash) {
|
||||||
return -1, errors.New("Extended Image hashes's size should be identical")
|
return -1, errors.New("Extended Image hashes's size should be identical")
|
||||||
}
|
}
|
||||||
|
|
||||||
var distance int
|
distance := 0
|
||||||
for idx, lh := range lHash {
|
for idx, lh := range lHash {
|
||||||
rh := rHash[idx]
|
rh := rHash[idx]
|
||||||
hamming := lh ^ rh
|
hamming := lh ^ rh
|
||||||
@ -186,9 +202,10 @@ func (h *ExtImageHash) Dump(w io.Writer) error {
|
|||||||
type D struct {
|
type D struct {
|
||||||
Hash []uint64
|
Hash []uint64
|
||||||
Kind Kind
|
Kind Kind
|
||||||
|
Bits int
|
||||||
}
|
}
|
||||||
enc := gob.NewEncoder(w)
|
enc := gob.NewEncoder(w)
|
||||||
err := enc.Encode(D{Hash: h.hash, Kind: h.kind})
|
err := enc.Encode(D{Hash: h.hash, Kind: h.kind, Bits: h.bits})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -200,6 +217,7 @@ func LoadImageHashExtend(b io.Reader) (*ExtImageHash, error) {
|
|||||||
type E struct {
|
type E struct {
|
||||||
Hash []uint64
|
Hash []uint64
|
||||||
Kind Kind
|
Kind Kind
|
||||||
|
Bits int
|
||||||
}
|
}
|
||||||
var e E
|
var e E
|
||||||
dec := gob.NewDecoder(b)
|
dec := gob.NewDecoder(b)
|
||||||
@ -207,7 +225,7 @@ func LoadImageHashExtend(b io.Reader) (*ExtImageHash, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ExtImageHash{hash: e.Hash, kind: e.Kind}, nil
|
return &ExtImageHash{hash: e.Hash, kind: e.Kind, bits: e.Bits}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const extStrFmt = "%1s:%s"
|
const extStrFmt = "%1s:%s"
|
||||||
@ -248,7 +266,7 @@ func ExtImageHashFromString(s string) (*ExtImageHash, error) {
|
|||||||
case "w":
|
case "w":
|
||||||
kind = WHash
|
kind = WHash
|
||||||
}
|
}
|
||||||
return NewExtImageHash(hash, kind), nil
|
return NewExtImageHash(hash, kind, len(hash)*64), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToString returns a hex representation of big hash
|
// ToString returns a hex representation of big hash
|
||||||
|
@ -127,6 +127,31 @@ func TestSerialization(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDifferentBitSizeHash(t *testing.T) {
|
||||||
|
checkErr := func(err error) {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file, err := os.Open("_examples/sample1.jpg")
|
||||||
|
checkErr(err)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
img, _, err := image.Decode(file)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
hash1, _ := AverageHashExtend(img, 32)
|
||||||
|
hash2, _ := DifferenceHashExtend(img, 32)
|
||||||
|
_, err = hash1.Distance(hash2)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Should got error with different kinds of hashes")
|
||||||
|
}
|
||||||
|
hash3, _ := AverageHashExtend(img, 31)
|
||||||
|
_, err = hash1.Distance(hash3)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Should got error with different bits of hashes")
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestDumpAndLoad(t *testing.T) {
|
func TestDumpAndLoad(t *testing.T) {
|
||||||
checkErr := func(err error) {
|
checkErr := func(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -168,6 +193,10 @@ func TestDumpAndLoad(t *testing.T) {
|
|||||||
if distance != 0 {
|
if distance != 0 {
|
||||||
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hash.Bits() != 64 || reHash.Bits() != 64 {
|
||||||
|
t.Errorf("Hash bits should be 64 but got, %v, %v", hash.Bits(), reHash.Bits())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for ExtIExtImageHash
|
// test for ExtIExtImageHash
|
||||||
@ -195,6 +224,10 @@ func TestDumpAndLoad(t *testing.T) {
|
|||||||
if distance != 0 {
|
if distance != 0 {
|
||||||
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
t.Errorf("Original and unserialized objects should be identical, got distance=%v", distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hash.Bits() != hashSize*hashSize || reHash.Bits() != hashSize*hashSize {
|
||||||
|
t.Errorf("Hash bits should be 64 but got, %v, %v", hash.Bits(), reHash.Bits())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user