유사성을 위해 이미지를 비교하는 간단하고 빠른 방법


192

유사성을 위해 두 이미지를 비교하는 간단하고 빠른 방법이 필요합니다. 즉, 정확히 같은 것을 포함하지만 약간 다른 배경을 가질 수 있고 몇 픽셀만큼 이동 / 크기 조정 될 수 있으면 높은 가치를 얻고 싶습니다.

(더 구체적인 경우, 하나의 그림은 아이콘이고 다른 그림은 스크린 샷의 하위 영역이며 해당 하위 영역이 정확히 아이콘인지 여부를 알고 싶습니다.)

나는 OpenCV 를 가지고 있지만 여전히 익숙하지 않습니다.

내가 지금까지 생각한 한 가지 가능성 : 두 그림을 10x10 셀로 나누고 그 100 셀 각각에 대해 색상 막대 그래프를 비교하십시오. 그런 다음 일부 구성 임계 값을 설정할 수 있으며 얻은 값이 해당 임계 값보다 높으면 비슷한 것으로 가정합니다.

나는 그것이 얼마나 잘 작동하는지 아직 시도하지 않았지만 충분할 것이라고 생각합니다. 이미지는 이미 사용 사례와 거의 비슷하므로 매우 높은 임계 값을 사용할 수 있습니다.

나는 이것에 대해 수십 가지의 다른 가능한 해결책이 있다고 생각합니다. 무엇을 제안 하시겠습니까?


이미지에서 서명 / 지문 / 해시를 얻는 것과 관련하여 몇 가지 매우 관련성이 있거나 유사한 질문이 있습니다.

또한 지문을 얻는 기능을 가진 이러한 구현을 우연히 발견했습니다.

지각 적 이미지 해시에 대한 몇 가지 토론 : here


약간의 주제 : 오디오 지문을 만드는 방법에는 여러 가지가 있습니다. 노래에 대한 지문 기반 조회를 제공하는 웹 서비스 인 MusicBrainz 는 Wiki에서 좋은 개요를 제공합니다 . 그들은 현재 AcoustID 를 사용 하고 있습니다. 일치하는 (또는 대부분 정확한) 일치를 찾기위한 것입니다. 유사한 일치 항목을 찾으려면 (또는 일부 스 니펫이나 노이즈가 높은 경우) Echoprint를 살펴 보십시오 . 관련 SO 질문이 있습니다 . 오디오에서 해결 된 것 같습니다. 이 모든 솔루션은 아주 잘 작동합니다.

퍼지 검색에 대한 일반적인 질문이 여기에 있습니다 . 예를 들어 지역에 민감한 해싱가장 가까운 이웃 검색이 있습니다.


1
이미지 지문이 도움이 될 수 있습니까? stackoverflow.com/questions/596262/…
GWW

Earth Mover 's Distance (EMD)라고도하는 Wasserstein 측정법은 사람들이 모르는 것 같지만 여기에서 원하는 것을 제공합니다.
mmgp


안녕하세요, 저는 dHash를 개선했습니다. IDHash : github.com/Nakilon/dhash-vips
Nakilon

답변:


107

스크린 샷 또는 아이콘을 변형 (확장, 회전, 기울이기 등) 할 수 있습니까? 내 머리 위에 도움이 될만한 몇 가지 방법이 있습니다.

  • @carlosdc가 언급 한 간단한 유클리드 거리 (변환 된 이미지에는 작동하지 않으며 임계 값이 필요합니다).
  • (정규화 된) 상호 상관 -이미지 영역을 비교하는 데 사용할 수있는 간단한 메트릭입니다. 단순한 유클리드 거리보다 강력하지만 변환 된 이미지에서는 작동하지 않으므로 다시 임계 값이 필요합니다.
  • 히스토그램 비교 -정규화 된 히스토그램을 사용하는 경우이 방법이 효과적이며 아핀 변환의 영향을받지 않습니다. 문제는 올바른 임계 값을 결정하는 것입니다. 또한 색상 변화 (밝기, 대비 등)에 매우 민감합니다. 이전 두 가지와 결합 할 수 있습니다.
  • MSER (Maximally Stable Extremal Regions) , SURF 또는 SIFT 와 같은 주요 지점 / 영역 탐지기 . 이것들은 매우 강력한 알고리즘이며 간단한 작업에는 너무 복잡 할 수 있습니다. 좋은 점은 아이콘이 하나만있는 정확한 영역을 가질 필요가 없다는 것입니다. 이러한 검출기는 올바른 일치를 찾을 수있을만큼 강력합니다. 이 방법의 좋은 평가는이 논문에서이다 : 지역 불변 기능 감지기 : 설문 조사 .

