Add debug output for go and python
This commit is contained in:
parent
ce71c2f66b
commit
5de0e78ee6
56
cmd/hash.py
Normal file
56
cmd/hash.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from typing import Collection, Sequence
|
||||||
|
from PIL import Image
|
||||||
|
import argparse,pathlib,numpy,imagehash
|
||||||
|
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
ap.add_argument("--file", type=pathlib.Path)
|
||||||
|
|
||||||
|
opts = ap.parse_args()
|
||||||
|
opts.file = pathlib.Path(opts.file)
|
||||||
|
|
||||||
|
hash_size = 8
|
||||||
|
|
||||||
|
image = Image.open(opts.file)
|
||||||
|
gray = image.copy().convert('L')
|
||||||
|
resized = gray.copy().resize((hash_size, hash_size), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
|
|
||||||
|
def print_image(image: Image.Image) -> None:
|
||||||
|
for row in numpy.asarray(image):
|
||||||
|
print('[ ', end='')
|
||||||
|
for i in row:
|
||||||
|
if isinstance(i, Collection):
|
||||||
|
print('{ ', end='')
|
||||||
|
for idx, x in enumerate(i):
|
||||||
|
if idx == len(i)-1:
|
||||||
|
print(f'{int(x):03d} ', end='')
|
||||||
|
else:
|
||||||
|
print(f'{int(x):03d}, ', end='')
|
||||||
|
print('}, ', end='')
|
||||||
|
else:
|
||||||
|
print(f'{int(i):03d}, ', end='')
|
||||||
|
print(']')
|
||||||
|
|
||||||
|
def bin_str(hash):
|
||||||
|
return ''.join(str(b) for b in 1 * hash.hash.flatten())
|
||||||
|
|
||||||
|
|
||||||
|
print("rgb")
|
||||||
|
print_image(image)
|
||||||
|
print()
|
||||||
|
image.save("py.rgb.png")
|
||||||
|
|
||||||
|
print("gray")
|
||||||
|
print_image(gray)
|
||||||
|
gray.save("py.gray.png")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("resized")
|
||||||
|
print_image(resized)
|
||||||
|
resized.save("py.resized.png")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print('ahash: ', bin_str(imagehash.average_hash(image)))
|
||||||
|
print('dhash: ', bin_str(imagehash.dhash(image)))
|
||||||
|
print('phash: ', bin_str(imagehash.phash(image)))
|
@ -7,21 +7,58 @@ import (
|
|||||||
"image/draw"
|
"image/draw"
|
||||||
_ "image/gif"
|
_ "image/gif"
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
|
|
||||||
|
// "github.com/pixiv/go-libjpeg/jpeg"
|
||||||
"image/png"
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
_ "github.com/spakin/netpbm"
|
|
||||||
|
|
||||||
"gitea.narnian.us/lordwelch/goimagehash"
|
"gitea.narnian.us/lordwelch/goimagehash"
|
||||||
|
"gitea.narnian.us/lordwelch/goimagehash/transforms"
|
||||||
"github.com/anthonynsimon/bild/transform"
|
"github.com/anthonynsimon/bild/transform"
|
||||||
_ "github.com/gen2brain/avif"
|
_ "github.com/gen2brain/avif"
|
||||||
|
_ "github.com/spakin/netpbm"
|
||||||
_ "golang.org/x/image/bmp"
|
_ "golang.org/x/image/bmp"
|
||||||
_ "golang.org/x/image/tiff"
|
_ "golang.org/x/image/tiff"
|
||||||
_ "golang.org/x/image/webp"
|
_ "golang.org/x/image/webp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// image.RegisterFormat("jpeg", "\xff\xd8", func(r io.Reader) (image.Image, error){return jpeg.Decode(r, &jpeg.DecoderOptions{
|
||||||
|
// DisableFancyUpsampling: false,
|
||||||
|
// DisableBlockSmoothing: false,
|
||||||
|
// DCTMethod: jpeg.DCTFloat,
|
||||||
|
// })}, jpeg.DecodeConfig)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToGray(img image.Image) *image.Gray {
|
||||||
|
gray := image.NewGray(image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy()))
|
||||||
|
gray.Pix = transforms.Rgb2Gray(img)
|
||||||
|
return gray
|
||||||
|
}
|
||||||
|
|
||||||
|
func resize(img image.Image, w, h int) *image.Gray {
|
||||||
|
resized := transform.Resize(img, w, h, transform.Lanczos)
|
||||||
|
r_gray := image.NewGray(image.Rect(0, 0, resized.Bounds().Dx(), resized.Bounds().Dy()))
|
||||||
|
draw.Draw(r_gray, resized.Bounds(), resized, resized.Bounds().Min, draw.Src)
|
||||||
|
return r_gray
|
||||||
|
}
|
||||||
|
|
||||||
|
func save_image(im image.Image, name string) {
|
||||||
|
file, err := os.Create(name)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to open file %s: %s", "tmp.png", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = png.Encode(file, im)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func fmtImage(im image.Image) string {
|
func fmtImage(im image.Image) string {
|
||||||
gray, ok := im.(*image.Gray)
|
gray, ok := im.(*image.Gray)
|
||||||
str := &strings.Builder{}
|
str := &strings.Builder{}
|
||||||
@ -34,10 +71,7 @@ func fmtImage(im image.Image) string {
|
|||||||
} else {
|
} else {
|
||||||
col := im.At(x, y)
|
col := im.At(x, y)
|
||||||
r, g, b, _ := col.RGBA()
|
r, g, b, _ := col.RGBA()
|
||||||
if uint8(r) == 0x0015 && uint8(g) == 0x0013 && uint8(b) == 0x0012 {
|
fmt.Fprintf(str, "{ %03d, %03d, %03d }, ", uint8(r>>8), uint8(g>>8), uint8(b>>8))
|
||||||
fmt.Fprintf(os.Stderr, "RGB: { %04x, %04x, %04x }\n", uint8(r), uint8(g), uint8(b))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(str, "{ %04x, %04x, %04x }, ", uint8(r), uint8(g), uint8(b))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str.WriteString("]\n")
|
str.WriteString("]\n")
|
||||||
@ -46,19 +80,18 @@ func fmtImage(im image.Image) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func debugImage(im image.Image, width, height int) {
|
func debugImage(im image.Image, width, height int) {
|
||||||
// gray := image.NewGray(image.Rect(0, 0, im.Bounds().Dx(), im.Bounds().Dy()))
|
gray := ToGray(im)
|
||||||
// gray.Pix = transforms.Rgb2Gray(im)
|
resized := resize(gray, width, height)
|
||||||
// i_resize := imaging.Resize(im, width, height, imaging.Linear)
|
|
||||||
resized := transform.Resize(im, 8, 8, transform.Lanczos)
|
|
||||||
r_gray := image.NewGray(image.Rect(0, 0, resized.Bounds().Dx(), resized.Bounds().Dy()))
|
|
||||||
draw.Draw(r_gray, resized.Bounds(), resized, resized.Bounds().Min, draw.Src)
|
|
||||||
|
|
||||||
// fmt.Fprintln(os.Stderr, "rgb")
|
fmt.Println("rgb")
|
||||||
// fmt.Println(fmtImage(im))
|
fmt.Println(fmtImage(im))
|
||||||
// fmt.Fprintln(os.Stderr, "grayscale")
|
save_image(im, "go.rgb.png")
|
||||||
// fmt.Println(fmtImage(gray))
|
fmt.Println("gray")
|
||||||
// fmt.Println("resized")
|
fmt.Println(fmtImage(gray))
|
||||||
fmt.Println(fmtImage(r_gray))
|
save_image(gray, "go.gray.png")
|
||||||
|
fmt.Println("resized")
|
||||||
|
fmt.Println(fmtImage(resized))
|
||||||
|
save_image(resized, "go.resized.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -86,6 +119,8 @@ func main() {
|
|||||||
im = goimagehash.FancyUpscale(im.(*image.YCbCr))
|
im = goimagehash.FancyUpscale(im.(*image.YCbCr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugImage(im, 8, 8)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ahash *goimagehash.ImageHash
|
ahash *goimagehash.ImageHash
|
||||||
dhash *goimagehash.ImageHash
|
dhash *goimagehash.ImageHash
|
||||||
@ -98,32 +133,22 @@ func main() {
|
|||||||
log.Println(msg)
|
log.Println(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dhash, err = goimagehash.DifferenceHash(im)
|
dhash, err = goimagehash.DifferenceHash(im)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Failed to dhash Image: %s", err)
|
msg := fmt.Sprintf("Failed to ahash Image: %s", err)
|
||||||
log.Println(msg)
|
log.Println(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
phash, err = goimagehash.PerceptionHash(im)
|
phash, err = goimagehash.PerceptionHash(im)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Failed to phash Image: %s", err)
|
msg := fmt.Sprintf("Failed to ahash Image: %s", err)
|
||||||
log.Println(msg)
|
log.Println(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gray := goimagehash.ToGray(im)
|
|
||||||
file2, err := os.Create("tmp.png")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to open file %s: %s", "tmp.png", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = png.Encode(file2, gray)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
file2.Close()
|
|
||||||
debugImage(gray, 9, 8)
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "ahash: %s\n", ahash.String())
|
fmt.Println("ahash: ", ahash.BinString())
|
||||||
fmt.Fprintf(os.Stderr, "dhash: %s\n", dhash.String())
|
fmt.Println("dhash: ", dhash.BinString())
|
||||||
fmt.Fprintf(os.Stderr, "phash: %s\n", phash.String())
|
fmt.Println("phash: ", phash.BinString())
|
||||||
}
|
}
|
||||||
|
8
go.mod
8
go.mod
@ -1,8 +1,8 @@
|
|||||||
module gitea.narnian.us/lordwelch/image-hasher
|
module gitea.narnian.us/lordwelch/image-hasher
|
||||||
|
|
||||||
go 1.21
|
go 1.22.1
|
||||||
|
|
||||||
toolchain go1.22.0
|
toolchain go1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.narnian.us/lordwelch/goimagehash v0.0.0-20240502010648-cb5a8237c420
|
gitea.narnian.us/lordwelch/goimagehash v0.0.0-20240502010648-cb5a8237c420
|
||||||
@ -30,8 +30,8 @@ require (
|
|||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
golang.org/x/crypto v0.21.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/net v0.22.0 // indirect
|
golang.org/x/net v0.22.0 // indirect
|
||||||
golang.org/x/oauth2 v0.6.0 // indirect
|
golang.org/x/oauth2 v0.7.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -91,8 +91,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
|
||||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
Loading…
Reference in New Issue
Block a user