วิธีที่ง่ายและรวดเร็วในการเปรียบเทียบภาพสำหรับความคล้ายคลึงกัน


192

ฉันต้องการวิธีที่ง่ายและรวดเร็วในการเปรียบเทียบภาพสองภาพเพื่อความคล้ายคลึงกัน คือฉันต้องการได้รับมูลค่าสูงหากมีสิ่งเดียวกัน แต่อาจมีพื้นหลังแตกต่างกันเล็กน้อยและอาจถูกย้าย / ปรับขนาดด้วยพิกเซลไม่กี่

(มีรูปธรรมมากขึ้นหากเป็นสิ่งสำคัญ: รูปภาพหนึ่งเป็นไอคอนและอีกรูปภาพหนึ่งเป็นพื้นที่ย่อยของภาพหน้าจอและฉันต้องการทราบว่าพื้นที่ย่อยนั้นเป็นไอคอนหรือไม่)

ฉันมีOpenCVในมือ แต่ก็ยังไม่คุ้นเคยกับมัน

ความเป็นไปได้อย่างหนึ่งที่ฉันคิดเกี่ยวกับ: แบ่งภาพทั้งสองออกเป็น 10x10 เซลล์และสำหรับแต่ละ 100 เซลล์เหล่านั้นเปรียบเทียบฮิสโตแกรมสี จากนั้นฉันสามารถตั้งค่าขีด จำกัด ที่สร้างขึ้นบางส่วนและถ้าค่าที่ฉันได้รับนั้นสูงกว่าขีด จำกัด นั้นฉันถือว่ามันคล้ายกัน

ฉันยังไม่ได้ลอง แต่ใช้งานได้ดี แต่ฉันคิดว่ามันจะดีพอ ภาพมีความคล้ายกันอยู่แล้ว (ในกรณีที่ใช้งาน) ดังนั้นฉันจึงสามารถใช้ค่าเกณฑ์ที่ค่อนข้างสูงได้

ฉันเดาว่ามีวิธีแก้ปัญหาที่เป็นไปได้อื่น ๆ อีกมากมายสำหรับสิ่งนี้ซึ่งจะทำงานได้มากหรือน้อย (เนื่องจากงานนั้นค่อนข้างง่ายเพราะฉันต้องการตรวจจับความเหมือนกันหากพวกมันคล้ายกันมากจริงๆ) คุณจะแนะนำอะไร


มีคำถามที่เกี่ยวข้องมาก / คล้ายกันสองสามข้อเกี่ยวกับการขอรับลายเซ็น / ลายนิ้วมือ / แฮชจากรูปภาพ:

นอกจากนี้ฉันยังสะดุดกับการใช้งานเหล่านี้ซึ่งมีฟังก์ชั่นดังกล่าวเพื่อรับลายนิ้วมือ:

การสนทนาบางอย่างเกี่ยวกับแฮชของการรับรู้ภาพ: ที่นี่


เรื่องย่อ: มีหลายวิธีในการสร้างเสียงลายนิ้วมือ MusicBrainzเป็นบริการเว็บที่ให้บริการค้นหาแบบลายนิ้วมือที่ใช้สำหรับเพลงมีภาพรวมที่ดีในวิกิพีเดียของพวกเขา พวกเขากำลังใช้AcoustID ในขณะนี้ นี่คือการหาการแข่งขันที่แน่นอน สำหรับการค้นหาที่ตรงกันที่คล้ายกัน (หรือถ้าคุณมีเพียงตัวอย่างบางส่วนหรือเสียงสูง) จะดูที่Echoprint คำถามที่เกี่ยวข้องเพื่อให้เป็นที่นี่ ดังนั้นดูเหมือนว่าสิ่งนี้จะได้รับการแก้ไขสำหรับเสียง โซลูชันทั้งหมดเหล่านี้ทำงานได้ค่อนข้างดี

คำถามที่ค่อนข้างทั่วไปมากขึ้นเกี่ยวกับการค้นหาเลือนโดยทั่วไปเป็นที่นี่ เช่นมีคร่ำเครียดท้องที่ที่มีความอ่อนไหวและค้นหาเพื่อนบ้านที่ใกล้ที่สุด


1
บางทีการพิมพ์ลายนิ้วมือของภาพอาจช่วยได้บ้าง stackoverflow.com/questions/596262/…
GWW

ตัวชี้วัด Wasserstein หรือที่เรียกว่าระยะทางของ Earth Mover (EMD) เป็นสิ่งที่ผู้คนดูเหมือนจะไม่รู้ แต่จะให้สิ่งที่คุณต้องการที่นี่
mmgp


