Простой и быстрый способ сравнения изображений на сходство
Мне нужен простой и быстрый способ сравнить два изображения для сходства. Т. е. я хочу получить высокое значение, если они содержат точно то же самое, но могут иметь немного другой фон и могут быть перемещены / изменены на несколько пикселей.
(более конкретно, если это имеет значение: одно изображение-это значок, а другое изображение-это подзона скриншота, и я хочу знать, является ли эта подзона именно значком или нет.)
У меня есть OpenCV под рукой, но я все еще не привыкла к этому.
одна возможность, о которой я думал до сих пор: разделите оба изображения на ячейки 10x10 и для каждой из этих 100 ячеек сравните цветовую гистограмму. Затем я могу установить некоторое пороговое значение, и если значение, которое я получаю, выше этого порога, я предполагаю, что они похожи.
Я еще не пробовал, насколько хорошо это работает, но я думаю, что это было бы достаточно хорошо. Изображения уже очень похожи (в моем случае использования), поэтому я могу использовать довольно высокий пороговое значение.
Я думаю, что есть десятки других возможных решений для этого, которые будут работать более или менее (поскольку сама задача довольно проста, поскольку я хочу только обнаружить сходство, если они действительно очень похожи). Что бы вы предложили?
есть несколько очень связанных / похожих вопросов о получении подписи / отпечатка пальца/хэша из изображения:
- OpenCV / SURF как создать хэш изображения / отпечаток пальца / подпись из дескрипторы?
- изображение отпечатка пальца для сравнения сходства многих изображений
- Обнаружение Почти Повторяющихся Изображений
OpenCV: изображение отпечатков пальцев и сравнение с базой данных.
больше больше больше,больше, больше, больше
кроме того, я наткнулась на эти реализации, которые имеют такие функции, чтобы получить отпечаток пальца:
- pHash
imgSeek (GitHub repo) (GPL) на основе бумаги Быстрый Запрос Изображения С Несколькими Разрешениями
изображения-матч. Очень похоже на то, что я искал. Похоже на pHash, основанный на подпись изображения для любого вида изображения, Goldberg et al. Использует Python и Elasticsearch.- iqdb
ImageHash. поддерживает pHash.
некоторые дискуссии о перцептивных хэшах изображений:здесь
немного offtopic: существует много методов для создания звуковых отпечатков пальцев. MusicBrainz, веб-сервис, который обеспечивает поиск по отпечаткам пальцев для песен, имеет хороший обзор в вики. Они используют AcoustID сейчас. Это для поиска точных (или в основном точных) совпадений. Для поиска похожих совпадений (или если у вас есть только некоторые фрагменты или высокий шум), взгляните на Echoprint. Связанный с этим вопрос здесь. Так что, похоже, это решено для аудио. Все эти решения работают достаточно хорошо.
здесь несколько более общий вопрос о нечетком поиске в целом. Например, есть город-чувствительного хеширования и ближайший сосед поиск.
7 ответов:
можно ли преобразовать скриншот или значок (масштабирование, поворот, перекос ...)? Есть довольно много методов на моей голове, которые могли бы помочь вам:
- простое евклидово расстояние как упоминалось @carlosdc (не работает с преобразованными изображениями, и вам нужен порог).
- (Нормализованная) Взаимная Корреляция - простая метрика, которую вы можете использовать для сравнения областей изображения. Это более надежный, чем простое евклидово расстояние, но не работает на преобразованных изображениях, и вам снова понадобится порог.
- сравнительная гистограмма - если вы используете нормализованные гистограммы, этот метод работает хорошо и не зависит от аффинных преобразований. Проблема заключается в определении правильного порога. Это также очень чувствительны к изменения цвета (яркость, контрастность и т. д.). Вы можете объединить его с предыдущими двумя.
- детекторы заметных точек / областей - таких, как MSER (максимально стабильные экстремальные области),SURF или просеять. Это очень надежные алгоритмы и они могут быть слишком сложны для простых задач. Хорошо, что вам не нужно иметь точную область только с одним значком, эти детекторы достаточно мощные, чтобы найти правильное совпадение. Хорошая оценка этих методов находится в этой статье:локальные инвариантные детекторы признаков: опрос.
большинство из них уже реализовано в OpenCV-см. например метод cvMatchTemplate (использует сопоставление гистограмм):http://dasl.mem.drexel.edu / ~noahKuntz/openCVTut6.html. также доступны детекторы заметных точек/областей-см. Обнаружение Функции OpenCV.
я сталкиваюсь с теми же проблемами в последнее время, чтобы решить эту проблему(простой и быстрый алгоритм для сравнения двух изображений) раз и навсегда, я вношу модуль img_hash к opencv_contrib, вы можете найти детали от этой ссылке.
модуль img_hash предоставляет шесть алгоритмов хэширования изображений, довольно простых в использовании.
пример коды
#include <opencv2/core.hpp> #include <opencv2/core/ocl.hpp> #include <opencv2/highgui.hpp> #include <opencv2/img_hash.hpp> #include <opencv2/imgproc.hpp> #include <iostream> void compute(cv::Ptr<cv::img_hash::ImgHashBase> algo) { auto input = cv::imread("lena.png"); cv::Mat similar_img; //detect similiar image after blur attack cv::GaussianBlur(input, similar_img, {7,7}, 2, 2); cv::imwrite("lena_blur.png", similar_img); cv::Mat hash_input, hash_similar; algo->compute(input, hash_input); algo->compute(similar_img, hash_similar); std::cout<<"gaussian blur attack : "<< algo->compare(hash_input, hash_similar)<<std::endl; //detect similar image after shift attack similar_img.setTo(0); input(cv::Rect(0,10, input.cols,input.rows-10)). copyTo(similar_img(cv::Rect(0,0,input.cols,input.rows-10))); cv::imwrite("lena_shift.png", similar_img); algo->compute(similar_img, hash_similar); std::cout<<"shift attack : "<< algo->compare(hash_input, hash_similar)<<std::endl; //detect similar image after resize cv::resize(input, similar_img, {120, 40}); cv::imwrite("lena_resize.png", similar_img); algo->compute(similar_img, hash_similar); std::cout<<"resize attack : "<< algo->compare(hash_input, hash_similar)<<std::endl; } int main() { using namespace cv::img_hash; //disable opencl acceleration may(or may not) boost up speed of img_hash cv::ocl::setUseOpenCL(false); //if the value after compare <= 8, that means the images //very similar to each other compute(ColorMomentHash::create()); //there are other algorithms you can try out //every algorithms have their pros and cons compute(AverageHash::create()); compute(PHash::create()); compute(MarrHildrethHash::create()); compute(RadialVarianceHash::create()); //BlockMeanHash support mode 0 and mode 1, they associate to //mode 1 and mode 2 of PHash library compute(BlockMeanHash::create(0)); compute(BlockMeanHash::create(1)); }в этом случае ColorMomentHash даст нам лучший результат
- gaussian blur attack: 0.567521
- shift attack: 0.229728
- изменение размера атаки: 0.229358
плюсы и минусы каждого алгоритма
производительность img_hash тоже хорош
сравнение скорости с библиотекой PHash (100 изображений из ukbench)
![]()
Если вы хотите знать рекомендуемые пороги для этих алгоритмов, пожалуйста, проверьте это post(http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html). Если вам интересно, как я могу измерить производительность модулей img_hash(включая скорость и различные атаки), пожалуйста, проверьте это link(http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of-opencvimghash.html).
содержит ли скриншот только значок? Если это так, то расстояния L2 двух изображений может быть достаточно. Если расстояние L2 не работает, следующий шаг-попробовать что-то простое и хорошо установленное, например: Лукаса-Канаде. Который, я уверен, доступен в OpenCV.
Если вы можете быть уверены, что точное выравнивание вашего шаблона (значок) в области тестирования, то любая старая сумма различий пикселей будет работать.
Если выравнивание будет только немного выключено, то вы можете низко пропускать оба изображения с cv:: GaussianBlur прежде чем найти сумму пиксельных различий.
Если качество выравнивания потенциально плохое, то я бы рекомендовал либо a гистограмма ориентированных градиентов или один удобных алгоритмов обнаружения/дескриптора ключевых точек OpenCV (таких как просеять или SURF).
Если вы хотите получить индекс о сходстве двух изображений, я предлагаю вам из метрики индекс SSIM. Это больше соответствует человеческому глазу. Вот статья об этом: Индекс Структурного Сходства
Он также реализован в OpenCV, и его можно ускорить с помощью GPU:OpenCV SSIM с GPU
Если для сопоставления идентичных изображений-код для расстояния L2
// 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 }быстро. Но не робастно к изменениям в освещении / точке зрения etc. источник
Если вы хотите сравнить изображение для сходства, я предлагаю вам использовать OpenCV. В OpenCV существует несколько сопоставлений функций и шаблонов. Для соответствовать характеристики, прибой, просеивает, быстрый и так далее детектор. Вы можете использовать это, чтобы обнаружить, описать и затем соответствовать образу. После этого, вы можете использовать определенный индекс, чтобы найти количество совпадений между двумя изображениями.







Comments