2012-05-26 5 views
8

मेरे पास एक ऐसा एप्लिकेशन है जो चित्रों की गैलरी लेता है (सभी जेपीईजी में) और प्रत्येक संभावित जोड़े के बीच समानता स्कोर देते हैं। समय पर हर बिंदु पर, केवल एक जोड़ी का चयन किया जा सकता है और इसके समानता स्कोर प्रदर्शित होता है।हैश बिटमैप्स के लिए एक सस्ता/तेज़ तरीका?

दो छवियों की तुलना करने वाले एल्गोरिदम में एक निश्चित प्रदर्शन लागत होती है, जैसे कि एक जोड़ी की तुलना करने में कुछ सेकंड लगते हैं।

जब दो चित्रों चुने गए हैं: जोड़ी की तुलना में कभी नहीं किया गया है

  1. हैं, स्कोर से पता चलता "अभी तक रन बनाए नहीं।"। उपयोगकर्ता "स्कोर" बटन पर क्लिक कर सकता है और जोड़ी को उस थ्रेड पर भेजा जाएगा जो गणना के लिए स्कोर को कतारबद्ध करता है। उदाहरण: http://db.tt/gb1Yk6yx
  2. यदि जोड़ी वर्तमान में कतार में गणना की जाती है, तो स्कोर फ़ील्ड "कंप्यूटिंग ..." दिखाता है। उदाहरण: http://db.tt/OvS1qGP3
  3. यदि जोड़ी की तुलना की गई है, तो जोड़ी से जुड़ा स्कोर दिखाया गया है। उदाहरण: http://db.tt/m2OQGybW

उदाहरण (जब एक बैच कर): http://db.tt/iD67SdCp

तो एक स्कोर गणना की नहीं किया गया है, और एक उपयोगकर्ता क्लिक "स्कोर", क्षेत्र में बदल जाएगा "कम्प्यूटिंग ..." तो गणना पूर्ण होने पर स्कोर प्रदर्शित करेगा।

स्कोर के क्षेत्र में कुछ भी प्रदर्शित करने से पहले, जब दो जोड़े चुने जाते हैं, तो उनके संलग्न बिटमैप को हैश मैप पर भेजा जाता है जो सत्यापित करता है कि उन दो बिटमैप्स में पहले से ही एक संलग्न स्कोर है, इस मामले में यह बस इसे वापस कर देता है। यदि कोई स्कोर नहीं है, तो नौकरी कतार में भेजी जाती है।

यह जानने के लिए कि कैश में स्कोर मौजूद है या नहीं, मुझे जोड़ों को हैश करने का एक तरीका ढूंढना होगा ताकि मैं कैश को देखने के लिए परिणामी कुंजी का उपयोग कर सकूं। यही वह जगह है जहां मेरी समस्या है। समझने के लिए, दो बिटमैप की हैशिंग तेज होनी चाहिए। अन्यथा, मैं सिर्फ गणना की एक और परत जोड़ रहा हूँ। लेकिन, जिस तरह से मैं दो बिटमैप को हैश करने के लिए करता हूं उन्हें उन्हें बाइट सरणी में भेजना और एमडी 5 चेकसम प्राप्त करना है। इस तरह:

private Long getHashKey(Bitmap first, Bitmap second){ 

    // TODO this IS costly, it render useless the cache optimization. 
    // also, it doesn't detect that comp(A,B) is the same as comp(B,A). 
    // much work to do here. 

    if(D) Profiling.start(TAG, "getHashKey"); 

    ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
    first.compress(Bitmap.CompressFormat.JPEG, 100, stream); 

    byte[] firstArray = stream.toByteArray(); 
    second.compress(Bitmap.CompressFormat.JPEG, 100, stream); 

    byte[] secondArray = stream.toByteArray(); 
    byte[] bitmapBuffer = new byte[firstArray.length + secondArray.length]; 

    System.arraycopy(firstArray, 0, bitmapBuffer, 0, firstArray.length); 

    System.arraycopy(secondArray, 0, bitmapBuffer, 
      firstArray.length, secondArray.length); 

    Adler32 md5Hash = new Adler32(); 
    md5Hash.update(bitmapBuffer); 
    long hashKey = md5Hash.getValue(); 

    if(D) Profiling.stop(); 

    return hashKey; 
} 

