Подтвердить что ты не робот

Проверка изображений для сходства с OpenCV

Поддерживает ли OpenCV сравнение двух изображений, возвращая некоторое значение (возможно, в процентах), которое указывает, насколько похожи эти изображения? Например, 100% будет возвращено, если одно и то же изображение было передано дважды, 0% будет возвращено, если изображения были совершенно другими.

Я уже читал много похожих тем здесь, на StackOverflow. Я также немного погуглил. К сожалению, я не смог придумать удовлетворительный ответ.

4b9b3361

Ответ 1

Это огромная тема с ответами из 3 строк кода на целые исследовательские журналы.

Я опишу наиболее распространенные такие приемы и их результаты.

Сравнение гистограмм

Один из самых простых и быстрых методов. Предложено несколько десятилетий назад как средство для поиска схожести картин. Идея состоит в том, что в лесу будет много зелени, а человеческое лицо - много розового или что-то в этом роде. Итак, если вы сравните две картинки с лесами, вы получите некоторое сходство между гистограммами, потому что у вас много зеленого цвета в обеих.

Недостаток: это слишком упрощенно. Банан и пляж будут выглядеть одинаково, так как оба желтые.

Метод OpenCV: compareHist()

Соответствие шаблона

Хорошим примером здесь matchTemplate является поиск хорошего соответствия. Это сворачивает поисковое изображение с тем, которое ищется в. Обычно используется, чтобы найти меньшие части изображения в большей.

Недостатки: он дает хорошие результаты только с идентичными изображениями, одинакового размера и ориентации.

Метод OpenCV: matchTemplate()

Соответствие функций

Считается одним из наиболее эффективных способов сделать поиск изображений. Из изображения извлекается ряд функций, что гарантирует повторное распознавание тех же объектов, даже если они повернуты, масштабированы или перекошены. Функции, извлеченные таким образом, могут быть сопоставлены с другими наборами функций изображения. Считается, что другое изображение с высокой долей признаков, соответствующих первому, изображает ту же сцену.

Поиск гомографии между двумя наборами точек позволит вам также найти относительную разницу в угле съемки между исходными снимками или величину наложения.

Об этом есть множество уроков/примеров по OpenCV, а также хорошее видео здесь. Ему посвящен целый модуль OpenCV (features2d).

Недостатки: это может быть медленно. Это не идеально.


На сайте вопросов и ответов OpenCV я говорю о разнице между дескрипторами функций, которые очень хороши при сравнении целых изображений и текстурных дескрипторов, которые используются для идентификации объектов, таких как человеческие лица или автомобили на изображении.

Ответ 2

Если для сопоставления одинаковых изображений (одинакового размера/ориентации)

// Compare two images by getting the L2 error (square-root of sum of squared error).
double getSimilarity( const Mat A, const Mat B ) {
if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) {
    // Calculate the L2 relative error between images.
    double errorL2 = norm( A, B, CV_L2 );
    // Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
    double similarity = errorL2 / (double)( A.rows * A.cols );
    return similarity;
}
else {
    //Images have a different size
    return 100000000.0;  // Return a bad value
}

Источник

Ответ 3

Решение Сэма должно быть достаточным. Я использовал комбинацию разницы в гистограмме и сопоставлении с шаблонами, потому что ни один метод не работал на меня в 100% случаев. Тем не менее, я дал меньшее значение методу гистограммы. Вот как я реализовал простой python script.

import cv2

class CompareImage(object):

    def __init__(self, image_1_path, image_2_path):
        self.minimum_commutative_image_diff = 1
        self.image_1_path = image_1_path
        self.image_2_path = image_2_path

    def compare_image(self):
        image_1 = cv2.imread(self.image_1_path, 0)
        image_2 = cv2.imread(self.image_2_path, 0)
        commutative_image_diff = self.get_image_difference(image_1, image_2)

        if commutative_image_diff < self.minimum_commutative_image_diff:
            print "Matched"
            return commutative_image_diff
        return 10000 //random failure value

    @staticmethod
    def get_image_difference(image_1, image_2):
        first_image_hist = cv2.calcHist([image_1], [0], None, [256], [0, 256])
        second_image_hist = cv2.calcHist([image_2], [0], None, [256], [0, 256])

        img_hist_diff = cv2.compareHist(first_image_hist, second_image_hist, cv2.HISTCMP_BHATTACHARYYA)
        img_template_probability_match = cv2.matchTemplate(first_image_hist, second_image_hist, cv2.TM_CCOEFF_NORMED)[0][0]
        img_template_diff = 1 - img_template_probability_match

        # taking only 10% of histogram diff, since it less accurate than template method
        commutative_image_diff = (img_hist_diff / 10) + img_template_diff
        return commutative_image_diff


    if __name__ == '__main__':
        compare_image = CompareImage('image1/path', 'image2/path')
        image_difference = compare_image.compare_image()
        print image_difference

Ответ 4

Немного от темы, но полезен подход pythonic numpy. Он прочный и быстрый, но просто сравнивает пиксели, а не объекты или данные, которые содержит изображение (и для этого требуются изображения одинакового размера и формы):

Очень простой и быстрый подход для этого без openCV и любой библиотеки для компьютерного зрения - это нормализовать массивы изображений на

import numpy as np
picture1 = np.random.rand(100,100)
picture2 = np.random.rand(100,100)
picture1_norm = picture1/np.sqrt(np.sum(picture1**2))
picture2_norm = picture2/np.sqrt(np.sum(picture2**2))

После определения как нормированных изображений (или матриц) вы можете просто суммировать умножение изображений, которые вы хотите сравнить:

1) Если вы сравниваете похожие изображения, сумма вернет 1:

In[1]: np.sum(picture1_norm**2)
Out[1]: 1.0

2) Если они не похожи, вы получите значение от 0 до 1 (процент, если умножить на 100):

In[2]: np.sum(picture2_norm*picture1_norm)
Out[2]: 0.75389941124629822

Обратите внимание, что если у вас есть цветные изображения, вы должны сделать это во всех трех измерениях или просто сравнить версию с оттенком серого. Мне часто приходится сравнивать огромное количество изображений с произвольным контентом и это очень быстрый способ сделать это.