OpenCV와 비슷한 두 이미지의 차이점을 어떻게 평가할 수 있습니까?


141

OpenCV는 두 이미지의 비교를 지원하고이 이미지의 유사성을 나타내는 값 (아마도 백분율)을 반환합니까? 예를 들어 동일한 이미지가 두 번 전달되면 100 %가 반환되고 이미지가 완전히 다른 경우 0 %가 반환됩니다.

StackOverflow에서 이미 비슷한 주제를 많이 읽었습니다. 나는 또한 꽤 인터넷 검색을했다. 슬프게도 나는 만족스러운 답변을 얻을 수 없었습니다.


답변:


208

이것은 3 줄의 코드에서 전체 리서치 잡지에 대한 답변이 포함 된 거대한 주제입니다.

가장 일반적인 기술과 그 결과를 간략하게 설명하겠습니다.

히스토그램 비교

가장 간단하고 빠른 방법 중 하나입니다. 수십 년 전에 그림의 유사성을 찾는 수단으로 제안되었습니다. 아이디어는 숲에 많은 녹색이 있고 인간의 얼굴에는 분홍색이 많거나 그 밖의 것이있을 것입니다. 따라서 두 장의 사진을 숲과 비교하면 히스토그램 사이에 약간의 녹색이 생겨 히스토그램간에 약간의 유사성이 나타납니다.

단점 : 너무 단순합니다. 바나나와 해변은 모두 노란색으로 똑같이 보입니다.

OpenCV 메소드 : compareHist ()

템플릿 매칭

여기에 좋은 예가 있습니다. matchTemplate이 일치하는 것을 찾습니다 . 검색 이미지와 검색 이미지를 통합합니다. 일반적으로 큰 이미지 부분에서 작은 이미지 부분을 찾는 데 사용됩니다.

단점 : 동일한 이미지, 동일한 크기 및 방향으로 좋은 결과 만 반환합니다.

OpenCV 메소드 : matchTemplate ()

기능 매칭

이미지 검색을 수행하는 가장 효율적인 방법 중 하나를 고려했습니다. 이미지에서 회전하거나 크기를 조정하거나 기울일 때에도 동일한 기능을 다시 인식 할 수 있도록 여러 기능이 이미지에서 추출됩니다. 이 방법으로 추출 된 기능은 다른 이미지 기능 세트와 비교할 수 있습니다. 첫 번째 이미지와 일치하는 기능의 비율이 높은 다른 이미지는 동일한 장면을 나타내는 것으로 간주됩니다.

두 세트의 점 사이에서 호모 그래피를 찾으면 원본 사진 사이의 촬영 각도 또는 겹치는 정도의 상대적인 차이도 찾을 수 있습니다.

이것에 관한 많은 OpenCV 튜토리얼 / 샘플이 있으며 여기에 좋은 비디오가 있습니다 . 전체 OpenCV 모듈 (기능 2d)이 전용입니다.

단점 : 느려질 수 있습니다. 완벽하지 않습니다.


오버에 OpenCV의 Q & A 나는 이미지의 인간의 얼굴이나 자동차와 같은 객체를 식별하는 데 사용되는 모든 이미지와 질감 기술자를 비교했을 때 좋은 기능 기술자의 차이에 대해 이야기하고있는 사이트.


몇 가지 뚜렷한 이미지 만있는 유사한 이미지를 비교하려면 (예 : 새 객체가 다른보기로 이동) absdiff codota.com/code/java/methods/org.opencv.core.Core/absdiff로 작업 할 수도 있습니다. 장면에서 장면으로 변경된 영역을 강조 할 수있는 마스크를 생성합니다.
최대 F.

34

동일한 이미지를 일치시키는 경우 (동일한 크기 / 방향)

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

출처


12

샘의 해결책이 충분해야합니다. 100 %의 시간 동안 하나의 방법으로 작동하지 않았기 때문에 히스토그램 차이와 템플릿 일치를 조합하여 사용했습니다. 그래도 히스토그램 방법에 대해서는 덜 중요합니다. 간단한 파이썬 스크립트로 구현 한 방법은 다음과 같습니다.

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

나는 파이썬을 잘 이해하지 못한다. 그러나 'commutative_image_diff'유형은 무엇입니까? cv.Mat 또는 double. cv.Mat 인 경우 'commutative_image_diff <self.minimum_commutative_image_diff'를 비교하여 어떻게 작동하는지 또는이 목적의 목적을 비교하십시오. 설명해 주시겠습니까?
BulletRain

1

약간 벗어난 주제이지만 유용한 것은 pythonic numpy접근법입니다. 견고하고 빠르지 만 그림과 객체와 데이터가 아닌 픽셀을 비교합니다 (크기와 모양이 같은 이미지가 필요함).

openCV와 컴퓨터 비전을위한 라이브러리없이이 작업을 수행하는 매우 간단하고 빠른 방법은 그림 배열을

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))

두 개의 표준 그림 (또는 행렬)을 정의한 후 비교하려는 그림의 곱셈을 요약하면됩니다.

1) 비슷한 그림을 비교하면 합계가 1을 반환합니다.

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

2) 유사하지 않으면 0과 1 사이의 값을 얻습니다 (100을 곱하면 백분율).

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

컬러 사진이있는 경우 3 차원 모두에서이 작업을 수행하거나 그레이 스케일 버전을 비교해야합니다. 나는 종종 많은 양의 그림을 임의의 내용과 비교해야하며 그렇게하는 정말 빠른 방법입니다.


2
안녕하세요, 나는 당신의 단계를 따르지만 정규화 부분이 적절한 결과를 얻을 수 없다는 것을 알았습니다. 최종 결과는 1.0보다 훨씬 큽니다. 어떤 생각?
G_cy 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.