이들 중 대부분은 이미 OpenCV로 구현되어 있습니다 (예 : cvMatchTemplate 메소드 (히스토그램 일치 사용) 참조 : http://dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html) . 두드러진 점 / 영역 검출기도 사용할 수 있습니다 ( OpenCV 기능 감지 참조) .


1
크기를 조정하거나 약간 이동할 수 있습니다. 또한 아이콘의 배경이 달라집니다. 히스토그램 비교를 시도했지만 많은 오 탐지가있었습니다. 나는 또한 유클리드 거리를 시도했지만 너무 많은 오탐을 제공합니다 (그러나 아이콘의 알파 값을 약간 더 잘 처리 할 수 ​​있습니다). 나는 그것을 조금 더 시도 할 것이고, 그렇지 않으면 MSER, SURF 또는 SIFT를 점검 할 것입니다.
Albert

1
또 다른 아이디어-sobel 연산자를 적용한 후 이미지의 히스토그램 비교를 사용하면 작동하지 않습니까? 그것은 가장자리의 유사성을 비교할 것입니다. 배경이 얼마나 "지저분한"지에 따라 작동하거나 작동하지 않을 수 있습니다.
Karel Petranek

44

나는 최근에 같은 문제에 직면 하여이 문제 (두 이미지를 비교하는 간단하고 빠른 알고리즘)를 해결하기 위해 img_hash 모듈 을 opencv_contrib에 기여합니다 . 이 링크 에서 세부 정보를 찾을 수 있습니다 .

img_hash 모듈은 사용하기 쉬운 6 개의 이미지 해시 알고리즘을 제공합니다.

코드 예

원산지 레나원산지 레나

블레나블레나

레나 크기 조정레나 크기 조정

교대 레나교대 레나

#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는 최상의 결과를 제공합니다.

  • 가우스 블러 공격 : 0.567521
  • 시프트 어택 : 0.229728
  • 크기 조정 공격 : 0.229358

각 알고리즘의 장단점

다른 공격에서 성능

img_hash의 성능도 좋습니다

PHash 라이브러리와 속도 비교 (ukbench의 100 개 이미지) 계산 성능 비교 성능

이러한 알고리즘의 권장 임계 값을 알고 싶다면이 게시물 ( http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html )을 확인하십시오 . img_hash 모듈의 성능을 측정하는 방법 (속도 및 다른 공격 포함)에 관심이있는 경우이 링크를 확인하십시오 ( http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of -opencvimghash.html ).


11

스크린 샷에 아이콘 만 포함되어 있습니까? 그렇다면 두 이미지의 L2 거리가 충분할 수 있습니다. L2 거리가 작동하지 않으면 다음 단계는 Lucas-Kanade 와 같이 간단하고 잘 설정된 것을 시도하는 것 입니다. OpenCV에서 사용할 수있는 것은 확실합니다.


하위 영역에는 아이콘 (임의의 배경이 있음) 만 있거나 다른 것이 있습니다. 어떤 경우인지 알고 싶습니다. 비록 그것은 약간 이동되거나 크기가 조정될 수 있지만, 거리를 볼 수 있는지 (정상적으로) 확실하지 않은 이유입니다. 그러나 축소 된 버전으로 시도 할 것입니다.
Albert

6

두 그림의 유사성에 대한 인덱스를 얻으려면 SSIM 인덱스 메트릭에서 제안합니다. 인간의 눈과 더 일치합니다. 여기에 관한 기사가 있습니다 : 구조적 유사성 지수

OpenCV에서도 구현되며 GPU를 사용하여 가속화 할 수 있습니다. GPU가있는 OpenCV SSIM


5

템플릿 (아이콘)을 테스트 영역에 정확하게 맞출 수 있다면 오래된 픽셀 차이의 합이 작동합니다.

정렬이 조금만 벗어나는 경우 픽셀 차이의 합을 찾기 전에 cv :: GaussianBlur로 두 이미지를 모두 저역 통과 할 수 있습니다 .

정렬의 품질이 잠재적으로 열악한 경우 히스토그램 방향 그라디언트 또는 OpenCV의 편리한 키포인트 감지 / 설명자 알고리즘 ( SIFT 또는 SURF 등 ) 중 하나를 권장합니다 .


4

동일한 이미지를 일치시키는 경우-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
}

빠른. 그러나 조명 / 관점에서 등 변화에 강력한되지 소스


2

유사성을 위해 이미지를 비교하려면 OpenCV를 사용하는 것이 좋습니다. OpenCV에는 기능 일치 및 템플릿 일치가 거의 없습니다. 특징 매칭을 위해 SURF, SIFT, FAST 등이 있습니다. 이를 사용하여 이미지를 감지, 설명 및 일치시킬 수 있습니다. 그런 다음 특정 색인을 사용하여 두 이미지 사이의 일치 수를 찾을 수 있습니다.


1
"그 후에 특정 인덱스를 사용하여 두 이미지 사이의 일치 수를 찾을 수 있습니다." 두 이미지 사이에서 일치하는 최소 개수는 무엇입니까?
Inês Martins
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.