C# Implementation of pHash (http://phash.org). Based on phash-0.9.4 for Windows.
- Shipwreck.Phash - C# Implementation of phash-0.9.4.
The Shipwreck.Phash
accepts only IByteImage
interface. The package does not contain any method to load an image.
So additional packages provide extension methods to instantiate ByteImage
- Shipwreck.Phash.Bitmaps - for System.Drawing.dll including Mono implementation.
- Shipwreck.Phash.PresentationCore - for PresentationCore.dll. Used for WPF, ASP.NET or Windows Service.
There are some more packages for uncommon usage.
- Shipwreck.Phash.Data - Provides Stored Function Implementations for pHash Digests
- Shipwreck.Phash.CrossCorrelation - C# Implementation of phash-0.9.4 that provides Only GetCrossCorrelation functionality. Intended to be referenced from SQL CLR.
Following methods contains breaking changes at versions below. Hashes computed by older versions cannot be compared with the new one:
ImagePhash.ComputeDctHash
: at0.5.0
.
var bitmap = (Bitmap)Image.FromFile(fullPathToImage);
var hash = ImagePhash.ComputeDigest(bitmap.ToLuminanceImage());
var bitmapSource = BitmapFrame.Create(stream);
var hash = ImagePhash.ComputeDigest(bitmapSource.ToLuminanceImage());
var score = ImagePhash.GetCrossCorrelation(hash1, hash2);
Example below required .NET 4.7+ since the function returns a tuple of results.
public static (ConcurrentDictionary<string, Digest> filePathsToHashes, ConcurrentDictionary<Digest, HashSet<string>> hashesToFiles) GetHashes(string dirPath, string searchPattern)
{
var filePathsToHashes = new ConcurrentDictionary<string, Digest>();
var hashesToFiles = new ConcurrentDictionary<Digest, HashSet<string>>();
var files = Directory.GetFiles(dirPath, searchPattern);
Parallel.ForEach(files, (currentFile) =>
{
var bitmap = (Bitmap)Image.FromFile(currentFile);
var hash = ImagePhash.ComputeDigest(bitmap);
filePathsToHashes[currentFile] = hash;
HashSet<string> currentFilesForHash;
lock (hashesToFiles)
{
if (!hashesToFiles.TryGetValue(hash, out currentFilesForHash))
{
currentFilesForHash = new HashSet<string>();
hashesToFiles[hash] = currentFilesForHash;
}
}
lock (currentFilesForHash)
{
currentFilesForHash.Add(currentFile);
}
});
return (filePathsToHashes, hashesToFiles);
}
Then you can call it like this:
(ConcurrentDictionary<string, Digest> gilePathsToHashes, ConcurrentDictionary<Digest, HashSet<string>> hashesToFiles) =
GetHashes(
dirPath: @"C:\some\path\",
searchPattern: "*.jpg");
Download Image sets from http://phash.org/download/ and extract into the /data/compr
, /data/blur
, /data/rotd
, /data/misc
directories.
Or you can create test Image sets by yourself.
GNU General Public License version 3 or later http://www.gnu.org/licenses/