This project has moved and is read-only. For the latest updates, please go here.


Aug 31, 2014 at 9:38 PM
How do I use PHASH with this library?

I've looked through the public properties and methods of MagickImage and MagickImageInfo to find the PHASH that is available in the ImageMagick library. Is there another place to look to find it?

Also, once found, how do you compare the codes to find similar images?

PS I like the library
Aug 31, 2014 at 9:44 PM
Not sure what you are trying to accomplish but are you looking for ErrorMetric.PerceptualHash? You can use this as one of the parameters of the Compare method.
Sep 3, 2014 at 2:49 AM
Edited Sep 3, 2014 at 2:50 AM
Ok, tried that - it is extremely slow and what result am I aiming for? Normally a good result is 75% or better.

It could be sped up if I could store the PHash in the database for each image. Any idea how I can get the PHash value for the image? Then to compare using that value?
Sep 4, 2014 at 9:42 PM
This is not possible at this moment. I will see if I can add this feature for you. There is already a method that calculates this available in ImageMagick, I just need to figure out how to present this in Magick.NET.
Sep 4, 2014 at 10:46 PM
Edited Sep 4, 2014 at 10:48 PM
Thank you.

I also experimenting with AverageHash, is that available too?

The version I created using this API bombs on really large images (10000 x 8000). I'm on my iPad or I'd post the code. But basically it's...
using(var image = new MagicImage(file))
   // Need the 8x8 image for 64 bits of information
   image.Resize(new MagicGeometry(8) { MaintainAspectRatio = false }); // bombs here
   image.Grayscale(forget the settings, but is is the enum.Undefined); // which would be nice as image.Grayscale() with no parameters...
   var colors = image.Pixels // forget exact property
                                .Select(p => p.GetChannel(0).Value)
    long average = colors.Average();
    var bits = colors.Select(c => c >= average); // bits as bool vaues
    // convert bits to Int64
    // I do it with a BitArray, but I saw a slicker version somewhere that does it with bitwise, but I was unsure how to convert back
    return theNewInt64;
Because of the image.Resize() failing, and having to use a separate libary image to create the AverageHash, I don't think it works correctly. That's why if ImageMagic has the AverageHash, to gain access to it would be helpful.

So, where it bombs, I use a thumbnail created with a GDI routine I made years ago. It would bomb with the image.Thumbnail(same geometry object) as well. Kept getting Memory allocation errors.

Then to compare two images, you compare their hashes, would be the same with PHash. You compare the bits and the more differences the less likely the image is similar. There are probably better ways than the below to compute the Hamming Distance.
int HammingDistance(Int64 a, Int64 b)
    var bitsA = Convert64ToBits(a); // Convert the Int64 back to an array of bools
    var bitsB = Convert64ToBits(b);
    int count = 0;
     for(int i = 0;i < 64;i++)
         if(bitsA[i] != bitsB[i]) count++;
    return count;
Sep 4, 2014 at 10:58 PM
Edited Sep 4, 2014 at 10:58 PM
The AverageHash does not seem to be available.

The Perceptual Hash function returns an object per channel (red/green/etc..) with 14 doubles that are calculated using the image moments. I will create a class with a method that will allow you to get the distance of a channel of two images. The lower this number the more equal the channel. I will also add something to easily convert this to and from a string.

Some more information about the ImageMagick internals can be found here:
Sep 5, 2014 at 9:27 PM
There is a work-around, by doing the grayscale before the resize, it doesn't bomb on the resize. It's terribly slow, but it works.
Sep 7, 2014 at 7:51 PM
The new PerceptualHash method and class has been added to the new release Magick.NET