AverageHashExtend: Implement AverageHashExtend and fix bugs (#20)
This commit is contained in:
parent
c41a59a872
commit
b535580cae
@ -91,9 +91,7 @@ func PerceptionHashExtend(img image.Image, hashSize int) (*ExtImageHash, error)
|
|||||||
if img == nil {
|
if img == nil {
|
||||||
return nil, errors.New("Image object can not be nil")
|
return nil, errors.New("Image object can not be nil")
|
||||||
}
|
}
|
||||||
highFreqFactor := 8
|
imgSize := hashSize * hashSize
|
||||||
imgSize := hashSize * highFreqFactor
|
|
||||||
|
|
||||||
resized := resize.Resize(uint(imgSize), uint(imgSize), img, resize.Bilinear)
|
resized := resize.Resize(uint(imgSize), uint(imgSize), img, resize.Bilinear)
|
||||||
pixels := transforms.Rgb2Gray(resized)
|
pixels := transforms.Rgb2Gray(resized)
|
||||||
dct := transforms.DCT2D(pixels, imgSize, imgSize)
|
dct := transforms.DCT2D(pixels, imgSize, imgSize)
|
||||||
@ -101,10 +99,9 @@ func PerceptionHashExtend(img image.Image, hashSize int) (*ExtImageHash, error)
|
|||||||
median := etcs.MedianOfPixels(flattens)
|
median := etcs.MedianOfPixels(flattens)
|
||||||
|
|
||||||
lenOfUnit := 64
|
lenOfUnit := 64
|
||||||
lenOfPhash := hashSize * hashSize
|
phash := make([]uint64, imgSize/lenOfUnit)
|
||||||
phash := make([]uint64, lenOfPhash/lenOfUnit)
|
|
||||||
for idx, p := range flattens {
|
for idx, p := range flattens {
|
||||||
indexOfArray := (lenOfPhash - 1 - idx) / lenOfUnit
|
indexOfArray := (imgSize - 1 - idx) / lenOfUnit
|
||||||
indexOfBit := idx % lenOfUnit
|
indexOfBit := idx % lenOfUnit
|
||||||
if p > median {
|
if p > median {
|
||||||
phash[indexOfArray] |= 1 << uint(indexOfBit)
|
phash[indexOfArray] |= 1 << uint(indexOfBit)
|
||||||
@ -112,3 +109,29 @@ func PerceptionHashExtend(img image.Image, hashSize int) (*ExtImageHash, error)
|
|||||||
}
|
}
|
||||||
return NewExtImageHash(phash, PHash), nil
|
return NewExtImageHash(phash, PHash), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AverageHashExtend function returns ahash of which the size can be set larger than uint64
|
||||||
|
// Support 64bits ahash (hashSize=8) and 256bits ahash (hashSize=16)
|
||||||
|
func AverageHashExtend(img image.Image, hashSize int) (*ExtImageHash, error) {
|
||||||
|
if img == nil {
|
||||||
|
return nil, errors.New("Image object can not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
imgSize := hashSize * hashSize
|
||||||
|
|
||||||
|
resized := resize.Resize(uint(hashSize), uint(hashSize), img, resize.Bilinear)
|
||||||
|
pixels := transforms.Rgb2Gray(resized)
|
||||||
|
flattens := transforms.FlattenPixels(pixels, hashSize, hashSize)
|
||||||
|
avg := etcs.MeanOfPixels(flattens)
|
||||||
|
|
||||||
|
lenOfUnit := 64
|
||||||
|
ahash := make([]uint64, imgSize/lenOfUnit)
|
||||||
|
for idx, p := range flattens {
|
||||||
|
indexOfArray := (imgSize - 1 - idx) / lenOfUnit
|
||||||
|
indexOfBit := idx % lenOfUnit
|
||||||
|
if p > avg {
|
||||||
|
ahash[indexOfArray] |= 1 << uint(indexOfBit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NewExtImageHash(ahash, AHash), nil
|
||||||
|
}
|
||||||
|
@ -147,22 +147,36 @@ func TestExtImageHashCompute(t *testing.T) {
|
|||||||
img1 string
|
img1 string
|
||||||
img2 string
|
img2 string
|
||||||
hashSize int
|
hashSize int
|
||||||
|
method func(img image.Image, hashSize int) (*ExtImageHash, error)
|
||||||
name string
|
name string
|
||||||
distance int
|
distance int
|
||||||
}{
|
}{
|
||||||
{"_examples/sample1.jpg", "_examples/sample1.jpg", 8, "PerceptionHashExtend", 0},
|
{"_examples/sample1.jpg", "_examples/sample1.jpg", 8, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample2.jpg", "_examples/sample2.jpg", 8, "PerceptionHashExtend", 0},
|
{"_examples/sample2.jpg", "_examples/sample2.jpg", 8, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample3.jpg", "_examples/sample3.jpg", 8, "PerceptionHashExtend", 0},
|
{"_examples/sample3.jpg", "_examples/sample3.jpg", 8, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample4.jpg", "_examples/sample4.jpg", 8, "PerceptionHashExtend", 0},
|
{"_examples/sample4.jpg", "_examples/sample4.jpg", 8, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample1.jpg", "_examples/sample2.jpg", 8, "PerceptionHashExtend", 32},
|
{"_examples/sample1.jpg", "_examples/sample2.jpg", 8, AverageHashExtend, "AverageHashExtend", 42},
|
||||||
{"_examples/sample1.jpg", "_examples/sample3.jpg", 8, "PerceptionHashExtend", 2},
|
{"_examples/sample1.jpg", "_examples/sample3.jpg", 8, AverageHashExtend, "AverageHashExtend", 4},
|
||||||
{"_examples/sample1.jpg", "_examples/sample4.jpg", 8, "PerceptionHashExtend", 30},
|
{"_examples/sample1.jpg", "_examples/sample4.jpg", 8, AverageHashExtend, "AverageHashExtend", 38},
|
||||||
{"_examples/sample2.jpg", "_examples/sample3.jpg", 8, "PerceptionHashExtend", 34},
|
{"_examples/sample2.jpg", "_examples/sample3.jpg", 8, AverageHashExtend, "AverageHashExtend", 40},
|
||||||
{"_examples/sample2.jpg", "_examples/sample4.jpg", 8, "PerceptionHashExtend", 20},
|
{"_examples/sample2.jpg", "_examples/sample4.jpg", 8, AverageHashExtend, "AverageHashExtend", 6},
|
||||||
{"_examples/sample1.jpg", "_examples/sample1.jpg", 16, "PerceptionHashExtend", 0},
|
{"_examples/sample1.jpg", "_examples/sample1.jpg", 16, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample2.jpg", "_examples/sample2.jpg", 16, "PerceptionHashExtend", 0},
|
{"_examples/sample2.jpg", "_examples/sample2.jpg", 16, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample3.jpg", "_examples/sample3.jpg", 16, "PerceptionHashExtend", 0},
|
{"_examples/sample3.jpg", "_examples/sample3.jpg", 16, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
{"_examples/sample4.jpg", "_examples/sample4.jpg", 16, "PerceptionHashExtend", 0},
|
{"_examples/sample4.jpg", "_examples/sample4.jpg", 16, AverageHashExtend, "AverageHashExtend", 0},
|
||||||
|
{"_examples/sample1.jpg", "_examples/sample1.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample2.jpg", "_examples/sample2.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample3.jpg", "_examples/sample3.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample4.jpg", "_examples/sample4.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample1.jpg", "_examples/sample2.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 32},
|
||||||
|
{"_examples/sample1.jpg", "_examples/sample3.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 2},
|
||||||
|
{"_examples/sample1.jpg", "_examples/sample4.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 30},
|
||||||
|
{"_examples/sample2.jpg", "_examples/sample3.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 34},
|
||||||
|
{"_examples/sample2.jpg", "_examples/sample4.jpg", 8, PerceptionHashExtend, "PerceptionHashExtend", 20},
|
||||||
|
{"_examples/sample1.jpg", "_examples/sample1.jpg", 16, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample2.jpg", "_examples/sample2.jpg", 16, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample3.jpg", "_examples/sample3.jpg", 16, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
|
{"_examples/sample4.jpg", "_examples/sample4.jpg", 16, PerceptionHashExtend, "PerceptionHashExtend", 0},
|
||||||
} {
|
} {
|
||||||
file1, err := os.Open(tt.img1)
|
file1, err := os.Open(tt.img1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -186,11 +200,11 @@ func TestExtImageHashCompute(t *testing.T) {
|
|||||||
t.Errorf("%s", err)
|
t.Errorf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hash1, err := PerceptionHashExtend(img1, tt.hashSize)
|
hash1, err := tt.method(img1, tt.hashSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s", err)
|
t.Errorf("%s", err)
|
||||||
}
|
}
|
||||||
hash2, err := PerceptionHashExtend(img2, tt.hashSize)
|
hash2, err := tt.method(img2, tt.hashSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s", err)
|
t.Errorf("%s", err)
|
||||||
}
|
}
|
||||||
@ -212,18 +226,6 @@ func TestExtImageHashCompute(t *testing.T) {
|
|||||||
if dis1 != tt.distance {
|
if dis1 != tt.distance {
|
||||||
t.Errorf("%s: Distance between %v and %v is expected %v but got %v", tt.name, tt.img1, tt.img2, tt.distance, dis1)
|
t.Errorf("%s: Distance between %v and %v is expected %v but got %v", tt.name, tt.img1, tt.img2, tt.distance, dis1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tt.hashSize == 8 {
|
|
||||||
hash0, err := PerceptionHash(img1)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s", err)
|
|
||||||
}
|
|
||||||
hex0 := hash0.ToString()
|
|
||||||
hex1 := hash1.ToString()
|
|
||||||
if hex0 != hex1 {
|
|
||||||
t.Errorf("Hex is expected %v but got %v", hex0, hex1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user