Resizing hash in Python ImageHash library

I am using the ImageHash library to generate a perceptual hash of an image. The library claims to be able to generate hashes of different sizes (64, 128, 256), but I can't figure out how to get the 128 hash.

The size of the hash is determined by the size of the image when the library rewrites it, for example:

def average_hash(image, hash_size=8):
    image = image.convert("L").resize((hash_size, hash_size), Image.ANTIALIAS)

      

here the default is 8 (8x8 images = 64 pixels -> grayscale -> 64 bits).

However, how is the 128 bit hash generated?

Second, the default size for pHash is 32 as described here , but later only the top-level DCT, the left section is 8x8, so that's 64 bits again. DCT is calculated through scipy.fftpack

:

def phash(image, hash_size=32):
    image = image.convert("L").resize((hash_size, hash_size), Image.ANTIALIAS)
    pixels = numpy.array(image.getdata(), dtype=numpy.float).reshape((hash_size, hash_size))
    dct = scipy.fftpack.dct(pixels)
    dctlowfreq = dct[:8, 1:9]
    avg = dctlowfreq.mean()
    diff = dctlowfreq > avg
    return ImageHash(diff)

      

How do I resize the hash?
Whatever value is used, the calculation will always be based on the top left 8x8, so it will always be 64!

The weird thing that happens is that if I start with an 8-dimensional pHash (resizing the image from the beginning) I got a final 56-bit hash (namely, calculating the hash of the 7x8 image: t understand why this is happening in DCT , but I really don't know much about it.

+4


source to share


1 answer


It looks like it was a bug in the library that has since been fixed. The current phash implementation looks like this:

def phash(image, hash_size=8, highfreq_factor=4):
    """
    Perceptual Hash computation.
    Implementation follows http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
    @image must be a PIL instance.
    """
    if hash_size < 2:
        raise ValueError("Hash size must be greater than or equal to 2")

    import scipy.fftpack
    img_size = hash_size * highfreq_factor
    image = image.convert("L").resize((img_size, img_size), Image.ANTIALIAS)
    pixels = numpy.asarray(image)
    dct = scipy.fftpack.dct(scipy.fftpack.dct(pixels, axis=0), axis=1)
    dctlowfreq = dct[:hash_size, :hash_size]
    med = numpy.median(dctlowfreq)
    diff = dctlowfreq > med
    return ImageHash(diff)

      



You will notice that it uses correctly hash_size

and not hardcoded values.

0


source







All Articles