public void Test_SumSquaredDistance() { /* VS2008 compiler produces different results, no clue why this is happening */ #if NET20 return; #endif using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); using (MagickImage other = new MagickImage(Files.MagickNETIconPNG)) { PerceptualHash otherPhash = other.PerceptualHash(); #if Q8 Assert.AreEqual(248.53, phash.SumSquaredDistance(otherPhash), 0.01); #elif Q16 Assert.AreEqual(199.53, phash.SumSquaredDistance(otherPhash), 0.01); #elif Q16HDRI Assert.AreEqual(183.73, phash.SumSquaredDistance(otherPhash), 0.01); #else #error Not implemented! #endif } } }
public async Task <ImageInfo> Analyse(Stream imageStream) { // ReSharper disable once UseAwaitUsing if (imageStream.Length == 0) { throw new Exception("Image stream is 0"); } byte[] shaHash; using (var sha256Hasher = SHA256.Create()) { shaHash = await sha256Hasher.ComputeHashAsync(imageStream); } imageStream.Position = 0; var(image, format) = await SixLabors.ImageSharp.Image.LoadWithFormatAsync <Rgba32>(imageStream); using (image) { var width = image.Width; var height = image.Height; var mimeType = format.DefaultMimeType; var averageHasher = new AverageHash(); var averageHash = averageHasher.Hash(image); var perceptualHasher = new PerceptualHash(); var perceptualHash = perceptualHasher.Hash(image); var differenceHasher = new DifferenceHash(); var differenceHash = differenceHasher.Hash(image); return(new ImageInfo(shaHash, averageHash, differenceHash, perceptualHash, width, height, mimeType)); } }
public void Test_ToString() { /* VS2008 compiler produces different results, no clue why this is happening */ #if NET20 return; #endif using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); string hash = phash.ToString(); Assert.AreEqual(210, hash.Length); #if Q8 Assert.AreEqual("81b4488656898d38a7a96223562017620f7a26cf81a12823dd85b948bf8d86e5d89b6b81b1f884cb8a0d38af2f622728fd3f623fedeac7a78beaed8d81d8984349824c783ada81c378959b8c86a8c42b628ed61b216279c81b49887348a15f8af43622a3619d362370", hash); #elif Q16 Assert.AreEqual("81b4488651898d38a7a8622346206c620f8a648f8290a8361086f778ca5d889098c65381b1e884c58a0d18af2d622718fd35623ffdeaeda78b3aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", hash); #elif Q16HDRI Assert.AreEqual("81b4488651898d38a7a8622346206b620f8a728e82dde83ac4878188d4b2890f58db6b81b1e884c58a0d18af2d622718fd35623ffdeaeda78b4aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", hash); #else #error Not implemented! #endif PerceptualHash clone = new PerceptualHash(hash); Assert.AreEqual(0.0, phash.SumSquaredDistance(clone), 0.001); } }
public ImageHashFacade(IFileSystem fileSystem) { this.fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); averageHash = new AverageHash(); differenceHash = new DifferenceHash(); perceptualHash = new PerceptualHash(); }
/// <summary> /// Get the perceptual hash /// </summary> /// <param name="path"></param> /// <returns>A hex string representing the hash</returns> public string GetPerceptualHash(string path) { // PerceptualHash, DifferenceHash, AverageHash var hashAlgorithm = new PerceptualHash(); using var stream = File.OpenRead(path); ulong imageHash = hashAlgorithm.Hash(stream); var binaryString = Convert.ToString((long)imageHash, 16); return(binaryString); }
//private string DetectBest(ScanAreaDictionary lookup, IDictionary<int, Tuple<ulong, Rectangle>> useArea, string debugkey) //{ // var hashes = new List<ulong>(); // var keys = new List<string>(); // var rect = new Rectangle(); // int theResolution; // foreach (var key in lookup.Keys) // { // var template = lookup[key]; // ulong matchhash; // if (template.ContainsKey(this.lastResolution)) // { // matchhash = template[this.lastResolution].Hash; // } // else if (template.ContainsKey(this.BaseResolution)) // { // matchhash = template[this.BaseResolution].Hash; // } // else // { // Log.Error("No scan data found for requested template: " + debugkey); // return null; // } // hashes.Add(matchhash); // keys.Add(key); // } // if (useArea.ContainsKey(this.lastResolution)) // { // rect = useArea[this.lastResolution].Rect; // theResolution = this.lastResolution; // } // else if (useArea.ContainsKey(this.BaseResolution)) // { // rect = useArea[this.BaseResolution].Rect; // theResolution = this.BaseResolution; // } // else // { // Log.Error("No scan data found for requested template: " + debugkey); // return null; // } // var source = this.image; // using (var roi = source.Clone(ResolutionHelper.CorrectRectangle(source.Size, rect, theResolution), PixelFormat.Format32bppRgb)) // { // var hash = this.imageHasher.Create(roi); // var best = PerceptualHash.FindBest(hash, hashes); // if (best.Distance <= ThreshHold) // { // Log.Diag("Detected best hash: '{0}' Distance: {1}", debugkey, best.Distance); // return keys[best.Index]; // } // } // return null; //} private string DetectBest(ScanAreaDictionary lookup, string debugkey, int?threshold = null) { threshold = threshold ?? ThreshHold; var hashes = new List <ulong>(); var keys = new List <string>(); var rect = new Rectangle(); int theResolution = BaseResolution; foreach (var key in lookup.Keys) { var template = lookup[key]; ulong matchhash; if (template.ContainsKey(this.lastResolution)) { matchhash = template[this.lastResolution].Hash; rect = template[this.lastResolution].Rect; theResolution = this.lastResolution; } else if (template.ContainsKey(this.BaseResolution)) { matchhash = template[this.BaseResolution].Hash; rect = template[this.BaseResolution].Rect; theResolution = this.BaseResolution; } else { Log.Error("No scan data found for requested template: " + debugkey); return(null); } hashes.Add(matchhash); keys.Add(key); } var source = this.image; using (var roi = source.Lock(ResolutionHelper.CorrectRectangle(source.Size, rect, theResolution), PixelFormat.Format32bppRgb)) { var hash = this.imageHasher.Create(roi.Data); var best = PerceptualHash.FindBest(hash, hashes); TraceLog.Log("Detected best hash: '{0}' Distance: {1}", debugkey, best.Distance); if (best.Distance <= threshold) { return(keys[best.Index]); } } return(null); }
public void Test_ToString() { using (var image = new MagickImage(Files.ImageMagickJPG)) { var phash = image.PerceptualHash(); string hash = phash.ToString(); Assert.Equal(210, hash.Length); #if Q8 OpenCLValue.Assert("81b4488655898d38a7aa6223562032620f8a2614819b78241685c4b8c1a786f0689c9881b1f884ca8a0d38af2f622728fd3d623fedeacea78bcaedaa81d8884349824c583ad981c37895998c8658c42a628ed61b216279b81b49887348a1608af44622a3619d362371", "81b4488656898d38a7a96223562017620f7a26cd81a1e823ec85b3b8cc3186ec889ad481b1f884cb8a0d58af30622728fd41623fedea8aa78d4aeda481d8f84355824cd83ae281c378959a8c8668c42a628ec61b216279c81b49887348a1608af44622a3619d362370", hash); #elif Q16 OpenCLValue.Assert("81b4488652898d48a7a9622346206e620f8a649d8297d835bd86eb58c7be887e78c5f881b1e884c58a0d18af2d622718fd35623ffdeac9a78cbaedaa81d888434e824c683ad781c37895978c8688c426628ed61b216279b81b48887318a1628af43622a2619d162372", "81b4488652898d48a7a9622346206e620f8a646682939835e986ec98c78f887ae8c67f81b1e884c58a0d18af2d622718fd35623ffdeac9a78cbaedaa81d888434e824c683ad781c37895978c8688c426628ed61b216279b81b48887318a1628af43622a2619d162372", hash); #else OpenCLValue.Assert("81b4488652898d48a7a9622346206e620f8a730882e4a83a9e877108d25488fc58dbb781b1e884c58a0d18af2d622718fd35623ffdeac9a78cbaedaa81d888434e824c683ad781c37895978c8688c426628ed61b216279b81b48887318a1628af43622a2619d162372", "81b4488652898d48a7a9622346206e620f8a731182e3a83aa2876d48d19488f438dcb581b1e884c58a0d18af2d622718fd35623ffdeac9a78cbaedaa81d888434e824c683ad781c37895978c8688c426628ed61b216279b81b48887318a1628af43622a2619d162372", hash); #endif PerceptualHash clone = new PerceptualHash(hash); Assert.InRange(phash.SumSquaredDistance(clone), 0.0, 0.001); } }
public void UpdateHash() { if (SelectedScanArea == null || Screenshot == null) { return; } var model = SelectedScanArea; var image = ImageHelper.BitmapImage2Bitmap(Screenshot); var roi = image.Clone(new Rectangle((int)(this.Region.XPos + this.BoardX), (int)this.Region.YPos, (int)this.Region.Width, (int)this.Region.Height), image.PixelFormat); var hash = hasher.Create(roi); var filename = AppDomain.CurrentDomain.BaseDirectory + "\\data\\images\\" + model.Key + ".png"; roi.Save(filename, ImageFormat.Png); image.Dispose(); model.Hash = hash; model.Image = roi; if (!String.IsNullOrWhiteSpace(CompareHash)) { CompareHashResult = PerceptualHash.HammingDistance(model.Hash, Convert.ToUInt64(CompareHash)); } var color = roi.GetDominantColor(); Mostly = String.Format("R: {0} G: {1} B: {2}", color.R, color.G, color.B); var corners = cornerDetecter.GetCorners(roi); var right = 0; foreach (var c in corners) { if (c.X > right) { right = c.X; } } RightMostCorner = right; }
public void Test_ToString() { using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); string hash = phash.ToString(); Assert.AreEqual(210, hash.Length); #if Q8 OpenCLValue.Assert("81b4488655898d38a7a9622356203b620f8a257faffcd823c685c228bed086e9c89c3b81b1f884c98a0d38af2f622728fd3d623fedeb01a78a7aed9381d8684342824c283ad681c378959a8c86b8c429628ee61b216279b81b49887338a1608af44622a3619d362371", "81b4488656898d38a7a96223562017620f7a26cf81a12823dd85b948bf8d86e5d89b6b81b1f884cb8a0d38af2f622728fd3f623fedeac7a78beaed8d81d8984349824c783ada81c378959b8c86a8c42b628ed61b216279c81b49887348a15f8af43622a3619d362370", hash); #elif Q16 OpenCLValue.Assert("81b4488651898d38a7a8622346206c620f8a64ba8293d835f086f338cb378897b8c52581b1e884c58a0d18af2d622718fd35623ffdeaeda78b3aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", "81b4488651898d38a7a8622346206c620f8a648f8290a8361086f778ca5d889098c65381b1e884c58a0d18af2d622718fd35623ffdeaeda78b3aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", hash); #elif Q16HDRI OpenCLValue.Assert("81b4488651898d48a7a8622346206c620f8a725f82deb83a96878108d4c2891118dad981b1e884c58a0d18af2d622718fd35623ffdeaeda78b4aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", "81b4488651898d38a7a8622346206b620f8a728e82dde83ac4878188d4b2890f58db6b81b1e884c58a0d18af2d622718fd35623ffdeaeda78b4aeda581d8484344824c083ad281c37895978c86d8c425628ee61b216279b81b48887318a1628af42622a2619d162372", hash); #else #error Not implemented! #endif PerceptualHash clone = new PerceptualHash(hash); Assert.AreEqual(0.0, phash.SumSquaredDistance(clone), 0.001); } }
public void Test_SumSquaredDistance() { using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); using (MagickImage other = new MagickImage(Files.MagickNETIconPNG)) { other.HasAlpha = false; PerceptualHash otherPhash = other.PerceptualHash(); #if Q8 Assert.AreEqual(311.71, phash.SumSquaredDistance(otherPhash), 0.01); #elif Q16 Assert.AreEqual(311.45, phash.SumSquaredDistance(otherPhash), 0.02); #elif Q16HDRI Assert.AreEqual(311.27, phash.SumSquaredDistance(otherPhash), 0.02); #else #error Not implemented! #endif } } }
/// <summary> /// Compute the perceptual hash of the given image file. We need to handle black and white PNG /// files which carry the image data in only the alpha channel. Other image files are trivial /// to handle by comparison with the CoenM.ImageSharp.ImageHash functions. /// </summary> public ulong ComputeImageHash(string path) { using (var image = (Image <Rgba32>)Image.Load(path)) { // check whether we have R=G=B=0 (ie, black) for all pixels, presumably with A varying. var allBlack = true; for (int x = 0; allBlack && x < image.Width; ++x) { for (int y = 0; allBlack && y < image.Height; ++y) { var pixel = image[x, y]; if (pixel.R != 0 || pixel.G != 0 || pixel.B != 0) { allBlack = false; } } } if (allBlack) { for (int x = 0; x < image.Width; ++x) { for (int y = 0; y < image.Height; ++y) { // If the pixels all end up the same because A never changes, we're no // worse off because the hash result will still be all zero bits. var pixel = image[x, y]; pixel.R = pixel.A; pixel.G = pixel.A; pixel.B = pixel.A; image[x, y] = pixel; } } } var hashAlgorithm = new PerceptualHash(); return(hashAlgorithm.Hash(image)); } }
public void Test_SumSquaredDistance() { using (IMagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); using (IMagickImage other = new MagickImage(Files.MagickNETIconPNG)) { other.HasAlpha = false; Assert.AreEqual(3, other.ChannelCount); PerceptualHash otherPhash = other.PerceptualHash(); #if Q8 OpenCLValue.Assert(394.74, 394.90, phash.SumSquaredDistance(otherPhash), 0.01); #elif Q16 OpenCLValue.Assert(395.35, 395.39, phash.SumSquaredDistance(otherPhash), 0.02); #elif Q16HDRI OpenCLValue.Assert(395.60, 395.68, phash.SumSquaredDistance(otherPhash), 0.02); #else #error Not implemented! #endif } } }
public void Test_Channel() { using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); ChannelPerceptualHash channel = phash.GetChannel(PixelChannel.Red); ExceptionAssert.Throws <ArgumentOutOfRangeException>(delegate() { channel.HclpHuPhash(7); }); ExceptionAssert.Throws <ArgumentOutOfRangeException>(delegate() { channel.SrgbHuPhash(7); }); #if Q8 TestChannel(channel, 0, 0.6980, 0.6980, 0.0959, 0.0993); TestChannel(channel, 1, 3.4390, 3.4390, 0.6548, 0.6673); TestChannel(channel, 2, 3.9123, 3.9123, 0.9158, 0.9181); TestChannel(channel, 3, 4.2921, 4.2920, 2.3586, 2.3443); TestChannel(channel, 4, 8.7567, 8.7573, 4.8847, 4.9037); TestChannel(channel, 5, 8.2505, 8.2147, 2.8316, 2.8253); TestChannel(channel, 6, 8.4397, 8.4394, 3.9994, 3.9786); #elif Q16 TestChannel(channel, 0, 0.6979, 0.6979, 0.2578, 0.2574); TestChannel(channel, 1, 3.4385, 3.4385, 1.0557, 1.0505); TestChannel(channel, 2, 3.9123, 3.9123, 1.3807, 1.3839); TestChannel(channel, 3, 4.2920, 4.2920, 2.8467, 2.8534); TestChannel(channel, 4, 8.7555, 8.7555, 5.2023, 5.1805); TestChannel(channel, 5, 8.2995, 8.2995, 3.5194, 3.5081); TestChannel(channel, 6, 8.4397, 8.4397, 5.0468, 5.0770); #elif Q16HDRI TestChannel(channel, 0, 0.6979, 0.6979, 0.2927, 0.2932); TestChannel(channel, 1, 3.4385, 3.4385, 1.1754, 1.1742); TestChannel(channel, 2, 3.9123, 3.9123, 1.4998, 1.5044); TestChannel(channel, 3, 4.2920, 4.2920, 3.0736, 3.0744); TestChannel(channel, 4, 8.7556, 8.7555, 5.4465, 5.4449); TestChannel(channel, 5, 8.2997, 8.2994, 3.7136, 3.7108); TestChannel(channel, 6, 8.4398, 8.4397, 5.6025, 5.6170); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Green); #if Q8 TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3992, 3.3994, 0.3088, 0.3090); TestChannel(channel, 2, 4.1171, 4.1171, 0.6081, 0.6081); TestChannel(channel, 3, 4.4847, 4.4847, 0.7557, 0.7561); TestChannel(channel, 4, 8.8179, 8.8181, 1.7217, 1.7225); TestChannel(channel, 5, 6.4828, 6.4830, 0.9410, 0.9414); TestChannel(channel, 6, 9.2143, 9.2141, 1.5061, 1.5066); #elif Q16 TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3988, 3.3988, 0.3089, 0.3089); TestChannel(channel, 2, 4.1168, 4.1168, 0.6083, 0.6083); TestChannel(channel, 3, 4.4844, 4.4844, 0.7555, 0.7555); TestChannel(channel, 4, 8.8174, 8.8174, 1.7219, 1.7219); TestChannel(channel, 5, 6.4821, 6.4821, 0.9408, 0.9408); TestChannel(channel, 6, 9.2147, 9.2147, 1.5058, 1.5058); #elif Q16HDRI TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3988, 3.3988, 0.3089, 0.3089); TestChannel(channel, 2, 4.1168, 4.1168, 0.6083, 0.6083); TestChannel(channel, 3, 4.4844, 4.4844, 0.7555, 0.7555); TestChannel(channel, 4, 8.8174, 8.8174, 1.7219, 1.7219); TestChannel(channel, 5, 6.4821, 6.4821, 0.9408, 0.9408); TestChannel(channel, 6, 9.2148, 9.2147, 1.5058, 1.5058); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Blue); #if Q8 TestChannel(channel, 0, 0.7223, 0.7223, 0.6984, 0.6984); TestChannel(channel, 1, 3.8298, 3.8298, 3.4611, 3.4611); TestChannel(channel, 2, 5.1307, 5.1306, 4.1312, 4.1311); TestChannel(channel, 3, 5.0216, 5.0218, 4.4867, 4.4867); TestChannel(channel, 4, 10.4775, 10.4768, 8.8669, 8.8668); TestChannel(channel, 5, 6.9452, 6.9454, 6.6106, 6.6108); TestChannel(channel, 6, 10.1394, 10.1398, 9.0727, 9.0722); #elif Q16 TestChannel(channel, 0, 0.7222, 0.7222, 0.6984, 0.6984); TestChannel(channel, 1, 3.8295, 3.8295, 3.4608, 3.4608); TestChannel(channel, 2, 5.1309, 5.1309, 4.1314, 4.1314); TestChannel(channel, 3, 5.0213, 5.0213, 4.4866, 4.4866); TestChannel(channel, 4, 10.4778, 10.4778, 8.8663, 8.8663); TestChannel(channel, 5, 6.9448, 6.9448, 6.6093, 6.6093); TestChannel(channel, 6, 10.1388, 10.1388, 9.0737, 9.0737); #elif Q16HDRI TestChannel(channel, 0, 0.7222, 0.7222, 0.6984, 0.6984); TestChannel(channel, 1, 3.8295, 3.8295, 3.4609, 3.4608); TestChannel(channel, 2, 5.1309, 5.1309, 4.1314, 4.1314); TestChannel(channel, 3, 5.0213, 5.0213, 4.4866, 4.4866); TestChannel(channel, 4, 10.4778, 10.4778, 8.8663, 8.8663); TestChannel(channel, 5, 6.9448, 6.9448, 6.6094, 6.6093); TestChannel(channel, 6, 10.1388, 10.1388, 9.0737, 9.0737); #else #error Not implemented! #endif } }
public void Test_Channel() { using (IMagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); ChannelPerceptualHash channel = phash.GetChannel(PixelChannel.Red); ExceptionAssert.Throws <ArgumentOutOfRangeException>(() => { channel.HclpHuPhash(7); }); ExceptionAssert.Throws <ArgumentOutOfRangeException>(() => { channel.SrgbHuPhash(7); }); #if Q8 TestChannel(channel, 0, 0.6980, 0.6980, 0.0974, 0.0993); TestChannel(channel, 1, 3.4388, 3.4390, 0.6582, 0.6685); TestChannel(channel, 2, 3.9123, 3.9123, 0.9238, 0.9195); TestChannel(channel, 3, 4.2922, 4.2920, 2.3627, 2.3354); TestChannel(channel, 4, 8.7570, 8.7574, 4.9574, 5.2273); TestChannel(channel, 5, 8.2422, 8.2149, 2.8422, 2.8360); TestChannel(channel, 6, 8.4397, 8.4394, 4.0087, 3.9636); #elif Q16 TestChannel(channel, 0, 0.6979, 0.6979, 0.2575, 0.2570); TestChannel(channel, 1, 3.4385, 3.4385, 1.0621, 1.0552); TestChannel(channel, 2, 3.9123, 3.9123, 1.3756, 1.3800); TestChannel(channel, 3, 4.2920, 4.2920, 2.8341, 2.8360); TestChannel(channel, 4, 8.7557, 8.7557, 5.1134, 5.1087); TestChannel(channel, 5, 8.3019, 8.3018, 3.4791, 3.4733); TestChannel(channel, 6, 8.4398, 8.4398, 5.0679, 5.0815); #elif Q16HDRI TestChannel(channel, 0, 0.6979, 0.6979, 0.2944, 0.2945); TestChannel(channel, 1, 3.4385, 3.4385, 1.1850, 1.1834); TestChannel(channel, 2, 3.9123, 3.9123, 1.5006, 1.5009); TestChannel(channel, 3, 4.2920, 4.2920, 3.0480, 3.0419); TestChannel(channel, 4, 8.7557, 8.7557, 5.3844, 5.3651); TestChannel(channel, 5, 8.3018, 8.3018, 3.6804, 3.6675); TestChannel(channel, 6, 8.4398, 8.4398, 5.6247, 5.6501); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Green); #if Q8 TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3993, 3.3995, 0.3090, 0.3093); TestChannel(channel, 2, 4.1171, 4.1172, 0.6084, 0.6083); TestChannel(channel, 3, 4.4847, 4.4847, 0.7559, 0.7566); TestChannel(channel, 4, 8.8180, 8.8183, 1.7224, 1.7237); TestChannel(channel, 5, 6.4829, 6.4832, 0.9413, 0.9421); TestChannel(channel, 6, 9.2143, 9.2141, 1.5065, 1.5074); #elif Q16 TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3989, 3.3989, 0.3092, 0.3092); TestChannel(channel, 2, 4.1169, 4.1169, 0.6084, 0.6084); TestChannel(channel, 3, 4.4844, 4.4844, 0.7559, 0.7559); TestChannel(channel, 4, 8.8174, 8.8174, 1.7230, 1.7230); TestChannel(channel, 5, 6.4821, 6.4821, 0.9413, 0.9413); TestChannel(channel, 6, 9.2148, 9.2148, 1.5063, 1.5063); #elif Q16HDRI TestChannel(channel, 0, 0.6942, 0.6942, -0.0601, -0.0601); TestChannel(channel, 1, 3.3989, 3.3989, 0.3092, 0.3092); TestChannel(channel, 2, 4.1169, 4.1169, 0.6084, 0.6084); TestChannel(channel, 3, 4.4844, 4.4844, 0.7559, 0.7559); TestChannel(channel, 4, 8.8174, 8.8174, 1.7230, 1.7230); TestChannel(channel, 5, 6.4821, 6.4821, 0.9413, 0.9413); TestChannel(channel, 6, 9.2148, 9.2148, 1.5063, 1.5063); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Blue); #if Q8 TestChannel(channel, 0, 0.7223, 0.7223, 0.6984, 0.6984); TestChannel(channel, 1, 3.8298, 3.8298, 3.4611, 3.4612); TestChannel(channel, 2, 5.1301, 5.1301, 4.1312, 4.1312); TestChannel(channel, 3, 5.0217, 5.0218, 4.4867, 4.4867); TestChannel(channel, 4, 10.4769, 10.4761, 8.8669, 8.8670); TestChannel(channel, 5, 6.9453, 6.9454, 6.6108, 6.6110); TestChannel(channel, 6, 10.1394, 10.1396, 9.0725, 9.0722); #elif Q16 TestChannel(channel, 0, 0.7222, 0.7222, 0.6984, 0.6984); TestChannel(channel, 1, 3.8295, 3.8295, 3.4609, 3.4609); TestChannel(channel, 2, 5.1304, 5.1304, 4.1314, 4.1314); TestChannel(channel, 3, 5.0214, 5.0214, 4.4866, 4.4866); TestChannel(channel, 4, 10.4771, 10.4772, 8.8663, 8.8663); TestChannel(channel, 5, 6.9448, 6.9448, 6.6094, 6.6094); TestChannel(channel, 6, 10.1388, 10.1388, 9.0737, 9.0737); #elif Q16HDRI TestChannel(channel, 0, 0.7222, 0.7222, 0.6984, 0.6984); TestChannel(channel, 1, 3.8295, 3.8295, 3.4609, 3.4609); TestChannel(channel, 2, 5.1304, 5.1304, 4.1314, 4.1314); TestChannel(channel, 3, 5.0214, 5.0214, 4.4866, 4.4866); TestChannel(channel, 4, 10.4772, 10.4772, 8.8663, 8.8663); TestChannel(channel, 5, 6.9448, 6.9448, 6.6094, 6.6094); TestChannel(channel, 6, 10.1388, 10.1388, 9.0737, 9.0737); #else #error Not implemented! #endif } }
/// <summary>The detect.</summary> /// <param name="lookup">The lookup.</param> /// <param name="key">The key.</param> /// <param name="useArea"></param> /// <param name="i"></param> /// <returns>The <see cref="bool"/>.</returns> private DetectionResult Detect(ScanAreaDictionary lookup, string key, IDictionary <int, ScanArea> useArea = null, int threshold = -1) { threshold = threshold >= 0 ? threshold : ThreshHold; if (!lookup.ContainsKey(key)) { Log.Error("No scan data found for requested template: {0}", key); return(new DetectionResult(false, -1)); } var template = lookup[key]; // var rect = new Rectangle(); int theResolution; // ulong matchhash; ScanArea area = null; if (template.ContainsKey(this.lastResolution)) { // rect = template[this.lastResolution].Rect; // matchhash = template[this.lastResolution].Hash; area = template[this.lastResolution]; theResolution = this.lastResolution; } else if (template.ContainsKey(this.BaseResolution)) { // rect = template[this.BaseResolution].Rect; // matchhash = template[this.BaseResolution].Hash; area = template[this.BaseResolution]; theResolution = this.BaseResolution; } else { Log.Error("No scan data found for requested template: " + key); return(new DetectionResult(false, -1)); } if (useArea != null) { if (useArea.ContainsKey(this.lastResolution)) { // rect = useArea[this.lastResolution].Rect; area = useArea[this.lastResolution]; theResolution = this.lastResolution; } else if (useArea.ContainsKey(this.BaseResolution)) { // rect = useArea[this.BaseResolution].Rect; area = useArea[this.BaseResolution]; theResolution = this.BaseResolution; } else { Log.Error("No scan data found for requested template: " + key); return(new DetectionResult(false, -1)); } } var source = this.image; int distance = -1; DetectionResult result = new DetectionResult(); using (var roi = source.Lock(ResolutionHelper.CorrectRectangle(source.Size, area.Rect, theResolution), source.PixelFormat)) { // var roi = source.Clone(ResolutionHelper.CorrectRectangle(source.Size, area.Rect, theResolution), source.PixelFormat); //Tuple<byte[], DetectionResult> cached = null; //byte[] roiBytes = roi.GetBytes(); //if (hashCache.TryGetValue(key, out cached)) //{ // if (ImageUtils.AreEqual(cached.Item1, roiBytes)) // { // TraceLog.Log("hash cache hit: {0}, hit: {1} distance: {2}", key, cached.Item2.Found, cached.Item2.Distance); // return cached.Item2; // } //} var hash = this.imageHasher.Create(roi.Data); distance = PerceptualHash.HammingDistance(hash, area.Hash); TraceLog.Log("Detecting '{0}'. Distance: {1}", key, distance); if (distance <= threshold) { TraceLog.Log("Detected '{0}'. Distance: {1}", key, distance); Mostly mostly; if (!String.IsNullOrEmpty(area.Mostly) && Enum.TryParse(area.Mostly, out mostly)) { result = new DetectionResult(roi.Data.IsMostly(mostly), distance); } else { result = new DetectionResult(true, distance); } } else { result = new DetectionResult(false, distance); } // hashCache.Set(key, new Tuple<byte[], DetectionResult>(roiBytes, result)); } return(result); }
public void Test_Channel() { #if NET20 Assert.Inconclusive("VS2008 compiler produces different results, no clue why this is happening"); #endif using (MagickImage image = new MagickImage(Files.ImageMagickJPG)) { PerceptualHash phash = image.PerceptualHash(); ChannelPerceptualHash channel = phash.GetChannel(PixelChannel.Red); ExceptionAssert.Throws <ArgumentOutOfRangeException>(delegate() { channel.HclpHuPhash(7); }); ExceptionAssert.Throws <ArgumentOutOfRangeException>(delegate() { channel.SrgbHuPhash(7); }); #if Q8 TestChannel(channel, 0, 0.6980, 0.0993); TestChannel(channel, 1, 3.4390, 0.6673); TestChannel(channel, 2, 3.9123, 0.9181); TestChannel(channel, 3, 4.2920, 2.3443); TestChannel(channel, 4, 8.7573, 4.9037); TestChannel(channel, 5, 8.2147, 2.8253); TestChannel(channel, 6, 8.4394, 3.9786); #elif Q16 TestChannel(channel, 0, 0.6979, 0.2574); TestChannel(channel, 1, 3.4385, 1.0505); TestChannel(channel, 2, 3.9123, 1.3839); TestChannel(channel, 3, 4.2920, 2.8534); TestChannel(channel, 4, 8.7555, 5.1805); TestChannel(channel, 5, 8.2995, 3.5081); TestChannel(channel, 6, 8.4397, 5.0770); #elif Q16HDRI TestChannel(channel, 0, 0.6979, 0.2932); TestChannel(channel, 1, 3.4385, 1.1742); TestChannel(channel, 2, 3.9123, 1.5044); TestChannel(channel, 3, 4.2920, 3.0744); TestChannel(channel, 4, 8.7555, 5.4449); TestChannel(channel, 5, 8.2994, 3.7108); TestChannel(channel, 6, 8.4397, 5.6170); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Green); #if Q8 TestChannel(channel, 0, 0.6942, -0.06010); TestChannel(channel, 1, 3.3994, 0.30909); TestChannel(channel, 2, 4.1171, 0.60813); TestChannel(channel, 3, 4.4847, 0.75613); TestChannel(channel, 4, 8.8181, 1.72254); TestChannel(channel, 5, 6.4830, 0.94147); TestChannel(channel, 6, 9.2141, 1.50663); #elif Q16 TestChannel(channel, 0, 0.6942, -0.0601); TestChannel(channel, 1, 3.3988, 0.3089); TestChannel(channel, 2, 4.1168, 0.6083); TestChannel(channel, 3, 4.4844, 0.7555); TestChannel(channel, 4, 8.8174, 1.7219); TestChannel(channel, 5, 6.4821, 0.9408); TestChannel(channel, 6, 9.2147, 1.5058); #elif Q16HDRI TestChannel(channel, 0, 0.6942, -0.06014); TestChannel(channel, 1, 3.3988, 0.30899); TestChannel(channel, 2, 4.1168, 0.60836); TestChannel(channel, 3, 4.4844, 0.75556); TestChannel(channel, 4, 8.8174, 1.72197); TestChannel(channel, 5, 6.4821, 0.94082); TestChannel(channel, 6, 9.2147, 1.50582); #else #error Not implemented! #endif channel = phash.GetChannel(PixelChannel.Blue); #if Q8 TestChannel(channel, 0, 0.7223, 0.6984); TestChannel(channel, 1, 3.8298, 3.4611); TestChannel(channel, 2, 5.1306, 4.1311); TestChannel(channel, 3, 5.0218, 4.4867); TestChannel(channel, 4, 10.4768, 8.8668); TestChannel(channel, 5, 6.9454, 6.6108); TestChannel(channel, 6, 10.1398, 9.0722); #elif Q16 TestChannel(channel, 0, 0.7222, 0.6984); TestChannel(channel, 1, 3.8295, 3.4608); TestChannel(channel, 2, 5.1309, 4.1314); TestChannel(channel, 3, 5.0213, 4.4866); TestChannel(channel, 4, 10.4778, 8.8663); TestChannel(channel, 5, 6.9448, 6.6093); TestChannel(channel, 6, 10.1388, 9.0737); #elif Q16HDRI TestChannel(channel, 0, 0.7222, 0.6984); TestChannel(channel, 1, 3.8295, 3.4608); TestChannel(channel, 2, 5.1309, 4.1314); TestChannel(channel, 3, 5.0213, 4.4866); TestChannel(channel, 4, 10.4778, 8.8663); TestChannel(channel, 5, 6.9448, 6.6093); TestChannel(channel, 6, 10.1388, 9.0737); #else #error Not implemented! #endif } }
public PerceptualHashTest() { sut = new PerceptualHash(); }