Get perceptual hash value for image using command line

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

Correction on the metric. It is just the sum of the squares of the differences in moments. No root is taken.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Get perceptual hash value for image using command line

Post by snibgo »

I would want to do some proper testing before making significant changes to IM. I'm convinced that HCL or anything with Hue is a bad colorspace to use. I suspect that sRGB is worse than, say, Lab or YCrCb. I don't know if two colorspaces are better than one, or if three are better than two, or what those colorspaces should be.

But I think a simple and easy change can be made now. Keep the behaviour as it is now, but add a define so the colorspace for the right-hand column can be whatever the user wants, or "none" to get no second colorspace.

More ideally, the user could also set the colorspace for the left-hand column, or give a list of colorspaces to use.

I also suggest the blur in statistic.c function GetImageChannelPerceptualHash() is made optional, or even variable:

Code: Select all

-define phash:sigma=2
Setting it to 0 means no blur.

I think blurring before calculating the phash is good, but if the user wants phashes from a number of colorspaces...

Code: Select all

convert ^
  r.png ^
  -verbose ^
  -define identify:moments ^
  ( +clone -colorspace Lab -set colorspace sRGB +write info: +delete ) ^
  ( +clone -colorspace YCbCr -set colorspace sRGB +write info: ) ^
  NULL:
... then the same image is repeatedly blurred. It is quicker to do this just once:

Code: Select all

convert ^
  r.png ^
  -blur 0x1 ^
  -verbose ^
  -define identify:moments ^
  -define phash:sigma=0 ^
  ( +clone -colorspace Lab -set colorspace sRGB +write info: +delete ) ^
  ( +clone -colorspace YCbCr -set colorspace sRGB +write info: ) ^
  NULL:
Tang et al normalize the image before calculating phash. They change size to 512x512 (with padding if they weren't square?) with bicubic (they don't say why that method) and "a 3x3 Gaussian low-pass filter with a unit standard deviation" (I suppose in IM that would be "-gaussian-blur 3x1", although the code uses "-blur 0x1".).

If 512x512 optimal? Perhaps this was chosen because web images are around that size. But photographic or video libraries might work better with larger sizes. Likewise the blur: there is nothing magical about that particular blur.

In general, I suggest no image normalization before calculating phash. No resizeing, no blur. This is because the nature of the required normalization will depend on the application. IM shouldn't make assumptions about what normalization is needed. Resizing and blur are easily set in the command line.

If IM does normalize, this should have an option to turn it off, so users can override with their own settings.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

There is no resizing going on and no normalization other than the blur. The blur is there supposedly to help with noise "attacks".

I think they used 512x512 simply for common sizes that are typical of nominal size used on the internet. I did not see any reason for that since image moments are scale invariant and very good at it.

I am not sure what they meant by "normalization", however, I assumed it was simply in size and to convert to HSI and YCbCr.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Get perceptual hash value for image using command line

Post by snibgo »

I've now done a bit of work on this using the source images from Fred's paper and a similar set of attack methods, but with hue adjustment.

My tentative conclusion is that when a single colorspace is used, so just 21 PH values, from best to worst: LUV, YCbCr, Lab, YIQ, sRGB, LCH, LCHuv, HCL, HCLp, xyY, RGB. There isn't much difference between the first four colorspaces, but the others are clearly worse. (I haven't tried other colorspaces.)

Are two colorspaces better than one? Generally, using two colorspaces gives results that are between the results of each individual colorspace in isolation. However, the combination of LUV and YIQ gives a slightly better result than either LUV or YIQ alone.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

How far did you adjust hue values? If you ignore hue changes (attacks), did one of the other colorspace do better than LUV? What pairs of colorspaces did you test? Do you have any graphs or tables of your tests and results? Did you exclude hue from any of the colorspace that contain Hue?

OHTA might be one other colorspace, but my recollection was that it did not perform well. But I only testing in combination with sRGB.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

