Ответ 1
Вот простой подход с 256-битным хэш-изображением (MD5 имеет 128 бит)
- измените размер изображения на 16x16.
- уменьшить цвета до черного/ белого (что равно true/ false в этом консольном выпуске)
- читайте логические значения в
List<bool>
- это хеш
Код
public static List<bool> GetHash(Bitmap bmpSource)
{
List<bool> lResult = new List<bool>();
//create new image with 16x16 pixel
Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16));
for (int j = 0; j < bmpMin.Height; j++)
{
for (int i = 0; i < bmpMin.Width; i++)
{
//reduce colors to true / false
lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.5f);
}
}
return lResult;
}
Я знаю, GetPixel
не так быстро, но на 16x16 пиксельном изображении это не должно быть узким местом.
- сравнить этот хеш с хэш-значениями из других изображений и добавить допуск (количество пикселей, которое может отличаться от другого хеша)
Код:
List<bool> iHash1 = GetHash(new Bitmap(@"C:\mykoala1.jpg"));
List<bool> iHash2 = GetHash(new Bitmap(@"C:\mykoala2.jpg"));
//determine the number of equal pixel (x of 256)
int equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);
Таким образом, этот код способен находить равные изображения с помощью:
- различные форматы файлов (например, jpg, png, bmp)
- вращение (90, 180, 270) - путем изменения порядка итераций
i
иj
- разные размеры (требуется тот же аспект)
- различное сжатие (допускается толерантность в случае потери качества, например, артефакты jpeg) - вы можете принять равенство 99% равным образом, а 50% - другим.
Обновление/впечатления:
после использования этого метода некоторое время я заметил несколько улучшений, которые можно сделать
- вместо
GetPixel
для большей производительности - с помощью exeif-thumbnail вместо чтения всего изображения для улучшения производительности
- вместо того, чтобы
0.5f
отличаться между светом и тьмой - используйте среднюю яркость всех 256 пикселей. В противном случае темные/светлые изображения считаются одинаковыми, и он позволяет обнаруживать изображения с измененной яркостью. - Если вам нужны быстрые вычисления, используйте
bool[]
илиList<bool>
, если вам нужно сохранить много хэшей с необходимостью сохранения памяти, используйтеBitarray