2013-01-31 16 views
6

यह एक स्टैक-आधारित बाढ़ भरने वाले एल्गोरिदम का मेरा सी # कार्यान्वयन है (जिसे मैं विकिपीडिया की परिभाषा पर आधारित करता हूं)। कोडिंग करते समय, मैं केवल इसे देखना चाहता था। और यह किया। फिर, मैं पिक्सेल की संख्या जानना चाहता था जो वास्तव में भर गया था। तो मेरे कोड में, मैंने वापसी प्रकार को int में बदल दिया और "ctr" चर लौटा दिया। लेकिन फिर सीआरटी भरने वाले पिक्सेल की वास्तविक संख्या लगभग दोगुना हो गया (मैंने उन पिक्सल को गिनने के एकमात्र उद्देश्य के साथ एक अलग कार्य किया - बस कुछ जानने के लिए)।बाढ़ भरने के कार्यान्वयन

कोई भी कैसे और क्यों परिवर्तनीय "ctr" को दो बार बढ़ाया जाना चाहिए?

* पिक्सेल कक्षा केवल बिटमैप से पिक्सल के एक्स, वाई, और रंग मानों के लिए एक कंटेनर के रूप में कार्य करती है।

if (popped.color == oldColor) 

लेकिन popped.color हो सकता है (और apperently मामलों के 50% में है) पुरानी:

