Сравните алгоритмы сходства изображений

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

Обзор

Как правило, существует три типа алгоритмов подобия изображений.

  • Алгоритм среднего хеширования
  • Алгоритм хеширования значения разницы
  • Алгоритм перцептивного хеширования

На самом деле, эти три алгоритма похожи.В качестве примера возьмем алгоритм среднего хеширования.Этапы алгоритма следующие:

  1. Изображение масштабировано до n*n
  2. Обесцветить, получить изображение в градациях серого
  3. получить хеш-отпечаток
  4. Сравните расстояние Хэмминга отпечатков хеша, чтобы получить значение сходства.

Разница между вышеперечисленными алгоритмами в основном связана с разными алгоритмами получения хэш-отпечатков.

Алгоритм среднего хеширования

Поясним на примере, исходное изображение выглядит следующим образом:

Изображение увеличено до 8*8.

Код:

img = cv2.resize(img, (8, 8), interpolation=cv2.INTER_CUBIC)

масштабировать результаты

раскрасить

код

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

результат:

Рассчитать среднее значение серого

    # 计算灰度平均值
    for i in range(8):
        for j in range(8):
            s = s + gray_img[i, j]
    avg = s / 64

Результат расчета 176

Рассчитать отпечаток хэша

Метод расчета: если значение серого точки больше среднего значения серого, это 1, иначе 0, код выглядит следующим образом:

    # 如果值大于灰度值, 则为1, 否则为0. 生成hash指纹
    for i in range(8):
        for j in range(8):
            if gray_img[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'

Рассчитать расстояние Хэмминга

Расстояние Хэмминга: в теории информации расстояние Хэмминга между двумя строками одинаковой длины — это количество различных символов в соответствующих позициях двух строк. Код:

def cmp_hash(hash_1, hash_2):
    # 计算汉明距离
    n = 0
    if len(hash_1) != len(hash_2):
        return -1
    for i in range(len(hash_1)):
        if hash_1[i] != hash_2[i]:
            n = n + 1
    return n

Алгоритм хеширования значения разницы

Предыдущее вычисление масштабирования, серого цвета и расстояния Хэмминга такое же, как и у среднего алгоритма хеширования, разница в том, что алгоритм вычисления хэш-отпечатка отличается. Алгоритм здесь таков: если значение серого предыдущего пикселя больше, чем значение серого следующего пикселя, оно равно 1, иначе оно равно 0. Полный алгоритм выглядит следующим образом:

# 差值感应hash
def b_hash(img):
    # 缩放到8*8的图片
    img = cv2.resize(img, (9, 8), interpolation=cv2.INTER_CUBIC)
    # 得到灰度图
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    hash_str = ''
    # 如果前一个像素比后一个大, 则为1, 否则为0. 生成hash指纹
    for i in range(8):
        for j in range(8):
            if gray_img[i, j] > gray_img[i, j + 1]:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str

Алгоритм перцептивного хеширования

Первые два алгоритма, которые сравнивают похожие изображения, просты для понимания, идея алгоритма индукционного хеширования отличается. Давайте посмотрим на изображение под другим углом. Изображение на самом деле представляет собой двухмерную информационную карту с различными частотными изменениями. Высокая частота представляет собой более крупное преобразование цвета, такое как контурная часть. Мы можем использовать преобразование DCT (дискретное косинусное преобразование ), чтобы получить карту частотной области Сравните низкочастотные части (зачем сравнивать низкочастотные части?) Достаточно ли они похожи.

Исходное изображение по-прежнему является исходным изображением выше. Давайте увеличим и уменьшим масштаб до части 32 * 32.

Обработка оттенков серого

Выполнить преобразование DCT

Мы получаем область 8 * 8 в верхнем левом углу и сравниваем расстояние Хэмминга этого изображения в градациях серого в соответствии с алгоритмом среднего хеширования.

Полный код выглядит следующим образом:

# 感知hash
def p_hash(img):
    # 缩放到32 * 32
    img = cv2.resize(img, (32, 32), interpolation=cv2.INTER_CUBIC)
    cv2.imwrite("bb.jpg", img)
    # 得到灰度图
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray_img = gray_img.astype(np.float32)
    cv2.imwrite("cc.jpg", gray_img)

    # 进行离散余弦变换, 目的是将低频部分放到左上角
    img = cv2.dct(gray_img)
    cv2.imwrite("dd.jpg", img)
    # 得到左上角8*8 的频率图
    img = img[0:8, 0:8]
    avg = 0
    # 与得到低频图的平均灰度
    hash_str = ''
    for i in range(8):
        for j in range(8):
            avg += img[i, j]
    avg = avg / 64

    # 如果低频图的像素值大于平均灰度, 则为1, 否则为0. 依次生成hash指纹
    for i in range(8):
        for j in range(8):
            if img[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str