हालांकि, इस विधि, रूपरेखा मैंने किया था के अनुसार, 53 के बारे में एमएस चलाने के लिए खर्च, जो यूआई काफी अप्रिय है कि में एक अंतराल का कारण बनता है। अधिक विस्तृत प्रोफाइलिंग में, मैंने पाया कि कंप्यूटिंग समय का लगभग 95% compress विधियों में किया जाता है। हालांकि, मुझे बिटमैप्स का समर्थन करने वाले बाइट्स को पाने का दूसरा तरीका नहीं मिला है।

05-26 17:56:13.220: D/Profiling(9458): Profile for ImageCompareActivity.getHashKey: 
05-26 17:56:13.220: D/Profiling(9458): >   Count : 1996 calls 
05-26 17:56:13.220: D/Profiling(9458): > Total runtime : 105765140 us 
05-26 17:56:13.220: D/Profiling(9458): > Avg runtime : 52988 us 

मुझे पता है कि बिशमैप काफी क्रूर है। लेकिन मुझे हैशिंग फ़ंक्शंस के बारे में बहुत कुछ पता नहीं है, और बिटमैप के कौन से हिस्से मैं फ़ाइलों की विशिष्ट पहचान करने के लिए उपयोग कर सकते हैं। मैं फ़ाइल नाम या ऐसा कुछ उपयोग नहीं करना चाहता, क्योंकि मैं अंततः डेटाबेस में उन बिटमैप्स को भेजना चाहता हूं।

[अद्यतन 1] मुझे ऑब्जेक्ट.hashCode() के बारे में पता नहीं था। अब, मैंने इस तरह की विधि को संशोधित किया:

private Integer getHashKey(Bitmap first, Bitmap second){ 

    if(D) Profiling.start(TAG, "getHashKey"); 

    Integer hashKey = new Integer(
      1013 * (first.hashCode())^1009 * (second.hashCode())); 

    if(D) Profiling.stop(); 

    return hashKey; 
} 

जो लगभग 18 के लिए औसत में चलता है।

+0

क्या आप Bitmap.getPixels का उपयोग कर सकते हैं? यह स्याही की एक सरणी देता है (ठीक है, वास्तव में यह आपके द्वारा पारित की जाने वाली चींटियों की एक सरणी को पॉप्युलेट करता है, लेकिन दोस्तों के बीच क्या है?)। – Iain

+2

बिटमैप्स को स्टोर करने के लिए डेटाबेस का उपयोग करने के बाद आप बिटमैप्स को स्टोर करने के लिए फ़ाइलों का उपयोग करते समय फ़ाइल पंक्ति का उपयोग क्यों नहीं करते हैं, और पंक्ति की प्राथमिक कुंजी (या डेटाबेस में ध्वज) का उपयोग करते हैं? –

+0

'copyPixelsToBuffer' विधि में देखें जो' बाइटबफर 'स्वीकार करता है। इसके अलावा, जेबी पर जगह है; किसी भी कारण से आप फ़ाइल नामों का उपयोग नहीं करना चाहते हैं? –

उत्तर

1

Here हैशिंग के बारे में एक हालिया प्रश्न है। एडलर शायद जेआरई में निर्मित सबसे तेज़ तरीका है। क्या आपने हैश को प्री-कंप्यूटिंग और छवि के साथ या डेटाबेस में संग्रहीत किया है?

+1

.NET रनटाइम बदलने की कोशिश की है? यह एक एंड्रॉइड सवाल है। –

+0

तो यह है। मैंने सोचा कि मैं सी # द्वारा फ़िल्टर कर रहा था। अपडेट किया गया। – bmm6o

+0

अच्छा लिंक, धन्यवाद! – AntoineG

0

एंड्रॉइड के समान एएस का उपयोग करने के बारे में कैसे?

संबंधित मुद्दे