एल्गोरिथ्म C#में दो छवियों की तुलना करने के लिए




image hash (3)

छवि की तुलना के लिए उपलब्ध तरीकों को देखने के लिए आप दो छवियों की तुलना करने के लिए एल्गोरिथ्म की जांच कर सकते हैं।

जब तक आप अपने दम पर पूर्ण एल्गोरिदम को फिर से बनाना नहीं चाहते हैं, तब तक आपको पहले से मौजूद पुस्तकालयों या उनके कोड का कम से कम भाग (जब तक उनका लाइसेंस आपके लिए ठीक है) का उपयोग करने का प्रयास करना चाहिए।

एज डिटेक्शन और संबंधित कंप्यूटर विज़न एल्गोरिदम के खुले स्रोत C # कार्यान्वयन के लिए, आप EmguCV कोशिश कर सकते हैं जो EmguCV का एक आवरण है।

मैं डुप्लिकेट छवियों को खोजने के लिए C # में एक उपकरण लिख रहा हूं। वर्तमान में मैं फ़ाइलों का MD5 चेकसम बनाता हूं और उन की तुलना करता हूं।

दुर्भाग्य से मेरी छवियां हो सकती हैं

  • 90 डिग्री से घुमाया गया
  • विभिन्न आयाम हैं (समान सामग्री वाली छोटी छवि)
  • अलग-अलग कंप्रेसेशन या फिल्टिप्स हैं (उदाहरण के लिए jpeg कलाकृतियां, नीचे देखें)

इस समस्या को हल करने के लिए सबसे अच्छा तरीका क्या होगा?


छवियों को कुछ सामान्य रिज़ॉल्यूशन में फिर से शामिल करने के बाद, आप एक वेवलेट अपघटन का उपयोग कर सकते हैं और छवियों के बजाय इस अपघटन के गुणांक की तुलना कर सकते हैं। केवल पहले एन गुणांक की तुलना करने से यह विधि शोर और अन्य कलाकृतियों के लिए और अधिक मजबूत हो जाएगी।

तरंगों के लिए कई C # कार्यान्वयन उपलब्ध हैं। एक उदाहरण https://waveletstudio.codeplex.com/


यहाँ 256 बिट छवि-हैश के साथ एक सरल दृष्टिकोण है (MD5 में 128 बिट है)

  1. चित्र 16x16 पिक्सेल का आकार बदलें

  1. काले / सफेद रंग को कम करें (जो इस कंसोल आउटपुट में सही / गलत के बराबर है )

  1. बूलियन मानों को List<bool> में पढ़ें - यह हैश है

कोड :

public static List<bool> GetHash(Bitmap bmpSource)
{
    List<bool> lResult = new List<bool>();         
    //create new image with 16x16 pixel
    Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16));
    for (int j = 0; j < bmpMin.Height; j++)
    {
        for (int i = 0; i < bmpMin.Width; i++)
        {
            //reduce colors to true / false                
            lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.5f);
        }             
    }
    return lResult;
}

मुझे पता है, GetPixel इतनी तेज़ नहीं है लेकिन 16x16 पिक्सेल की छवि पर यह अड़चन नहीं होनी चाहिए।

  1. इस हैश की अन्य छवियों से मानों की तुलना करें और एक सहिष्णुता जोड़ें। (पिक्सेल की संख्या जो अन्य हैश से भिन्न हो सकती है)

कोड:

List<bool> iHash1 = GetHash(new Bitmap(@"C:\mykoala1.jpg"));
List<bool> iHash2 = GetHash(new Bitmap(@"C:\mykoala2.jpg"));

//determine the number of equal pixel (x of 256)
int equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);

इसलिए यह कोड समान छवियों को खोजने में सक्षम है:

  • विभिन्न फ़ाइल प्रारूप (जैसे jpg, png, bmp)
  • रोटेशन (90, 180, 270), क्षैतिज / ऊर्ध्वाधर फ्लिप - i और j के पुनरावृति क्रम को बदलकर
  • विभिन्न आयाम (एक ही पहलू की आवश्यकता है)
  • अलग संपीड़न (जेपीआर कलाकृतियों की तरह गुणवत्ता के नुकसान के मामले में सहिष्णुता की आवश्यकता होती है) - आप एक ही छवि होने के लिए 99% समानता और एक अलग होने के लिए 50% स्वीकार कर सकते हैं।
  • रंग बदलकर गीज़्ड हो गया और दूसरा रास्ता गोल (क्योंकि चमक रंग से स्वतंत्र है)

अद्यतन / सुधार:

थोड़ी देर के लिए इस पद्धति का उपयोग करने के बाद मैंने कुछ सुधारों को देखा जो किया जा सकता है

  • अधिक प्रदर्शन के लिए GetPixel replacing
  • प्रदर्शन सुधार के लिए पूरी छवि को पढ़ने के बजाय exeif-thumbnail का उपयोग करना
  • प्रकाश और अंधेरे के बीच अंतर करने के लिए 0.5f को सेट करने के बजाय - सभी 256 पिक्सेल के अलग-अलग माध्यिका चमक का उपयोग करें। अन्यथा अंधेरे / प्रकाश चित्रों को एक ही माना जाता है और यह उन छवियों का पता लगाने में सक्षम होता है जिनमें एक परिवर्तित चमक होती है।
  • यदि आपको fast गणनाओं की आवश्यकता है, तो bool[] या List<bool> यदि आपको मेमोरी को बचाने की आवश्यकता के साथ बहुत सारे हैश स्टोर करने की आवश्यकता है, तो एक Bitarray उपयोग करें क्योंकि एक बूलियन बिट में संग्रहीत नहीं है, यह एक byte लेता है!




hash