สวัสดีฉันมาด้วยการปรับปรุง dHash - ฉันเรียกมันว่า IDHash: github.com/Nakilon/dhash-vips
Nakilon

คำตอบ:


107

สามารถแปลงภาพหน้าจอหรือไอคอน (ปรับขนาด, หมุน, เบ้ ... )? มีสองสามวิธีที่เหนือหัวฉันที่อาจช่วยคุณได้:

  • ระยะทางแบบยุคลิดแบบง่ายตามที่ระบุไว้โดย @carlosdc (ไม่ทำงานกับภาพที่แปลงแล้วและคุณต้องการเกณฑ์)
  • (ปรับให้เป็นมาตรฐาน) Cross Correlation - ตัวชี้วัดง่ายๆที่คุณสามารถใช้สำหรับการเปรียบเทียบพื้นที่รูปภาพ มันแข็งแกร่งกว่าระยะทางแบบยุคลิดแบบธรรมดา แต่ไม่สามารถใช้งานกับภาพที่แปลงแล้วและคุณจะต้องใช้เกณฑ์อีกครั้ง
  • การเปรียบเทียบฮิสโตแกรม - หากคุณใช้ฮิสโตแกรมที่ทำให้เป็นมาตรฐานวิธีนี้ใช้ได้ดีและไม่ได้รับผลกระทบจากการแปลงเลียนแบบ ปัญหาคือการกำหนดเกณฑ์ที่ถูกต้อง นอกจากนี้ยังมีความไวสูงต่อการเปลี่ยนแปลงสี (ความสว่างความคมชัด ฯลฯ ) คุณสามารถรวมกับสองก่อนหน้า
  • ตรวจจับจุดสำคัญ / พื้นที่ - เช่นMSER (Maximally Stable extremal ภูมิภาค) , SURFหรือร่อน นี่เป็นอัลกอริธึมที่แข็งแกร่งมากและอาจซับซ้อนเกินไปสำหรับงานง่าย ๆ ของคุณ สิ่งที่ดีคือคุณไม่จำเป็นต้องมีพื้นที่ที่แน่นอนด้วยไอคอนเดียวเท่านั้นเครื่องตรวจจับเหล่านี้มีพลังมากพอที่จะหาคู่ที่เหมาะสม การประเมินผลที่ดีของวิธีการเหล่านี้อยู่ในบทความนี้: ท้องถิ่นตรวจจับคุณลักษณะคง: การสำรวจ

เหล่านี้ส่วนใหญ่จะดำเนินการอยู่แล้วใน OpenCV - ดูตัวอย่างวิธีการ cvMatchTemplate (histogram ใช้การจับคู่): http://dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html พุ่งตรวจจับจุด / พื้นที่นอกจากนี้ยังมี - ดูOpenCV การตรวจสอบคุณสมบัติ


1
สามารถปรับขนาดหรือเคลื่อนย้ายเล็กน้อย นอกจากนี้พื้นหลังของไอคอนจะแตกต่างกัน ฉันลองเปรียบเทียบฮิสโตแกรม แต่ได้ผลบวกปลอมหลายอย่าง ฉันลองใช้ระยะทางแบบยุคลิด แต่ก็ให้ผลบวกที่ผิดพลาดมากเกินไป (แต่บางทีฉันอาจทำให้การจัดการค่าอัลฟาในไอคอนดีขึ้นเล็กน้อย) ฉันจะลองอีกเล็กน้อยมิฉะนั้นฉันจะลองใช้ MSER, SURF หรือ SIFT
อัลเบิร์ต

1
ความคิดอื่น - มันจะไม่ทำงานถ้าคุณใช้การเปรียบเทียบฮิสโตแกรมของภาพหลังจากใช้ตัวดำเนินการ sobel นั่นจะเปรียบเทียบความคล้ายคลึงกันของขอบเท่านั้น อาจหรืออาจไม่ทำงานขึ้นอยู่กับพื้นหลัง "หงุดหงิด"
Karel Petranek

44

ฉันต้องเผชิญกับปัญหาเดียวกันเมื่อเร็ว ๆ นี้เพื่อแก้ปัญหานี้ (อัลกอริทึมที่ง่ายและรวดเร็วในการเปรียบเทียบสองภาพ) และทุกครั้งฉันมีส่วนร่วมในโมดูล img_hash กับ opencv_contrib คุณสามารถค้นหารายละเอียดได้จากลิงค์นี้

img_hash module มีอัลกอริธึมแฮชภาพหกแบบใช้งานง่าย

ตัวอย่างรหัส

ต้นกำเนิดลีนาต้นกำเนิดลีนา

เบลอเสนาเบลอเสนา

