Initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.jpg
|
||||
*.jpeg
|
10
go.mod
Normal file
10
go.mod
Normal file
@@ -0,0 +1,10 @@
|
||||
module imhash
|
||||
|
||||
go 1.24.3
|
||||
|
||||
require (
|
||||
git.site.quack-lab.dev/dave/cylogger v1.2.2
|
||||
github.com/corona10/goimagehash v1.1.0
|
||||
)
|
||||
|
||||
require github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
6
go.sum
Normal file
6
go.sum
Normal file
@@ -0,0 +1,6 @@
|
||||
git.site.quack-lab.dev/dave/cylogger v1.2.2 h1:4xUXASEBlG9NiGxh7f57xHh9imW4unHzakIEpQoKC5E=
|
||||
git.site.quack-lab.dev/dave/cylogger v1.2.2/go.mod h1:VS9MI4Y/cwjCBZgel7dSfCQlwtAgHmfvixOoBgBhtKg=
|
||||
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
|
||||
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
78
main.go
Normal file
78
main.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"image/jpeg"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||
"github.com/corona10/goimagehash"
|
||||
)
|
||||
|
||||
func main() {
|
||||
thresh := flag.Int("thresh", 10, "Threshold for distance")
|
||||
flag.Parse()
|
||||
logger.InitFlag()
|
||||
hashes := &sync.Map{}
|
||||
logger.Info("Starting")
|
||||
logger.Info("Threshold: %v", *thresh)
|
||||
logger.Info("Files: %d", len(flag.Args()))
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
for _, file := range flag.Args() {
|
||||
wg.Add(1)
|
||||
go func(file string) {
|
||||
defer wg.Done()
|
||||
log := logger.Default.WithPrefix(file)
|
||||
imgfile, err := os.Open(file)
|
||||
if err != nil {
|
||||
log.Error("Failed to open file: %v", err)
|
||||
return
|
||||
}
|
||||
defer imgfile.Close()
|
||||
img, err := jpeg.Decode(imgfile)
|
||||
if err != nil {
|
||||
log.Error("Failed to decode image: %v", err)
|
||||
return
|
||||
}
|
||||
hash, err := goimagehash.ExtPerceptionHash(img, 8, 8)
|
||||
if err != nil {
|
||||
log.Error("Failed to calculate hash: %v", err)
|
||||
return
|
||||
}
|
||||
log.Debug("Hashed: %v", hash)
|
||||
hashes.Store(file, hash)
|
||||
}(file)
|
||||
}
|
||||
|
||||
groupedImages := make(map[string][]string)
|
||||
wg.Wait()
|
||||
hashes.Range(func(key, value interface{}) bool {
|
||||
filea := key.(string)
|
||||
hasha := value.(*goimagehash.ExtImageHash)
|
||||
hashes.Range(func(key, value interface{}) bool {
|
||||
fileb := key.(string)
|
||||
hashb := value.(*goimagehash.ExtImageHash)
|
||||
if filea == fileb {
|
||||
return true
|
||||
}
|
||||
distance, err := hasha.Distance(hashb)
|
||||
if err != nil {
|
||||
logger.Error("Failed to calculate distance: %v", err)
|
||||
return true
|
||||
}
|
||||
logger.Debug("Distance between %v and %v: %v", filea, fileb, distance)
|
||||
if distance <= *thresh {
|
||||
groupedImages[filea] = append(groupedImages[filea], fileb)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return true
|
||||
})
|
||||
|
||||
for file, files := range groupedImages {
|
||||
logger.Info("Grouped %v with %v", file, files)
|
||||
}
|
||||
logger.Info("Done")
|
||||
}
|
Reference in New Issue
Block a user