OpenCV ile benzer iki görüntünün nasıl olduğunu nasıl değerlendirebilirim?


141

OpenCV, bu görüntülerin ne kadar benzer olduğunu gösteren bir değer (belki bir yüzde) döndürerek iki görüntünün karşılaştırılmasını destekliyor mu? Aynı görüntü iki kez geçirilirse% 100, görüntüler tamamen farklıysa% 0 döndürülür.

StackOverflow'da zaten birçok benzer konuyu okudum. Ayrıca oldukça Googling yaptım. Ne yazık ki tatmin edici bir cevap bulamadım.


Yanıtlar:


208

Bu, 3 satır koddan tüm araştırma dergilerine cevap veren büyük bir konudur.

Bu tür teknikleri ve sonuçlarını en yaygın şekilde anlatacağım.

Histogramları karşılaştırma

En basit ve en hızlı yöntemlerden biri. On yıllar önce resim benzerliklerini bulmanın bir yolu olarak önerildi. Fikir şu ki, bir orman çok yeşil olacak ve bir insan yüzü çok pembe ya da her neyse. Yani, iki resmi ormanlarla karşılaştırırsanız, histogramlar arasında bir miktar benzerlik elde edersiniz, çünkü her ikisinde de çok fazla yeşil vardır.

Dezavantajı: çok basit. Her ikisi de sarı olduğu için bir muz ve bir plaj aynı görünecektir.

OpenCV yöntemi: comparHist ()

Şablon eşleme

Buna iyi bir örnek burada matchTemplate iyi eşleşme bulmak . Arama görüntüsünü, arandığı görüntüyle birleştirir. Genellikle daha büyük olan daha küçük görüntü parçalarını bulmak için kullanılır.

Dezavantajları: Sadece aynı görüntüler ve aynı boyutta iyi sonuçlar verir.

OpenCV yöntemi: matchTemplate ()

Özellik eşleme

Görsel arama yapmanın en etkili yollarından biri olarak kabul edilir. Bir görüntüden bir dizi özellik çıkarılır, aynı özelliklerin döndürüldüğünde, ölçeklendirildiğinde veya eğildiğinde bile yeniden tanınacağını garanti edecek şekilde. Bu şekilde çıkarılan özellikler diğer görüntü özellik kümeleriyle eşleştirilebilir. Birincisiyle eşleşen özelliklerin yüksek bir oranına sahip başka bir görüntünün aynı sahneyi tasvir ettiği düşünülmektedir.

İki nokta kümesi arasındaki homografiyi bulmak, orijinal resimler arasındaki çekim açısındaki göreceli farkı veya örtüşen miktarı da bulmanızı sağlar.

Bu konuda bir dizi OpenCV öğreticisi / örneği ve güzel bir video var . Bütün bir OpenCV modülü (features2d) buna ayrılmıştır.

Dezavantajları: Yavaş olabilir. Mükemmel değil.


Aşırı üzerinde OpenCV Q & A Bir görüntülerdeki insan yüzlerini veya arabalar gibi nesneleri tanımlamak için kullanılan bütün görüntü ve doku tanımlayıcılar, karşılaştırırken büyük özellik tanımlayıcıları, arasındaki fark bahsediyorum sitede.


sadece (örneğin yeni bir nesne aksi takdirde aynı görünüm içine taşındı) ile yapabilirsiniz ayrıca çalışma birkaç farklı görüntüler olduğunu benzer resimleri karşılaştırmak absdiff codota.com/code/java/methods/org.opencv.core.Core/absdiff Veri Eşiği sonuç sahneden sahneye değişen bölgeleri vurgulamanızı sağlayan bir maske üretir.
Max

34

Aynı görüntüleri eşleştirmek için ise (aynı boyut / yön)

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

Kaynak


12

Sam'in çözümü yeterli olmalı. Histogram farkının ve şablon eşleşmesinin bir kombinasyonunu kullandım çünkü tek bir yöntem% 100 kez benim için çalışmıyor. Yine de histogram yöntemine daha az önem verdim. Basit python betiğinde şu şekilde uyguladım.

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 __name__ == '__main__':
        compare_image = CompareImage('image1/path', 'image2/path')
        image_difference = compare_image.compare_image()
        print image_difference

Python'u iyi anlamıyorum. Peki 'commutative_image_diff' türü nedir? Mat veya çift. Cv.Mat ise, 'commutative_image_diff <self.minimum_commutative_image_diff' nasıl çalışır veya bunun amacı nedir? Benim için açıklayabilir misin?
BulletRain

1

Biraz konu dışı ama yararlı pitonik numpyyaklaşımdır. Sağlam ve hızlıdır, ancak resmin içerdiği nesneleri veya verileri değil, pikselleri karşılaştırır (ve aynı boyutta ve şekilde görüntüler gerektirir):

Bunu openCV ve bilgisayar vizyonu için herhangi bir kütüphane olmadan yapmak için çok basit ve hızlı bir yaklaşım, resim dizilerini

import numpy as np
picture1 = np.random.rand(100,100)
picture2 = np.random.rand(100,100)
picture1_norm = picture1/np.sqrt(np.sum(picture1**2))
picture2_norm = picture2/np.sqrt(np.sum(picture2**2))

Her iki normlu resmi (veya matrisi) tanımladıktan sonra, karşılaştırmak istediğiniz resimlerin çarpımını özetleyebilirsiniz:

1) benzer resimleri karşılaştırırsanız toplam 1 dönecektir:

In[1]: np.sum(picture1_norm**2)
Out[1]: 1.0

2) Benzer değilse, 0 ile 1 arasında bir değer alırsınız (100 ile çarptığınızda yüzde):

In[2]: np.sum(picture2_norm*picture1_norm)
Out[2]: 0.75389941124629822

Renkli resimleriniz varsa bunu 3 boyutun hepsinde yapmanız veya gri tonlamalı bir sürümü karşılaştırmanız gerektiğini lütfen unutmayın. Sık sık büyük miktarda resmi keyfi içerikle karşılaştırmam gerekiyor ve bunu yapmanın gerçekten hızlı bir yolu.


2
merhaba, sadece adımınızı takip ediyorum ama normalleştirilen parçanın düzgün sonuç alamadığını gördüm. Nihai sonuç 1.0'dan çok daha büyük. Herhangi bir fikir?
G_cy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.