Add debug output for go and python

This commit is contained in:
Timmy Welch 2024-05-10 13:58:04 -07:00
parent ce71c2f66b
commit 5de0e78ee6
4 changed files with 122 additions and 41 deletions

56
cmd/hash.py Normal file
View 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)))

View File

@ -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
View File

@ -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
View File

@ -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=