From aacead54abd180e50e571a59d478098e012be0af Mon Sep 17 00:00:00 2001 From: miracvbasaran Date: Thu, 19 Jan 2023 22:34:28 +0100 Subject: [PATCH 1/2] Add convenience wrapper for quick similarity computation --- image.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 image.go diff --git a/image.go b/image.go new file mode 100644 index 0000000..ea7401f --- /dev/null +++ b/image.go @@ -0,0 +1,72 @@ +package imagehash + +import ( + "fmt" + "image" + + "github.com/vitali-fedulov/images4" +) + +// Default hyper space parameters. +const ( + epsPct = 0.25 + numBuckets = 4 +) + +// HyperParams holds hyper space parameters for hash computations. +type HyperParams struct { + epsPct float64 + numBuckets int +} + +// Open opens and decodes an image file for a given path. It is a convenience wrapper around +// imagehash and images4 that returns the icon and hashes. +// +// Takes as input a single optional params that holds epsPct and numBuckets hyper space parameters. +func Open(path string, params ...HyperParams) (Image, error) { + if len(params) > 1 { + return Image{}, fmt.Errorf("Open() only accepts a single HyperParams as input, got %d instead", len(params)) + } + eps := epsPct + buckets := numBuckets + if len(params) == 1 { + eps = params[0].epsPct + buckets = params[0].numBuckets + } + + img, err := images4.Open(path) + if err != nil { + return Image{}, err + } + icon := images4.Icon(img) + centralHash := CentralHash(icon, HyperPoints10, eps, buckets) + hashSet := HashSet(icon, HyperPoints10, eps, buckets) + return Image{Image: img, Icon: icon, CentralHash: centralHash, HashSet: hashSet}, nil +} + +// Image is a convenience wrapper for holding everything imagehash and images4 needs. +// +// Call Similar() on an Image object for quick similarity computation instead of images4.Similar(). +type Image struct { + Image image.Image + Icon images4.IconT + CentralHash uint64 + HashSet []uint64 +} + +// Similar returns true if img2 is similar to img. It is a convenience wrapper around imagehash and +// images4 that first compares the images using CentralHash & Hashset, and then using the +// images4.Similar() function iff there is a match between the hashes. +// +// It is faster than calling images4.Similar() directly for dissimilar images and +// only slightly slower for similar images. +func (img Image) Similar(img2 Image) bool { + foundSimilarImage := false + for _, hash := range img2.HashSet { + if img.CentralHash == hash { + foundSimilarImage = true + break + } + } + return foundSimilarImage && images4.Similar(img.Icon, img2.Icon) +} From e01d51c590e7372b69b1522f13f4d95abaecb2f9 Mon Sep 17 00:00:00 2001 From: miracvbasaran Date: Tue, 24 Jan 2023 02:12:02 +0100 Subject: [PATCH 2/2] Remove image.Image field from imagehash.Image --- image.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/image.go b/image.go index ea7401f..8171d35 100644 --- a/image.go +++ b/image.go @@ -2,7 +2,6 @@ package imagehash import ( "fmt" - "image" "github.com/vitali-fedulov/images4" ) @@ -41,14 +40,13 @@ func Open(path string, params ...HyperParams) (Image, error) { icon := images4.Icon(img) centralHash := CentralHash(icon, HyperPoints10, eps, buckets) hashSet := HashSet(icon, HyperPoints10, eps, buckets) - return Image{Image: img, Icon: icon, CentralHash: centralHash, HashSet: hashSet}, nil + return Image{Icon: icon, CentralHash: centralHash, HashSet: hashSet}, nil } -// Image is a convenience wrapper for holding everything imagehash and images4 needs. +// Image is a convenience wrapper for holding objects necessary for computing image similarity. // // Call Similar() on an Image object for quick similarity computation instead of images4.Similar(). type Image struct { - Image image.Image Icon images4.IconT CentralHash uint64 HashSet []uint64