समानता के लिए छवियों की तुलना करने के लिए सरल और तेज़ विधि


192

मुझे समानता के लिए दो छवियों की तुलना करने के लिए एक सरल और तेज़ तरीका चाहिए। यानी मैं एक उच्च मूल्य प्राप्त करना चाहता हूं अगर वे बिल्कुल एक ही चीज होते हैं, लेकिन कुछ अलग पृष्ठभूमि हो सकती है और कुछ पिक्सेल द्वारा स्थानांतरित / आकार बदला जा सकता है।

(अधिक ठोस, अगर यह मायने रखता है: एक तस्वीर एक आइकन है और दूसरी तस्वीर एक स्क्रीनशॉट की एक सबअरीया है और मैं जानना चाहता हूं कि क्या यह सबारिया बिल्कुल आइकन है या नहीं।)

मेरे पास OpenCV है , लेकिन मैं अभी भी इसका उपयोग नहीं कर रहा हूं।

एक संभावना जो मैंने अब तक के बारे में सोचा था: दोनों चित्रों को 10x10 कोशिकाओं में विभाजित करें और उन 100 कोशिकाओं में से प्रत्येक के लिए, रंग हिस्टोग्राम की तुलना करें। फिर मैं कुछ बनाये गए थ्रेशोल्ड वैल्यू सेट कर सकता हूँ और अगर मुझे जो वैल्यू मिलती है, वह उस सीमा से ऊपर है, तो मैं मानता हूँ कि वे समान हैं।

मैंने अभी तक इसकी कोशिश नहीं की है कि यह कितना अच्छा है लेकिन मुझे लगता है कि यह काफी अच्छा होगा। छवियां पहले से ही बहुत अधिक समान हैं (मेरे उपयोग के मामले में), इसलिए मैं बहुत अधिक उच्च मूल्य का उपयोग कर सकता हूं।

मुझे लगता है कि इसके लिए दर्जनों अन्य संभावित समाधान हैं जो कम या ज्यादा काम करेंगे (जैसा कि कार्य स्वयं काफी सरल है क्योंकि मैं केवल समानता का पता लगाना चाहता हूं यदि वे वास्तव में बहुत समान हैं)। आप क्या सुझाव देंगे?


एक छवि से एक हस्ताक्षर / फिंगरप्रिंट / हैश प्राप्त करने के बारे में कुछ बहुत ही संबंधित / समान प्रश्न हैं:

इसके अलावा, मैं इन कार्यान्वयनों पर अड़ गया, जिनके पास फिंगरप्रिंट प्राप्त करने के लिए ऐसे कार्य हैं:

अवधारणात्मक छवि हैश के बारे में कुछ चर्चाएँ: यहाँ


थोडा ऑफटॉपिक: ऑडियो फिंगरप्रिंट बनाने के लिए कई तरीके मौजूद हैं। MusicBrainz , एक वेब-सेवा जो गानों के लिए फ़िंगरप्रिंट-आधारित लुकअप प्रदान करती है, उनकी विकी में एक अच्छा अवलोकन है । वे अब एक्वाडिड का उपयोग कर रहे हैं। यह सटीक (या अधिकतर सटीक) मिलान खोजने के लिए है। इसी तरह के मैचों को खोजने के लिए (या यदि आपके पास केवल कुछ स्निपेट्स या उच्च शोर हैं), तो इकोप्रिंट पर एक नज़र डालें । एक संबंधित SO प्रश्न यहाँ है । तो ऐसा लगता है कि यह ऑडियो के लिए हल है। ये सभी समाधान काफी अच्छे काम करते हैं।

सामान्य रूप से फ़ज़ी खोज के बारे में कुछ अधिक सामान्य प्रश्न यहाँ है । उदाहरण के लिए, स्थानीय-संवेदनशील हैशिंग और निकटतम पड़ोसी खोज है


1
शायद छवि फिंगरप्रिंटिंग मदद कर सकता है? stackoverflow.com/questions/596262/…
GWW

वासेरस्टीन मैट्रिक, जिसे अर्थ मूवर्स डिस्टेंस (EMD) के नाम से भी जाना जाता है, ऐसा कुछ है जिसके बारे में लोगों को पता नहीं है, लेकिन आप यहाँ जो चाहते हैं वह बहुत कुछ देगा।
mmgp


