Средний хеш, реализованный поиском по графу

Идентификация изображения

предисловие

Недавно я обнаружил функцию поиска изображений на Таобао, когда делал покупки на Таобао.Может быть, я слишком низкий.Этот технический момент реализован давно. Я думал над тем, смогу ли я реализовать эту функцию.Сначала я так и думал.Сравните две картинки от первого пикселя в верхнем левом углу до последнего пикселя в нижнем правом углу, и зафиксируйте их сходство при сравнении.Возможно быть, я слишком наивен (в основном знания ограничивают воображение), при этом возникает много проблем, например, размеры двух картинок несовместимы, положение основных элементов различно и т. д. В конце концов, у меня было Прибегнуть к помощи интернета и нашел метод под названием Алгоритм среднего хеширования (Average hash algorithm), а затем разработать его основные идеи и применимые сценарии.

Основная идея среднего хэша

1. Уменьшите размер:

Самый быстрый способ удалить из изображения высокие частоты и детали — уменьшить изображение до размера 8x8, что в сумме дает 64 пикселя. Не сохраняйте соотношение сторон, просто сделайте квадрат 8 на 8. Таким образом, можно сравнивать изображения любого размера и отбрасывать различия изображений, вызванные разными размерами и пропорциями.

2. Упростите цвета:

Преобразуйте небольшое изображение 8 на 8 в изображение в градациях серого.

3. Рассчитайте среднее значение:

Вычислите среднее значение оттенков серого для всех 64 пикселей.

4. Сравните оттенки серого пикселей:

Сравните оттенки серого каждого пикселя со средним значением. Если оно больше или равно среднему значению, оно записывается как 1, если оно меньше среднего значения, оно записывается как 0.

5. Рассчитайте хеш-значение:

Результаты сравнения предыдущего шага объединяются для формирования 64-битного целого числа, которое является отпечатком этого изображения. Порядок композиции не важен, просто убедитесь, что все изображения расположены в одном порядке.

При увеличении или уменьшении изображения или изменении соотношения сторон результирующее значение не изменится. Увеличение или уменьшение яркости или контрастности или изменение цвета не окажет большого влияния на значение хеш-функции. Самое большое преимущество: скорость расчета высокая!

После выполнения вышеуказанных шагов изображение эквивалентно наличию собственного «отпечатка пальца», а затем вычисляется количество различных битов, которое является расстоянием Хэмминга (например, пример Хэмминга 1010001 и 1011101 равен 2, что отличается номер).

Если расстояние Хэмминга меньше 5, то это означает несколько иную, но относительно похожую картину, а если расстояние Хэмминга больше 10, то это означает совсем другую картину.

Выше приведена основная идея реализации среднего хэша, которая в целом относительно проста.

Реализация С#

public class ImageHashHelper
{
    /// <summary>
    /// 获取缩略图
    /// </summary>
    /// <returns></returns>
    private static Bitmap GetThumbImage(Image image, int w, int h)
    {
        Bitmap bitmap = new Bitmap(w, h);
        Graphics g = Graphics.FromImage(bitmap);
        g.DrawImage(image,
            new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);
        return bitmap;
    }

    /// <summary>
    /// 将图片转换为灰度图像
    /// </summary>
    /// <returns></returns>
    private static Bitmap ToGray(Bitmap bmp)
    {
        for (int i = 0; i < bmp.Width; i++)
        {
            for (int j = 0; j < bmp.Height; j++)
            {
                //获取该点的像素的RGB的颜色
                Color color = bmp.GetPixel(i, j);
                //利用公式计算灰度值
                int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);//计算方式1
                //int gray1 = (int)((color.R + color.G + color.B) / 3.0M);//计算方式2
                Color newColor = Color.FromArgb(gray, gray, gray);
                bmp.SetPixel(i, j, newColor);
            }
        }
        return bmp;
    }

    /// <summary>
    /// 获取图片的均值哈希
    /// </summary>
    /// <returns></returns>
    public static int[] GetAvgHash(Bitmap bitmap)
    {
        Bitmap newBitmap = ToGray(GetThumbImage(bitmap, 8, 8));
        int[] code = new int[64];
        //计算所有64个像素的灰度平均值。
        List<int> allGray = new List<int>();
        for (int row = 0; row < bitmap.Width; row++)
        {
            for (int col = 0; col < bitmap.Height; col++)
            {
                allGray.Add(newBitmap.GetPixel(row, col).R);
            }
        }
        double avg = allGray.Average(a => a);//拿到平均值
        //比较像素的灰度
        for (int i = 0; i < allGray.Count; i++)
        {
            code[i] = allGray[i] >= avg ? 1 : 0;//将比较结果进行组合
        }
        //返回结果
        return code;
    }

    /// <summary>
    /// 对两个AvgHash进行比较
    /// </summary>
    /// <returns></returns>
    public static int Compare(int[] code1, int[] code2)
    {
        int v = 0;
        for (int i = 0; i < 64; i++)
        {
            if (code1[i] == code2[i])
            {
                v++;
            }
        }
        return v;
    }
}

Здесь мы получаем значение серого в 64 пикселя напрямую через R в функции GetAvgHash, потому что RGB один и тот же, поэтому можно использовать любой.

Преобразование значения серого:baike.baidu.com/item/grayscale/10…

Демонстрация эффекта:

1. Поиск исходного изображения

2. Полный поиск мозаики

Загрузка исходного кода:

Нажмите, чтобы загрузить исходный код

Наконец

Среднее хеширование подходит для эскизов, чтобы найти оригинальные изображения, сопоставление людей и т. д. не подходит.

использованная литература:

woohoo.hackerfactor.com/blog/index. …