ฉันจะประเมินได้อย่างไรว่ามีสองภาพที่คล้ายกันกับ OpenCV?


141

OpenCV รองรับการเปรียบเทียบภาพสองภาพโดยคืนค่าบางค่า (อาจเป็นเปอร์เซ็นต์) ที่ระบุว่าภาพเหล่านี้คล้ายกันอย่างไร เช่น 100% จะถูกส่งกลับหากภาพเดียวกันถูกส่งผ่านสองครั้ง 0% จะถูกส่งกลับหากภาพนั้นแตกต่างกันโดยสิ้นเชิง

ฉันได้อ่านหัวข้อที่คล้ายกันจำนวนมากที่นี่ใน StackOverflow แล้ว ฉันทำ Googling ด้วยเช่นกัน น่าเศร้าที่ฉันไม่สามารถหาคำตอบที่น่าพอใจได้


ดูคำตอบเพิ่มเติมได้ที่stackoverflow.com/questions/4196453/…
B. Go

คำตอบ:


208

นี่เป็นหัวข้อใหญ่ที่มีคำตอบจากรหัส 3 บรรทัดไปจนถึงนิตยสารวิจัยทั้งหมด

ฉันจะร่างเทคนิคดังกล่าวที่พบบ่อยที่สุดและผลลัพธ์ของพวกเขา

การเปรียบเทียบฮิสโตแกรม

หนึ่งในวิธีที่ง่ายและเร็วที่สุด เสนอมานานหลายทศวรรษที่ผ่านมาเป็นวิธีการค้นหาภาพที่คล้ายคลึงกัน แนวคิดก็คือป่าจะมีสีเขียวจำนวนมากและใบหน้าของมนุษย์จะมีสีชมพูหรืออะไรก็ตาม ดังนั้นหากคุณเปรียบเทียบภาพสองภาพกับป่าไม้คุณจะได้รับความคล้ายคลึงกันระหว่างฮิสโทแกรมเพราะคุณมีทั้งสีเขียวและสีเขียวมากมาย

ข้อเสีย: มันง่ายเกินไป กล้วยและชายหาดจะมีหน้าตาเหมือนกันเพราะทั้งคู่เป็นสีเหลือง

วิธี OpenCV: comparHist ()

การจับคู่แม่แบบ

เป็นตัวอย่างที่ดีที่นี่matchTemplate การหาคู่ที่ดี มันทำให้ภาพการค้นหาตรงกับที่ค้นหา มักจะใช้เพื่อค้นหาส่วนภาพที่เล็กลงในส่วนที่ใหญ่กว่า

ข้อเสีย: มันจะส่งกลับผลลัพธ์ที่ดีด้วยภาพที่เหมือนกันขนาดและทิศทางเดียวกัน

วิธี OpenCV: matchTemplate ()

การจับคู่คุณสมบัติ

ถือว่าเป็นหนึ่งในวิธีที่มีประสิทธิภาพที่สุดในการค้นหารูปภาพ คุณสมบัติจำนวนมากถูกดึงออกมาจากรูปภาพในลักษณะที่รับประกันว่าฟีเจอร์เดียวกันจะได้รับการจดจำอีกครั้งแม้ว่าจะหมุนปรับหรือเบ้ก็ตาม คุณสมบัติที่แยกด้วยวิธีนี้สามารถจับคู่กับชุดคุณสมบัติภาพอื่น ๆ ได้ ภาพอื่นที่มีสัดส่วนสูงของคุณสมบัติที่ตรงกับภาพแรกนั้นถือว่าเป็นภาพที่เหมือนกัน

การค้นหาความคล้ายคลึงกันระหว่างคะแนนสองชุดจะช่วยให้คุณค้นหาความแตกต่างสัมพัทธ์ในมุมการถ่ายภาพระหว่างภาพต้นฉบับหรือจำนวนการซ้อนทับกัน

มีจำนวนของบทเรียน OpenCV / ตัวอย่างเกี่ยวกับเรื่องนี้และวิดีโอที่ดีอยู่ที่นี่ โมดูล OpenCV ทั้งหมด (features2d) อุทิศให้กับมัน

ข้อเสีย: อาจช้า มันไม่สมบูรณ์แบบ


บนเว็บไซต์ถามตอบเกี่ยวกับOpenCVฉันกำลังพูดถึงความแตกต่างระหว่างตัวบอกคุณสมบัติซึ่งยอดเยี่ยมเมื่อเปรียบเทียบภาพทั้งหมดกับตัวอธิบายพื้นผิวซึ่งใช้เพื่อระบุวัตถุเช่นใบหน้ามนุษย์หรือรถยนต์ในภาพ


เพื่อเปรียบเทียบภาพที่คล้ายกันที่มีเพียงภาพที่แตกต่างกันไม่กี่ (เช่นวัตถุใหม่ย้ายเข้ามาในมุมมองเดียวกันอื่น ๆ ) นอกจากนี้คุณยังสามารถทำงานร่วมกับabsdiff codota.com/code/java/methods/org.opencv.core.Core/absdiff Thresholding ผล ผลิตหน้ากากที่ช่วยให้คุณสามารถเน้นภูมิภาคที่เปลี่ยนจากฉากเป็นฉาก
Max 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 หรือสองครั้ง หากเป็น cv.Mat ให้เปรียบเทียบ 'commutative_image_diff <self.minimum_commutative_image_diff' มันทำงานอย่างไรหรือวัตถุประสงค์ของการเปรียบเทียบนี้เป็นอย่างไร คุณอธิบายให้ฉันได้ไหม
BulletRain

1

หัวข้อปิดเล็กน้อย แต่มีประโยชน์คือ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))

หลังจากกำหนดรูปภาพ normed (หรือเมทริกซ์) ทั้งสองคุณสามารถสรุปผลคูณของรูปภาพที่คุณต้องการเปรียบเทียบ:

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

โปรดสังเกตว่าหากคุณมีภาพสีคุณต้องทำทั้งสามมิติหรือเพียงแค่เปรียบเทียบรุ่น greyscaled ฉันมักจะต้องเปรียบเทียบรูปภาพจำนวนมากกับเนื้อหาที่กำหนดเองและนั่นเป็นวิธีที่รวดเร็วในการทำเช่นนั้น


2
สวัสดีฉันเพิ่งทำตามขั้นตอนของคุณ แต่ฉันพบว่าส่วนปกติไม่สามารถรับผลลัพธ์ที่เหมาะสมได้ ผลสุดท้ายมากกว่า 1.0 มาก ความคิดใด ๆ
G_cy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.