/// <summary> /// Compare two image hashes and return a value between 0 and 1. /// 0 meaning the two hashes (and therefore underlying images) are the same, /// and 1 meaning they are totally different. /// </summary> /// <param name="hash1"></param> /// <param name="hash2"></param> /// <returns></returns> public static double CompareHashes(ImageHash hash1, ImageHash hash2) { if (hash1.Algorithm != hash2.Algorithm) { throw new ArgumentException("Both hashes must use the same algorithm!"); } double result; switch (hash1.Algorithm) { case HashAlgorithm.DCT: int rawHammingResult = NativeFunctions.ph_hamming_distance(((DCTHash)hash1).Hash, ((DCTHash)hash2).Hash); result = NormalizeThreshold(HashAlgorithm.DCT, rawHammingResult); break; case HashAlgorithm.Radial: NativeStructures.Digest digest1 = ((RadialHash)hash1).Digest; NativeStructures.Digest digest2 = ((RadialHash)hash2).Digest; double rawCrossCorrResult; NativeFunctions.ph_crosscorr(ref digest1, ref digest2, out rawCrossCorrResult); result = NormalizeThreshold(HashAlgorithm.Radial, rawCrossCorrResult); break; case HashAlgorithm.MH: MHHash mhHash1 = (MHHash)hash1; MHHash mhHash2 = (MHHash)hash2; double rawHamming2Result = NativeFunctions.ph_hammingdistance2(mhHash1.BytesPtr, mhHash1.ByteCount, mhHash2.BytesPtr, mhHash2.ByteCount); result = NormalizeThreshold(HashAlgorithm.MH, rawHamming2Result); break; default: throw new NotImplementedException(); } return result; }
/// <summary> /// Compare two image hashes and return a value between 0 and 1. /// 0 meaning the two hashes (and therefore underlying images) are the same, /// and 1 meaning they are totally different. /// </summary> /// <param name="hash1"></param> /// <param name="hash2"></param> /// <returns></returns> public static double CompareHashes(ImageHash hash1, ImageHash hash2) { if (hash1.Algorithm != hash2.Algorithm) { throw new ArgumentException("Both hashes must use the same algorithm!"); } double result; switch (hash1.Algorithm) { case HashAlgorithm.DCT: int rawHammingResult = NativeFunctions.ph_hamming_distance(((DCTHash)hash1).Hash, ((DCTHash)hash2).Hash); result = NormalizeThreshold(HashAlgorithm.DCT, rawHammingResult); break; case HashAlgorithm.Radial: NativeStructures.Digest digest1 = ((RadialHash)hash1).Digest; NativeStructures.Digest digest2 = ((RadialHash)hash2).Digest; double rawCrossCorrResult; NativeFunctions.ph_crosscorr(ref digest1, ref digest2, out rawCrossCorrResult); result = NormalizeThreshold(HashAlgorithm.Radial, rawCrossCorrResult); break; case HashAlgorithm.MH: MHHash mhHash1 = (MHHash)hash1; MHHash mhHash2 = (MHHash)hash2; double rawHamming2Result = NativeFunctions.ph_hammingdistance2(mhHash1.BytesPtr, mhHash1.ByteCount, mhHash2.BytesPtr, mhHash2.ByteCount); result = NormalizeThreshold(HashAlgorithm.MH, rawHamming2Result); break; default: throw new NotImplementedException(); } return(result); }
/// <summary> /// Compare two image hashes and return a boolean indicating if the underlying images are similar (true) or not (false). /// </summary> /// <param name="hash1"></param> /// <param name="hash2"></param> /// <param name="result"></param> /// <param name="threshold"></param> /// <returns></returns> public static bool CompareHashes(ImageHash hash1, ImageHash hash2, out double result, double threshold = .40f) { result = CompareHashes(hash1, hash2); return result <= threshold; }
/// <summary> /// Compare two image hashes and return a boolean indicating if the underlying images are similar (true) or not (false). /// </summary> /// <param name="hash1"></param> /// <param name="hash2"></param> /// <param name="threshold"></param> /// <returns></returns> public static bool CompareHashes(ImageHash hash1, ImageHash hash2, double threshold = .40f) { double result = CompareHashes(hash1, hash2); return(result <= threshold); }