हाय, मैं सुधार dHash के साथ आया था - मैं इसे IDHash कहा जाता है: github.com/Nakilon/dhash-vips
Nakilon

जवाबों:


107

क्या स्क्रीनशॉट या आइकन को रूपांतरित किया जा सकता है (स्केल किया गया, घुमाया गया, तिरछा ...)? मेरे सिर के ऊपर कुछ तरीके हैं जो संभवतः आपकी मदद कर सकते हैं:

  • @Carlosdc द्वारा उल्लिखित सरल यूक्लिडियन दूरी (रूपांतरित छवियों के साथ काम नहीं करती है और आपको थ्रेशोल्ड की आवश्यकता है)।
  • (सामान्यीकृत) क्रॉस सहसंबंध - एक सरल मैट्रिक्स जिसे आप छवि क्षेत्रों की तुलना के लिए उपयोग कर सकते हैं। यह साधारण यूक्लिडियन दूरी से अधिक मजबूत है, लेकिन रूपांतरित छवियों पर काम नहीं करता है और आपको फिर से एक सीमा की आवश्यकता होगी।
  • हिस्टोग्राम तुलना - यदि आप सामान्यीकृत हिस्टोग्राम का उपयोग करते हैं, तो यह विधि अच्छी तरह से काम करती है और एफाइन ट्रांसफ़ॉर्म से प्रभावित नहीं होती है। समस्या सही सीमा निर्धारित कर रही है। यह रंग परिवर्तन (चमक, इसके विपरीत आदि) के प्रति भी बहुत संवेदनशील है। आप इसे पिछले दो के साथ जोड़ सकते हैं।
  • मुख्य बिंदुओं / क्षेत्रों के डिटेक्टर - जैसे कि MSER (मैक्सिमली स्टेबल एक्सट्रीमल रीजन) , SURF या SIFT । ये बहुत मजबूत एल्गोरिदम हैं और ये आपके सरल कार्य के लिए बहुत जटिल हो सकते हैं। अच्छी बात यह है कि आपके पास केवल एक आइकन के साथ एक सटीक क्षेत्र होने की आवश्यकता नहीं है, ये डिटेक्टर सही मैच खोजने के लिए पर्याप्त शक्तिशाली हैं। इन विधियों का एक अच्छा मूल्यांकन इस पत्र में है: स्थानीय अपरिवर्तनीय फीचर डिटेक्टर: एक सर्वेक्षण

इनमें से अधिकांश पहले से ही OpenCV में लागू हैं - उदाहरण के लिए cvMatchTemplate विधि (हिस्टोग्राम मिलान का उपयोग करता है) देखें: http://dasl.mem.drexel.edu/~noahKuntz/openCVTM6.html । मुख्य बिंदु / क्षेत्र डिटेक्टर भी उपलब्ध हैं - OpenCV फ़ीचर डिटेक्शन देखें


1
इसे थोड़ा बढ़ाया या बढ़ाया जा सकता है। साथ ही आइकन का बैकग्राउंड भी अलग होगा। मैंने हिस्टोग्राम तुलना की कोशिश की, लेकिन मुझे कई झूठी सकारात्मक चीजें मिलीं। मैंने यूक्लिडियन दूरी की भी कोशिश की, लेकिन यह बहुत अधिक झूठी सकारात्मकता भी देता है (लेकिन शायद मैं यह बेहतर कर सकता हूं कि आइकन में अल्फा वैल्यू के लिए कुछ बेहतर हैंडलिंग)। मैं कोशिश करूंगा कि थोड़ा और आगे, अन्यथा मैं MSER, SURF या SIFT की जांच करूंगा।
अल्बर्ट

1
एक और विचार - अगर आप सोबल ऑपरेटर लगाने के बाद छवियों की हिस्टोग्राम तुलना का उपयोग करते हैं तो यह काम नहीं करेगा? यह केवल किनारों की समानता की तुलना करेगा। पृष्ठभूमि के "नुकीले" होने के आधार पर काम हो सकता है या नहीं भी हो सकता है।
कारेल पेट्रानेक

44

मैं हाल ही में एक ही मुद्दे का सामना करता हूं, इस समस्या को हल करने के लिए (दो छवियों की तुलना करने के लिए सरल और तेज एल्गोरिदम) एक बार और सभी के लिए, मैं opencv_contrib के लिए एक img_hash मॉड्यूल का योगदान देता हूं, आप इस लिंक से विवरण पा सकते हैं ।

