如何对重复的哈希进行分组?

时间:2014-01-30 19:14:30

标签: c# image hash tuples sha256

public byte[] HashImage(string fileName)
{
    using (var image = new Bitmap(fileName))
    {
        var sha256 = SHA256.Create();

        var rect = new Rectangle(0, 0, image.Width, image.Height);
        var data = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat);

        var dataPtr = data.Scan0;

        var totalBytes = (int)Math.Abs(data.Stride) * data.Height;
        var rawData = new byte[totalBytes];
        System.Runtime.InteropServices.Marshal.Copy(dataPtr, rawData, 0, totalBytes);

        image.UnlockBits(data);

        return sha256.ComputeHash(rawData);
    }
}

private Tuple<int, string> GetIndexedImage(string fileName)
{
    var baseFileName = Path.GetFileNameWithoutExtension(fileName);
    int index;
    if (int.TryParse(baseFileName, out index))
    {
        return Tuple.Create(index, fileName);
    }
    return null;
}

private string HashToString(byte[] hash)
{
    var builder = new StringBuilder();
    foreach (var b in hash)
    {
        builder.AppendFormat("{0:x2}", b);
    }
    return builder.ToString();
}

HashImage()将图像的SHA256哈希值作为字节。 GetFileIndex()返回索引和文件名的元组。 HashToString()是一个字符串构建器,它将哈希值转换为字符串。

private void button1_Click(object sender, EventArgs e)
{
    string original = @"C:\Users\user\Documents\CaptchaCollection\";

    var equivalentImages = Directory.GetFiles(original)
                                    .Select(f => GetIndexedImage(f)) // build tuples (index, fileName) or null if parsing failed
                                    .Where(t => t != null)           // ignore all invalid ones
                                    .OrderBy(t => t.Item1)           // order by index
                                    .Select(t => Tuple.Create(HashImage(t.Item2), t.Item2)) // create new tuple (hash, fileName)
                                    .GroupBy(t => t.Item1);          // group by Hash

    // print groups
    foreach (var group in equivalentImages)
    {
        Console.WriteLine("All images with hash: {0}", HashToString(group.Key));
        foreach (var t in group)
        {
            Console.WriteLine("\t{0}", t.Item2);
        }
    }

}

现在这就像是一个主要方法,当我点击按钮时,我开始得到图像文件的哈希值。

然而,现在主要的问题是,当我从文件中收集哈希的output时,它们似乎没有分组,而是按顺序打印。相反,它们遍布输出文件。

如何将具有相同散列的任何组和重复元素分组?

1 个答案:

答案 0 :(得分:0)

您正在byte[]进行分组。不幸的是,.NET集合不支持相等和散列。这意味着您默认获得参考比较。 (我的观点:这是.NET框架中的一个设计缺陷。应该没有默认的相等。在这种情况下应该抛出错误。)

给自己写一个IEqualityComparer<byte[]>

此外,您在分组前订购。分组不会保留订购。文档并不能保证不会被依赖。事实上,它并没有实践。