public Bitmap floodfill(Bitmap image, int x, int y, Color newColor) 
{ 
    Bitmap result = new Bitmap(image.Width, image.Height); 
    Stack<Pixel> pixels = new Stack<Pixel>(); 
    Color oldColor = image.GetPixel(x, y); 
    int ctr = 0; 

    pixels.Push(new Pixel(x, y, oldColor)); 

    while (pixels.Count > 0) 
    { 
     Pixel popped = pixels.Pop(); 

     if (popped.color == oldColor) 
     { 
      ctr++; 
      result.SetPixel(popped.x, popped.y, newColor); 

      pixels.Push(new Pixel(popped.x - 1, popped.y, image.GetPixel(x - 1, y)); 
      pixels.Push(new Pixel(popped.x + 1, popped.y, image.GetPixel(x + 1, y)); 
      pixels.Push(new Pixel(popped.x, popped.y - 1, image.GetPixel(x, y - 1)); 
      pixels.Push(new Pixel(popped.x, popped.y + 1, image.GetPixel(x, y + 1)); 
     } 
    } 

    return result; 
} 
+1

'ctr' का मतलब है, तो' counter', वहाँ यह बुला 'counter' साथ कुछ भी गलत नहीं है। –

उत्तर

7

आप पिक्सेल यहां के रंग की जांच करते हैं। चूंकि आप अपने स्टैक में पिक्सेल डालने पर डुप्लिकेट की जांच नहीं करते हैं, तो आपके पास डुप्लीकेट होंगे। इन डुप्लिकेट को पॉप अप करने पर, रंग विशेषता लंबे समय से सहेजी गई होगी।

शायद यह एक ड्राइंग के साथ स्पष्ट हो जाता है:

graphical explanation

एक उदाहरण के रूप में मैं 9 पिक्सल के साथ एक बिटमैप ले लिया। पहले फलक पर आपके पास पिक्सेल की संख्या है, और दाईं ओर आपके पास स्टैक है।

आप पिक्सेल संख्या 5 के साथ शुरू करते हैं और स्टैक पर पिक्सल 2, 4, 6 और 8 दबाते हैं। फिर आप पिक्सेल 2 बंद करते हैं और 1 और 3 दबाते हैं। अगले चरण में आप 1 पॉप करते हैं और 2 और 4 दबाते हैं (फिर से!)। फिर आप 2 ले सकते हैं और महसूस कर सकते हैं कि इसे धक्का दिया गया था जब इसे पहले से ही नया रंग मिल गया है। (थोड़ा देर हो चुकी है, लेकिन कभी भी देर से बेहतर नहीं) हालांकि: पिक्सेल संख्या। 4 दो बार है और पुराने रंग दो बार याद किया है। तो आप पिक्सेल संख्या 4 लेते हैं और इसे रंगते हैं।

कुछ चरणों बाद में आपके पास छवि भर गई है और अभी भी आपके स्टैक पर कुछ आइटम हैं। चूंकि इन वस्तुओं के अंदर पुराना रंग मान अभी भी संग्रहीत है, इसलिए उन्हें फिर से गिना जाता है।

जबकि मेरे पास स्टैक में गलत ऑर्डरिंग हो सकती है, तो बिंदु मान्य रहता है। आपकी समस्या का

समाधान: त्वरित और गंदे (क्योंकि यह यह अभी भी अक्षम)

if (image.GetPixel(popped.x, popped.y) == oldColor) 

यह पिक्सल ही अगर वर्तमान रंग गलत, याद रंग नहीं है गिना जाता है।

अनुशंसित: अपने पिक्सेल को जांचें कि उन्हें स्टैक पर धक्का देने से पहले रंग की आवश्यकता है या नहीं।

+0

मैं आपके बिंदु को समझता हूं। लेकिन तब popped पिक्सल (जो oldColor है) नहीं फिर से (अगले पुनरावृत्तियों में) के बाद से अपने रंग संपत्ति SetPixel समारोह के साथ बदल गया है धक्का दे दिया जाना चाहिए। – libzz

+0

मैंने अपना जवाब बढ़ाया और उम्मीद है कि चित्रण इसे स्पष्ट करता है। अपनी टिप्पणी के लिए: आप कुछ अंधेरे जादू (या उस बात के लिए विस्तार विधि) Bitmap.SetPixel() क्रियान्वित नहीं किया है निश्चित रूप से अपने पिक्सेल वस्तु में संग्रहीत रंग मूल्य नहीं बदल जाएगा। यह भी पता नहीं है कि आपकी पिक्सेल कक्षा मौजूद है! –

+0

धन्यवाद! मैं देखता हूं कि मैंने अभी अनदेखा किया था। मैं आपके सुझावों का प्रयास करूंगा! ड्राइंग बनाने के प्रयास के लिए और अधिक धन्यवाद!^_^ – libzz

0

सभी पिक्सेल होता है, तो पकड़ रंग इसके निर्माता को पारित कर दिया है, यह रंग अपडेट नहीं करेंगे के बाद पिक्सेल भर जाता है, इसलिए एक बार प्रति पिक्सल की तुलना में अधिक सीटीआर को बढ़ा सकता है।

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

[संपादित करें]

मामले में इसे स्वीकार कर लिया जवाब से स्पष्ट नहीं था, GetPixel एक रंग देता है। इसे उस int के रूप में सोचें जो उस समय पिक्सेल के आरजीबी मान को एन्कोड करता है।

आप तेजी से भरने प्रदर्शन करने के लिए, एक Graphics.FloodFill उदाहरण देखो चाहते हैं।

आप लक्ष्य मैं प्रसंस्करण और वापस फिर से के लिए एक सरणी के लिए अपनी छवि डेटा की प्रतिलिपि की सलाह देते हैं सीख रहा है कर रहे हैं - सबसे क्लासिक छवि एल्गोरिदम बहुत मजेदार GetPixel का उपयोग नहीं कर रहे हैं()।

+0

लेकिन जब मैं पिक्सल धक्का, यह छवि पर ही आधार और पिक्सेल वर्ग से नहीं। तो मुझे लगता है कि वे अब अगर कथन में प्रवेश नहीं करेंगे। इस प्रकार, (माना जाता है) वृद्धि सीटीआर नहीं है। – libzz

+0

हां, हमारे प्रशिक्षक ने हमें बिटमैपडाटा का उपयोग करके बाइट पॉइंटर प्रोसेसिंग सिखाई। मैंने पहले से ही अपना कोड बदल दिया है और यह वास्तव में पहले से डाले गए पिक्सेल डालने के लिए इसे संशोधित करने के बाद भी तेज़ तेज़ काम करता है। मगर आपकी सलाह के लिए धन्यवाद। – libzz

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