Might you get better result by combing something like CLp ( or Saturation, Lightness/Brightness) with LUV or LAB or YCbCr) than only one colorspace? So you have 5 channels or 35 PH values.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

If you need my source images or a list of commands for the attacks, let me know. I can send them to you.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Get perceptual hash value for image using command line

Post by snibgo »

Your paper includes a link to the attacks you used, Fred: http://www.fmwconcepts.com/misc_tests/p ... ations.txt . I used that list up to and including "# mirror".

I shifted hue with -modulate 100,100,%%V where %%V was 80, 85, 90, ... 120. So quite small shifts.

I haven't tried it ignoring the hue-shift test. I tested all combinations of the 4 best colorspaces: LUV+YCbCr, LUV+Lab, LUV+YIQ, YCbCr+Lab, YCbCr+YIQ, Lab+YIQ. I may automate this so I can try all the possibilities. No, I haven't yet tried simply excluding the hue channel. Not have I yet tried adding weight to lightness channel.

Ah, yes, I'll certainly add OHTA. Thanks.

I'll do a write-up. It's just notes, currently.

I've tried both formulas for difference: simple subtraction, or subtract and divide by the average. The second method seems far better.

(All my results are tentative, so far.)
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

snibgo wrote:I've tried both formulas for difference: simple subtraction, or subtract and divide by the average. The second method seems far better.
That is good to know. I had been worried about the ranges of the hash values and had thought that some normalization might help. But never thought about your simple method of dividing by the average (or sum).

I look forward to your final results. Then I can go to Magick about making some changes and/or adding -defines.

Thanks for your time and efforts in making improvements.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Get perceptual hash value for image using command line

Post by snibgo »

I've expanded the list of colorspaces (OHTA looks very useful), and added HCL etc without the H channel. By themselves, *CL etc give bad results on this test set, but may be useful in combination with other colorspaces.

I've automated the two-colorspace tests, so I'll get results for every possible pair of colorspaces. I'll do some 3-colorspace calcs, but probably not every possible combination.

I haven't yet added your attacks by distortion. I'm still getting the methodology right, so using a fairly small dataset, 650 images.

When I think I've got what I can from standard images and attacks, then the real work starts, using real images.

It doesn't matter if we divide by the average or the sum. I do divide the sum of the squares by the number of values so I get comparable scores whether I have 14, 21, 35, 42 or more PHs, and I take the square root.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

Why the square root? It just take more time and I do not see that it buys anything special.

When you normalize, what range of values do you get for any hash value? Does it keep them in the range 0 to 1?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

OHTA is like a cheap computation of Principle Components (orthogonal channels). The first channel is just the simple average of the RGB channels.
blair
Posts: 7
Joined: 2016-08-07T17:46:35-07:00
Authentication code: 1151

Re: Get perceptual hash value for image using command line

Post by blair »

Hey fmw42 & snibgo, I just wanted to say I started messing about with the tips you gave me and it seems to be working quite well. Same-images return a difference of 0.

I took one high-quality JPEG (@ 2448x3264 pixels) and compressed it slightly and reduced its size to 979x1305 pixels. My compare_hash function returns a difference of 0.013451284537704401 ... or roughly 1.35%, as I understand it, which is I think pretty darn good.

Thanks again.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Get perceptual hash value for image using command line

Post by snibgo »

The phash values for images, generated by IM, seem to have a maximum value of 11. So the RMS of differences has a theoretical maximum of 11, but in practice is below 8. (If you don't take the square root, the theoretical max is 121 but in practice is below 64.)

I'm working on this today. Each test run involves 3 billion comparisons, so it takes time. I hope to publish results and conclusions early next week.

EDIT: The maximum is 11, but the minimum is less than 0.0 so the difference can be greater than 11.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Get perceptual hash value for image using command line

Post by fmw42 »

the limit of 11 comes from limiting the smallest value to 10^-11, so that the log of a very small number would not approach -infinity.
Post Reply