Método simple y rápido para comparar imágenes por similitud


Necesito una forma sencilla y rápida de comparar dos imágenes por similitud. Es decir, quiero obtener un valor alto si contienen exactamente lo mismo, pero pueden tener un fondo ligeramente diferente y pueden ser movidos / redimensionados por unos pocos píxeles.

(Más concreto, si eso importa: Una imagen es un icono y la otra imagen es una subárea de una captura de pantalla y quiero saber si esa subárea es exactamente el icono o no.)

Tengo OpenCV a mano pero todavía no estoy acostumbrado a se.

Una posibilidad que he pensado hasta ahora: Dividir ambas imágenes en celdas de 10x10 y para cada una de esas 100 celdas, comparar el histograma de color. Entonces puedo establecer algún valor de umbral compuesto y si el valor que obtengo está por encima de ese umbral, asumo que son similares.

Todavía no lo he probado lo bien que funciona, pero supongo que sería lo suficientemente bueno. Las imágenes ya son bastante similares (en mi caso de uso), por lo que puedo usar un valor de umbral bastante alto.

Supongo hay docenas de otras posibles soluciones para esto que funcionarían más o menos (ya que la tarea en sí es bastante simple ya que solo quiero detectar similitud si son realmente muy similares). ¿Qué sugieres?


Hay algunas preguntas muy relacionadas / similares sobre cómo obtener una firma / huella digital / hash de una imagen:

También, me topé con estas implementaciones que tienen tales funciones para obtener un huella digital:

Algunos discusiones sobre hashes de imagen perceptual: aquí


Un poco fuera de tema: Existen muchos métodos para crear huellas digitales de audio. MusicBrainz , un servicio web que proporciona búsquedas basadas en huellas dactilares para canciones, tiene una buena visión general en su wiki . Ahora están usandoAcoustID . Esto es para encontrar coincidencias exactas (o casi exactas). Para encontrar coincidencias similares (o si solo tiene algunos fragmentos o alto ruido), eche un vistazo a Echoprint. Una pregunta relacionada con SO es aquí . Así que parece que esto se resuelve para el audio. Todas estas soluciones funcionan bastante bien.

Una pregunta algo más genérica sobre la búsqueda difusa en general es aquí. Por ejemplo, existe hashing sensible a la localidad y búsqueda de vecinos más cercanos.

Author: Albert, 2010-11-16

7 answers

Se puede transformar la captura de pantalla o el icono (escalar, girar, sesgar)...)? Hay un buen número de métodos en la parte superior de mi cabeza que posiblemente podría ayudarle:

  • Distancia euclidiana simple como menciona @carlosdc (no funciona con imágenes transformadas y necesita un umbral).
  • (Normalizado) Correlación Cruzada - una métrica simple que puede usar para comparar áreas de imagen. Es más robusta que la simple distancia euclidiana, pero no trabaje en imágenes transformadas y nuevamente necesitará un umbral.
  • Comparación de histogramas - si utiliza histogramas normalizados, este método funciona bien y no se ve afectado por transformaciones afines. El problema es determinar el umbral correcto. También es muy sensible a los cambios de color(brillo, contraste, etc.). Puedes combinarlo con los dos anteriores.
  • Detectores de puntos/áreas salientes - tales como MSER (Regiones Extremales de máxima Estabilidad), SURF o TAMIZAR. Estos son algoritmos muy robustos y pueden ser demasiado complicados para su tarea simple. Lo bueno es que usted no tiene que tener un área exacta con un solo icono, estos detectores son lo suficientemente potentes para encontrar la coincidencia correcta. Una buena evaluación de estos métodos está en este documento: Detectores de características invariantes locales: un estudio.

La mayoría de estos ya están implementados en OpenCV-ver por ejemplo el método cvMatchTemplate (usa histograma coincidente): http://dasl.mem.drexel.edu / ~noahKuntz/openCVTut6.html. Los detectores de puntos/áreas salientes también están disponibles - ver Detección de características OpenCV.

 93
Author: Karel Petranek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-17 09:59:36

Me enfrento a los mismos problemas recientemente, para resolver este problema(algoritmo simple y rápido para comparar dos imágenes) de una vez por todas, contribuyo con un módulo img_hash a opencv_contrib, puede encontrar los detalles en este enlace.

El módulo Img_hash proporciona seis algoritmos hash de imagen, bastante fáciles de usar.

Ejemplo de códigos

origen lenaorigen lena

blur lenablur lena

cambiar el tamaño de lenaredimensionar lena

cambio lenashift lena

#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));
}

En este caso, ColorMomentHash nos dan el mejor resultado

  • ataque de desenfoque gaussiano: 0.567521
  • shift attack: 0.229728
  • redimensionar ataque: 0.229358

Pros y contras de cada algoritmo

Rendimiento bajo diferentes ataques

El rendimiento de img_hash también es bueno

Comparación de velocidad con la biblioteca PHash (100 imágenes de ukbench) rendimiento de cómputo rendimiento de la comparación

Si desea conocer los umbrales recomendados para estos algoritmos, consulte este post ( http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html). Si te interesa saber cómo mido el rendimiento de los módulos img_hash(incluye velocidad y diferentes ataques), por favor comprueba esto link(http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of-opencvimghash.html).

 33
Author: StereoMatching,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-27 14:25:25

¿La captura de pantalla contiene solo el icono? Si es así, la distancia L2 de las dos imágenes podría ser suficiente. Si la distancia L2 no funciona, el siguiente paso es probar algo simple y bien establecido, como: Lucas-Kanade. Que estoy seguro que está disponible en OpenCV.

 8
Author: carlosdc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-16 23:19:06

Si puede estar seguro de tener una alineación precisa de su plantilla (el icono) con la región de prueba, entonces cualquier suma antigua de diferencias de píxeles funcionará.

Si la alineación solo va a estar un poco apagada, entonces puede pasar ambas imágenes con cv::GaussianBlur antes de encontrar la suma de diferencias de píxeles.

Si la calidad de la alineación es potencialmente pobre, entonces recomendaría un Histograma de Gradientes Orientados o uno de los convenientes de OpenCV algoritmos de detección de puntos clave/descriptores (como SIFTo SURF).

 4
Author: rcv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-17 23:28:02

Si desea obtener un índice sobre la similitud de las dos imágenes, le sugiero que de las métricas el índice SSIM. Es más consistente con el ojo humano. Aquí hay un artículo sobre esto: Índice de Similitud Estructural

También se implementa en OpenCV, y se puede acelerar con GPU: OpenCV SSIM con GPU

 4
Author: ramez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-12 16:49:00

Si para la coincidencia de imágenes idénticas-código para L2 distancia

// 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
}

Rápido. Pero no robusto a los cambios en la iluminación / punto de vista, etc. Fuente

 3
Author: Kiran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-04 08:28:09

Si desea comparar la imagen por similitud,le sugiero que utilice OpenCV. En OpenCV, hay pocas coincidencias de características y plantillas. Para la coincidencia de características, hay SURF, TAMIZ, detector RÁPIDO y así sucesivamente. Puede usar esto para detectar, describir y luego hacer coincidir la imagen. Después de eso, puede usar el índice específico para encontrar el número de coincidencia entre las dos imágenes.

 2
Author: Hua Er Lim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-19 05:17:24