img_hash मॉड्यूल छह छवि हैश एल्गोरिदम प्रदान करता है, उपयोग करने के लिए काफी आसान है।

कोड उदाहरण

मूल लीनामूल लीना

धब्बा देनाधब्बा देना

लीना का आकार बदलेंलीना का आकार बदलें

शिफ्ट करनाशिफ्ट करना

#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 हमें सबसे अच्छा परिणाम देता है

  • गॉसियन ब्लर अटैक: 0.567521
  • पारी का दौरा: 0.229728
  • आकार परिवर्तन हमला: 0.229358

प्रत्येक एल्गोरिथ्म के पेशेवरों और विपक्ष

विभिन्न हमलों के तहत प्रदर्शन

Img_hash का प्रदर्शन भी अच्छा है

PHash लाइब्रेरी के साथ स्पीड तुलना (ukbench से 100 चित्र) कंप्यूट प्रदर्शन तुलना प्रदर्शन

यदि आप इन एल्गोरिदम के लिए थ्रेसहोल्ड की सिफारिश जानना चाहते हैं, तो कृपया इस पोस्ट ( http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html ) को देखें। यदि आप इस बारे में दिलचस्प हैं कि मैं img_hash मॉड्यूल के प्रदर्शन को कैसे मापता हूं (गति और विभिन्न हमलों को शामिल करें), तो कृपया इस लिंक ( http://qtandopencv.blogspot.my/2016/06/speed-up-image-shshing-of) को देखें। -opencvimghash.html )।


11

क्या स्क्रीनशॉट में केवल आइकन है? यदि ऐसा है, तो दो छवियों की L2 दूरी पर्याप्त हो सकती है। यदि L2 दूरी काम नहीं करती है, तो अगला कदम कुछ सरल और अच्छी तरह से स्थापित करने की कोशिश करना है, जैसे: लुकास-कनाडे । मुझे यकीन है कि OpenCV में उपलब्ध है।


सबारिया में या तो केवल आइकन (कुछ यादृच्छिक पृष्ठभूमि के साथ) या कुछ अलग होता है। मैं देखना चाहता हूं कि यह कौन सा मामला है। हालांकि, यह बहुत थोड़ा स्थानांतरित या आकार बदला जा सकता है, यही कारण है कि मुझे यकीन नहीं था कि अगर मैं बस (जो भी आदर्श हो) दूरी को देख सकता हूं। लेकिन मैं एक स्केल डाउन वर्जन के साथ कोशिश करूंगा।
अल्बर्ट

6

यदि आप दो चित्रों की समानता के बारे में एक इंडेक्स प्राप्त करना चाहते हैं, तो मैं आपको मेट्रिक्स SSIM इंडेक्स से सुझाव देता हूं। यह मानव आंख के साथ अधिक सुसंगत है। इसके बारे में एक लेख यहां दिया गया है: संरचनात्मक समानता सूचकांक

यह OpenCV में भी लागू किया गया है, और यह GPU के साथ त्वरित किया जा सकता है: GPU के साथ OpenCV SSIM


5

यदि आप परीक्षण क्षेत्र में अपने टेम्पलेट (आइकन) का सटीक संरेखण सुनिश्चित कर सकते हैं, तो पिक्सेल अंतर का कोई भी पुराना योग काम करेगा।

यदि संरेखण केवल एक छोटा सा बंद होने जा रहा है, तो आप पिक्सेल अंतर का योग खोजने से पहले cv :: GaussianBlur के साथ दोनों छवियों को कम-पास कर सकते हैं ।

यदि संरेखण की गुणवत्ता संभावित रूप से खराब है, तो मैं या तो ओरिएंटेड ग्रेडिस्ट के हिस्टोग्राम या ओपनसीवी के सुविधाजनक कीपॉइंट डिटेक्शन / डिस्क्रिप्टर एल्गोरिदम (जैसे सिफ्ट या एसयूआरएफ ) में से एक की सिफारिश करूंगा ।


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
आपने कहा "उसके बाद, आप दो छवियों के बीच मिलान की संख्या का पता लगाने के लिए विशिष्ट सूचकांक का उपयोग कर सकते हैं।" यह कहने के लिए कि दोनों छवियों के बीच मैचों की न्यूनतम संख्या क्या हो सकती है, क्योंकि वे एक ही वस्तु पर "कंटैस" करते हैं?
मार्ट मार्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.