ปรับขนาด lenaปรับขนาด 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 ให้ผลลัพธ์ที่ดีที่สุดแก่เรา

  • Gaussian Blur Attack: 0.567521
  • การโจมตีกะ: 0.229728
  • ปรับขนาดการโจมตี: 0.229358

ข้อดีและข้อเสียของแต่ละอัลกอริทึม

ประสิทธิภาพภายใต้การโจมตีที่แตกต่างกัน

ประสิทธิภาพของ img_hash นั้นก็ดีเช่นกัน

เปรียบเทียบความเร็วกับ PHash ไลบรารี่ (100 ภาพจาก ukbench) คำนวณประสิทธิภาพ ประสิทธิภาพการเปรียบเทียบ

หากคุณต้องการทราบเกณฑ์ที่แนะนำสำหรับอัลกอริทึมเหล่านี้โปรดตรวจสอบโพสต์นี้ ( 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 )


11

ภาพหน้าจอมีไอคอนเท่านั้นหรือไม่ หากเป็นเช่นนั้นระยะ L2 ของภาพสองภาพอาจเพียงพอ ถ้าระยะห่าง L2 ไม่ทำงานขั้นตอนต่อไปคือการพยายามที่สิ่งที่ง่ายและดีขึ้นเช่น: Lucas-Kanade ซึ่งฉันแน่ใจว่ามีอยู่ใน OpenCV


พื้นที่ย่อยมีเพียงไอคอนเท่านั้น (ที่มีพื้นหลังแบบสุ่ม) หรือบางอย่างที่แตกต่าง ฉันต้องการดูว่าเป็นกรณีใด แม้ว่ามันอาจจะขยับเล็กน้อยหรือปรับขนาดเล็กน้อยนั่นคือสาเหตุที่ฉันไม่แน่ใจว่าฉันสามารถมองระยะทางได้หรือไม่ แต่ฉันจะลองกับรุ่นที่ลดขนาดลง
อัลเบิร์ต

6

หากคุณต้องการรับดัชนีเกี่ยวกับความคล้ายคลึงกันของภาพทั้งสองนี้ฉันขอแนะนำคุณจากการวัดดัชนี SSIM มันสอดคล้องกับดวงตาของมนุษย์มากขึ้น นี่คือบทความเกี่ยวกับมัน: ดัชนีความคล้ายคลึงกันของโครงสร้าง

มีการใช้งานใน OpenCV ด้วยและสามารถเร่งด้วย GPU: OpenCV SSIM พร้อม GPU


5

หากคุณมั่นใจได้ว่ามีการจัดตำแหน่งแม่แบบของคุณ (ไอคอน) อย่างแม่นยำในพื้นที่การทดสอบผลรวมของความแตกต่างของพิกเซลเก่า ๆ จะทำงานได้

หากการจัดตำแหน่งจะลดลงเพียงเล็กน้อยคุณสามารถส่งภาพทั้งสองภาพด้วยcv :: GaussianBlurก่อนที่จะค้นหาผลรวมของความแตกต่างของพิกเซล

หากคุณภาพของการจัดแนวนั้นอาจไม่ดีนักฉันขอแนะนำฮิสโตแกรมของการไล่ระดับสีเชิงเส้นหรือหนึ่งในอัลกอริทึมการตรวจหา / กำหนดคำอธิบายที่สะดวกสบายของ OpenCV (เช่นSIFTหรือSURF )


4

ถ้าจับคู่ภาพที่เหมือนกัน - รหัสสำหรับระยะทาง 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
}

รวดเร็ว แต่ไม่ทนทานต่อการเปลี่ยนแปลงของแสง / จุดชมวิวเป็นต้น ที่มา


2

หากคุณต้องการเปรียบเทียบภาพเพื่อความคล้ายคลึงฉันขอแนะนำให้คุณใช้ OpenCV ใน OpenCV มีการจับคู่คุณสมบัติน้อยและการจับคู่แม่แบบ สำหรับการจับคู่คุณสมบัตินั้นมี SURF, SIFT, FAST และอื่น ๆ คุณสามารถใช้สิ่งนี้เพื่อตรวจจับอธิบายและจับคู่ภาพแล้ว หลังจากนั้นคุณสามารถใช้ดัชนีเฉพาะเพื่อค้นหาจำนวนการจับคู่ระหว่างภาพทั้งสอง


1
คุณพูดว่า "หลังจากนั้นคุณสามารถใช้ดัชนีเฉพาะเพื่อค้นหาจำนวนการจับคู่ระหว่างภาพสองภาพ" จำนวนการจับคู่ที่น้อยที่สุดระหว่างสองภาพเพื่อบอกว่าพวกเขา "ประดิษฐ์" เป็นวัตถุเดียวกันคืออะไร
Inês Martins
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.