web-dev-qa-db-ja.com

OpenCVとの類似性について画像を確認する

OpenCVは2つの画像の比較をサポートしており、これらの画像がどれほど似ているかを示す何らかの値(おそらくパーセンテージ)を返しますか?例えば。同じ画像が2回渡された場合は100%が返され、画像がまったく異なる場合は0%が返されます。

StackOverflowについては、すでに多くの同様のトピックを読んでいます。私もかなりのグーグルをしました。悲しいことに、私は満足のいく答えを思い付くことができませんでした。

126
Boris

これは巨大なトピックであり、3行のコードから研究雑誌全体への回答があります。

最も一般的なこのような手法とその結果の概要を説明します。

ヒストグラムの比較

最も単純で最速の方法の1つ。写真の類似性を見つける手段として数十年前に提案されました。考えは、森にはたくさんの緑があり、人間の顔にはたくさんのピンク、または何でもあるということです。そのため、2つの写真を森林と比較すると、両方のヒストグラムに多くの緑があるため、ヒストグラム間である程度の類似性が得られます。

欠点:あまりにも単純すぎる。バナナとビーチは両方とも黄色なので、同じように見えます。

OpenCVメソッド:compareHist()

テンプレートマッチング

ここの良い例 matchTemplateが適切な一致を見つける 。検索画像と検索対象の画像を畳み込みます。通常、大きな画像部分で小さな画像部分を見つけるために使用されます。

欠点:同じ画像、同じサイズ、同じ向きでのみ良い結果を返します。

OpenCVメソッド:matchTemplate()

機能マッチング

画像検索を行う最も効率的な方法の1つと考えられています。画像からいくつかの特徴が抽出され、回転、拡大縮小、傾斜した場合でも同じ特徴が再び認識されるようになります。この方法で抽出された特徴は、他の画像特徴セットと照合できます。最初の画像と一致する特徴の割合が高い別の画像は、同じシーンを描いていると見なされます。

2セットのポイント間のホモグラフィを見つけることで、元の画像間の撮影角度の相対的な差や重なりの量も見つけることができます。

これに関するOpenCVチュートリアル/サンプルが多数あり、素敵なビデオ こちら があります。 OpenCVモジュール全体(features2d)が専用です。

欠点:遅いかもしれません。完璧ではありません。


OpenCV Q&A サイトで、画像全体と画像内の人間の顔や車などのオブジェクトを識別するために使用されるテクスチャ記述子を比較する場合に素晴らしい特徴記述子の違いについて話しています。

186
Sam

一致する同一の画像の場合(同じサイズ/向き)

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

ソース

30
Kiran

サムのソリューションで十分なはずです。ヒストグラムの差分とテンプレートマッチングの両方を組み合わせて使用​​したのは、100%の時間に1つのメソッドが機能していなかったためです。ただし、ヒストグラム法はそれほど重要ではありません。以下に、簡単なpythonスクリプトで実装した方法を示します。

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's less accurate than template method
        commutative_image_diff = (img_hist_diff / 10) + img_template_diff
        return commutative_image_diff


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