2010-11-16 98 views
150

我需要一個簡單而快速的方法來比較兩個圖像的相似性。即如果它們包含完全相同的東西,但是可能會有一些稍微不同的背景,並且可能會被幾個像素移動/調整大小,我希望獲得較高的值。簡單而快速的方法來比較圖像的相似性

(更具體的,如果該事項:在一個畫面是一個圖標,另一個畫面截圖的分區,我想知道這是否分區是完全圖標或沒有。)

我有OpenCV在手邊,但我仍然不習慣它。我想過到目前爲止

一種可能性:既劃分成照片10×10細胞,併爲每個100個細胞,對比顏色直方圖。然後我可以設置一些補償閾值,如果我得到的值高於該閾值,我認爲它們是相似的。

我還沒有嘗試過,但它的工作狀況如何,但我想它會足夠好。圖像已經非常相似(在我的用例中),所以我可以使用相當高的閾值。

我想有許多其他可能的解決方案,這其中會工作或多或少(如任務本身是很簡單的,我只是想檢測的相似性,如果他們真的很相似)。你會建議什麼?


有大約從圖像獲取簽名/指紋/哈希幾個非常相關的/類似的問題:

另外,我偶然發現了這些實現方式中,其具有這樣的功能,以獲得指紋:

約感知圖像哈希一些討論:here


有點offtopic:存在許多方法來創建音頻指紋。 MusicBrainz是一種爲歌曲提供基於指紋的查詢的網絡服務,它有一個good overview in their wiki。他們現在使用AcoustID。這是爲了找到確切的(或者大多數確切的)匹配。爲了找到相似的匹配(或者如果你只有一些片段或高噪音),看看Echoprint。一個相關的SO問題是here。所以這似乎解決了音頻。所有這些解決方案都很好。

關於模糊搜索的一般性問題是here。例如。有locality-sensitive hashingnearest neighbor search

+1

也許圖像指紋可以幫助嗎? HTTP://計算器。com/questions/596262/image-fingerprint-to-compare-similar-of-many-images – GWW 2010-11-16 16:43:21

+0

Wasserstein指標,也被稱爲Earth Mover's Distance(EMD),是人們似乎不知道的東西,但會給出很多你想在這裏。 – mmgp 2013-01-14 14:06:25

+2

[圖像比較 - 快速算法]的可能重複(http://stackoverflow.com/questions/843972/image-comparison-fast-algorithm) – sashoalm 2013-10-23 06:23:53

回答

86

屏幕截圖或圖標是否可以轉換(縮放,旋轉,傾斜...)?還有我的頭頂部有不少的方法,可以幫助可能你:

  • 由@carlosdc提到的(不變換圖像的工作,你需要一個閾值),簡單的歐氏距離
  • (Normalized) Cross Correlation - 一個簡單的指標,你可以用它來比較圖像區域。它比簡單的歐幾里德距離更加穩健,但不適用於轉換後的圖像,並且您將再次需要閾值。
  • 直方圖比較 - 如果使用標準化的直方圖,此方法運行良好,不受仿射變換的影響。問題是確定正確的閾值。它也對顏色變化(亮度,對比度等)非常敏感。你可以把它和前兩個結合起來。
  • 檢測器的顯着點/區域 - 如MSER (Maximally Stable Extremal Regions),SURFSIFT。這些算法非常強大,對於您的簡單任務來說它們可能太複雜。好的是,你不必擁有一個只有一個圖標的確切區域,這些探測器足夠強大,可以找到正確的匹配。本文對這些方法進行了很好的評估:Local invariant feature detectors: a survey

其中大多數已經在OpenCV中實現 - 例如參見cvMatchTemplate方法(使用直方圖匹配):http://dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html。顯着點/區域檢測器也可用 - 請參見OpenCV Feature Detection

+1

它可以縮放或輕微移動。此外,圖標的背景也會有所不同。我嘗試了直方圖比較,但我得到了很多誤報。我也嘗試了歐幾里德距離,但是這也會帶來太多的誤報(但也許我可以更好地處理圖標中的alpha值)。我會進一步嘗試,否則我會檢查出MSER,SURF或SIFT。 – Albert 2010-11-17 15:09:31

+0

另一個想法 - 如果在應用sobel算子之後對圖像進行直方圖比較,它會不會奏效?那隻會比較邊緣的相似性。取決於背景的「前衛」,可能或可能不起作用。 – 2010-11-17 17:32:24

8

屏幕截圖是否只包含圖標?如果是這樣,那麼這兩個圖像的L2距離就足夠了。如果L2距離不起作用,下一步就是嘗試一些簡單且完善的方法,如:Lucas-Kanade。我確信在OpenCV中可以找到它。

+0

分區包含完全只有圖標(有一些隨機背景)或不同的東西。我想看看它是哪種情況。雖然它可能會稍微移動或調整大小,這就是爲什麼我不確定我是否可以只看遠處(以任何規範)。但我會嘗試縮小版本。 – Albert 2010-11-16 22:23:24

3

如果您可以確保模板(圖標)與測試區域精確對齊,那麼任何舊的像素差異總和都可以使用。

如果對齊只會稍微偏離一點,那麼在找到像素差異總和之前,您可以用cv::GaussianBlur低通兩個圖像。

如果校準的質量可能不好然後我建議無論是Histogram of Oriented Gradients或的OpenCV的便利關鍵點檢測/描述符算法(如SIFTSURF)之一。

2

如果你想比較圖像的相似性,我建議你使用OpenCV。在OpenCV中,很少有功能匹配和模板匹配。對於特徵匹配,有SURF,SIFT,FAST等檢測器。您可以使用它來檢測,描述並匹配圖像。之後,您可以使用特定索引查找兩張圖像之間的匹配數量。

+0

你說過「之後,你可以使用特定的索引來查找兩張圖片之間的匹配數量。」兩幅圖像之間的最小匹配數是多少,以表示它們「包含」同一個對象? – 2015-11-03 11:44:48

4

如果你想得到一個有關這兩張圖片相似度的指標,我建議你從SSIM指數的指標。它更符合人眼。下面是一個關於它的文章:Structural Similarity Index

它在OpenCV中實現太,和它可與GPU來加速:OpenCV SSIM with GPU

3

如果匹配的相同的圖像 - 代碼爲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 
} 

快速。但不穩健的照明/觀點等 Source

26

改變我最近面臨着同樣的問題,要解決這個問題(簡單而快速的算法來比較兩個圖像)一勞永逸,我貢獻了img_hash module到opencv_contrib,你可以從this link找到詳細信息。

img_hash模塊提供了六個圖像哈希算法,相當容易使用。

代碼示例

origin lena原點海倫

blur lena模糊海倫

resize lena調整大小海倫

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

在這種情況下,ColorMomentHash給我們最好的結果

  • 高斯模糊攻擊:0.567521
  • 移攻擊:0.229728
  • 調整大小的攻擊:0.229358

優點和每種算法的利弊

Performance under different attacks

img_hash的表現也很好

與PHash庫(從ukbench 100個圖像) compute performance comparison performance

如果你想知道的建議閾值這些算法的速度對比,請檢查這篇文章(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)。

+2

感謝您的好評。你能告訴我們速度比較的來源嗎? – ocolot 2016-08-04 12:20:32

+2

@ocolot當然,我讓這個帖子中的鏈接更加明顯,只需點擊它們,你就會找到你的答案。我正在開發基於此模塊的應用程序,未來我也會支持視頻指紋 – StereoMatching 2016-08-05 06:59:00