2012-01-12 10 views
7

figureआरजीबी मूल्यों पर बिलीनेर इंटरपोलेशन कैसे करें?

देखते हुए काले पिक्सेल का समन्वय करता है, मैं गणितीय समीकरण y = mx + स के माध्यम से नीले पिक्सेल के मूल्यों समन्वय को जोड़ सकता है। लेकिन नए आरजीबी पिक्सेल मूल्यों के बारे में क्या? मैं ब्लू पिक्सल के लिए भारित औसत आरजीबी मान प्राप्त करने के बारे में कैसे जा सकता हूं, यह देखते हुए कि काले पिक्सेल आरजीबी मान इस तरह के आंकड़े दिए गए हैं?

किसी भी मदद की बहुत सराहना की जाती है। अग्रिम में धन्यवाद।

+0

आप शायद एक उचित रंग स्थान (जैसे एचएसवी) को बदलने की आवश्यकता को बनाए रखा, वहाँ प्रक्षेप हैं, और तब आरजीबी के लिए वापस परिवर्तित। –

+3

उम, नहीं, बिलकुल नहीं। आपको एचएसवी, या किसी अन्य रंग स्थान में कनवर्ट करने की आवश्यकता नहीं है। यह सच है कि कुछ रिक्त स्थानों में अलग-अलग गुण होते हैं। –

उत्तर

8

आप आर, जी, और बी के लिए गणना करते हुए स्वतंत्र रूप से मूल्यों को अलग करते हैं। उदाहरण के लिए, (200,50,10) और (0,0,0) उपज (100,25,5) के बीच आधा रास्ते इंटरपोल करना)।

+0

क्या यह आरजीबी कलर स्पेस में सही तरीके से काम करने जा रहा है? क्या आपको एचएसवी स्पेस में इस तरह की चीज नहीं करनी चाहिए? –

+0

यह आरजीबी में मेरे लिए ठीक काम करता है; मैंने इसे अतीत में छवि प्रसंस्करण के लिए उपयोग किया है। –

+3

@ पॉल - नहीं। किसी अन्य रंग स्थान में कनवर्ट करने की आवश्यकता नहीं है। आरजीबी किसी भी रंग की जगह के रूप में मान्य है। यह किसी ऐसे व्यक्ति द्वारा कहा जाता है जो रंग इंटरपोलेशन के तरीकों में एक विशेषज्ञ है - मैं। आरजीबी रिक्त स्थान में इंटरपोलेशन का एकमात्र मुद्दा जिसे किसी को चिंता करने की ज़रूरत है, वह न्यूट्रल के साथ क्या होता है, और यह केवल इंटरपोलेशन के प्रकार के लिए प्रासंगिक है। उदाहरण के लिए, ट्रिलिनर इंटरपोलेशन न्यूट्रल के लिए आरजीबी रिक्त स्थान के साथ समस्याएं पैदा करता है। –

12

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

विशेषता जो आरजीबी और इंटरपोलेशन से संबंधित है वह यह है कि एक तटस्थ को एक बिंदु के रूप में परिभाषित किया जाता है जैसे आर = जी = बी। ट्रिलिनर इंटरपोलेंट में उस तटस्थ अक्ष के साथ अधिकतम त्रुटि होगी, और आमतौर पर रंग स्थान के माध्यम से तटस्थ पथ के साथ त्रुटियों के लिए एक विशेषता (स्कैलप्ड) आकार होगा।

तो हम 3-डी में कैसे इंटरपोलेट करते हैं? मुझे लगता है कि एक रंग अंतरिक्ष में अंक की नियमित जाली में interpolating है। उस स्थिति में, कोई एक घन की पहचान कर सकता है जिसमें कोई भी बिंदु शामिल है। यदि आप बिंदुओं के बिखरे हुए सेट के अंदर इंटरपोलेट कर रहे हैं, तो सबसे सरल समाधान आमतौर पर उन बिंदुओं का त्रिकोण बनाने के लिए होता है, फिर किसी दिए गए टेट्राहेड्रॉन के भीतर एक सादगी (रैखिक) इंटरपोलेशन करने के लिए। उच्च आदेश इंटरपोलेंट वैसे भी समस्याग्रस्त हैं, क्योंकि वे कुछ परिस्थितियों में रंग की समस्याएं पैदा कर सकते हैं। उदाहरण के लिए कोई ग्रेडियेंट के साथ रिवर्सल देखना नहीं चाहेगा। ऐसा इसलिए हो सकता है क्योंकि रिंगिंग अपेक्षाकृत उच्च वक्रता वाले क्षेत्रों में स्पलीन आधारित इंटरपोलेंट के साथ एक गंभीर समस्या है। और यदि गैमट मैपिंग शामिल है, तो ऐसे संक्रमण निश्चित रूप से एक मुद्दा होंगे। यहां तक ​​कि यदि कोई गैमट मैपिंग आवश्यक नहीं है, तब भी इसके साथ जुड़े मुद्दों के मुद्दे हैं।

बिखरे हुए डेटा से डोमेन के त्रिकोण बनाने के कई तरीके हैं। अल्फा आकार डेलाउने त्रिभुज पर आधारित होते हैं, और एक उचित विकल्प हैं। लेकिन यह मानते हुए कि आपके पास नियमित जाली है और ट्रिलिनर इंटरपोलेशन करना चाहते हैं, समस्या 3-डी में एक साधारण घन के अंदर इंटरपोलेशन को कम कर देती है।

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

चाल है, हम बिलीनेर इंटरपोलेंट की एक जोड़ी के बीच इंटरपोलिंग करके एक त्रिलिनर इंटरपोलेंट का निर्माण करते हैं। हम उन किनारों के साथ बिंदुओं की एक जोड़ी के बीच रैखिक रूप से इंटरपोल करके उन बिलीनेर इंटरपोलेंट्स का निर्माण करते हैं, और फिर उनके बीच तीसरा इंटरपोलेशन करते हैं। तो वास्तव में, हम 7 सरल रैखिक इंटरपोलेशंस से बना एक ट्रिलिनर इंटरपोलेंट का इलाज कर सकते हैं। दिलचस्प बात यह है कि कोई यह दिखा सकता है कि इससे कोई फर्क नहीं पड़ता कि हम किस अक्ष को पहले इंटरपोलेशन करते हैं। इस प्रकार हम पहले आर के साथ इंटरपोलेट कर सकते हैं, फिर बी, फिर जी अक्ष, या किसी अन्य ऑर्डर का चयन कर सकते हैं - ट्रिलिनर इंटरपोलेंट अद्वितीय और किसी भी ऑर्डर के लिए समान होगा। (यह बिलीनेर इंटरपोलेंट के बारे में भी सच है।)

तो चाल है, हम अंक के दो triads के बीच एक रैखिक इंटरपोलेशन कैसे करते हैं? सबसे पहले, हमें यह निर्धारित करने की आवश्यकता है कि हम उन बिंदुओं के बीच रेखा खंड पर कहां हैं। उदाहरण के लिए, हमारे रंग स्थान में दो बिंदुओं पर विचार करें जो घन के लाल (आर) किनारे के साथ झूठ बोलते हैं। मैं, इस प्रकार उन बिंदुओं के लिए एक ही मान आप से पता चला है का उपयोग करेंगे:

Q1 = [66, 51, 77] 
Q2 = [55, 66, 77] 

ये मान हम के बीच, अनिवार्य रूप से अपनी मैपिंग में उत्पादन को जोड़ कर रहे हैं, लेकिन हम भी जहां उन बिंदुओं में झूठ जानने की जरूरत इनपुट आरजीबी अंतरिक्ष। तो मान लेते हैं कि इन निर्देशांक, घन वे से आया के निर्देशांक के आधार पर कर रहे हैं:

P1 = [0, 0, 0] 
P2 = [1, 0, 0] 

इस में 3-डी एक इकाई घन है के रूप में मैं इसे लिखा है, इसलिए अन्य बिंदुओं

पर झूठ होगा
P3 = [0, 1, 0] 
P4 = [1, 1, 0] 
P5 = [0, 0, 1] 
P6 = [1, 0, 1] 
P7 = [0, 1, 1] 
P8 = [1, 1, 1] 

बेशक, कोई भी सामान्य घन भी काम करता है, और इसके लिए एक वास्तविक घन होने का कोई कारण नहीं है। कोई 3-डी दाएं, आयताकार 4 तरफा प्रिज्म भी यहां काम करेगा। आप चीजों को इकाई घन में हमेशा बदल सकते हैं।

अब, मान लीजिए कि हम क्यू 1 और क्यू 2 द्वारा परिभाषित डोमेन में पी 1 और पी 2 के बीच घन के इस किनारे के साथ इंटरपोलेट करना चाहते हैं? उस किनारे के साथ कुछ बिंदु उठाओ। आप देख सकते हैं कि केवल आर इन बिंदुओं के बीच उस किनारे के साथ बदलता है, इसलिए हम केवल उस बिंदु पर आर के मूल्य की परवाह करते हैं जिस पर हम इंटरपॉल करते हैं। किनारे के साथ दूरी के प्रतिशत के संदर्भ में इसके बारे में सोचें। इंटरपोलेशन केवल दो अंतराल, एक रैखिक संयोजन का भारित औसत है। इस प्रकार लाल चैनल में 1 0 से किनारे के साथ आर के लाल मूल्य के साथ बात करने के लिए, हमारे प्रक्षेप

Q(r) = Q1*(1-r) + Q2*r 

आप देख सकते हैं, जब आर 1/2 है, इस प्रकार किनारे के साथ रास्ते के मध्य में हो जाएगा, हमारे interpolant तार्किक रूप से

Q(1/2,0,0) = (Q1 + Q2)/2 

को कम करेगा, मध्य मूल्य दो समाप्ति बिंदुओं की औसत हो जाएगा। आप स्वतंत्र आउटपुट चैनल के लिए स्वतंत्र रूप से इंटरपोलेशन करते हैं।

Q(1/2,0,0) = ([66, 51, 77] + [55, 66, 77])/2 = [60.5, 58.5, 77] 

क्या यह एंडपॉइंट्स को पुनर्प्राप्त करने के लिए काम करता है? बिलकुल यह करता है। जब आर = 0 या आर = 1, आप देख सकते हैं कि यह वास्तव में संबंधित Q1 या Q2 देता है।

फिर से, आप ट्रिलिनर इंटरपोलेंट के लिए चार लाल किनारों में से प्रत्येक के साथ इस इंटरपोलेशन करते हैं। फिर आप दो और अधिक इंटरपोलेशंस करते हैं, शायद ऊपर के चार परिणामों के हरे रंग के किनारों के साथ। अंत में, आप ट्रिलिनर इंटरपोलेंट प्राप्त करने के लिए नीले किनारे के साथ एक और अधिक इंटरपोलेशन करते हैं। फिर, यह महत्वपूर्ण नहीं है कि आप इंटरपोलेशन की धुरी चुनते हैं। नतीजा गणितीय रूप से वही होगा।

क्या आप एक बिलीनेर इंटरपोलेशन पर रोक रहे थे, तो ऐसे तीन रैखिक इंटरपोलेशन हैं।हां, यह सच है कि एक बिलीनेर इंटरपोलेंट, या एक त्रिलिनेर इंटरपोलेंट आयताकार (या घन) के सभी 4 (या 8) कोनों के भारित संयोजन के रूप में भी किया जा सकता है। इसे भविष्य में छोड़ा जा सकता है।

+0

हाय वुडचिप्स, मेरे बिलीनेर इंटरपोलेशन एल्गोरिदम जिसे मैंने अभी तक कोड किया है, केवल 2x के कारक द्वारा छवि स्केलिंग की अनुमति देता है। मैं इसे 3x, 4x जैसे पूर्णांक गुणकों तक विस्तारित करना चाहता हूं .. एन बार। मैं मूल छवि से उपलब्ध पिक्सल को नई छवि के नए बफर स्थान और इन पिक्सेल के बीच में सफेद रिक्त स्थान निर्धारित करने के तरीके को समझने के तरीके से अटक गया हूं। यह अभी के लिए हार्डकोडिंग है, क्या आप थोड़ी देर के लिए मेरे शिक्षक हो सकते हैं? मैं वास्तव में अब खो गया हूँ। :) जल्द ही आपके उत्तर की आशा में। यदि आप एक नज़र रखना चाहते हैं तो मैं कोड भेज सकता हूं। – f0rfun

1
/* 
    resize an image using bilinear interpolation 
*/ 
void bilerp(unsigned char *dest, int dwidth, int dheight, unsigned char *src, int swidth, int sheight) 
{ 
    float a, b; 
    float red, green, blue, alpha; 
    float dx, dy; 
    float rx, ry; 
    int x, y; 
    int index0, index1, index2, index3; 

    dx = ((float) swidth)/dwidth; 
    dy = ((float) sheight)/dheight; 
    for(y=0, ry = 0;y<dheight-1;y++, ry += dy) 
    { 
    b = ry - (int) ry; 
    for(x=0, rx = 0;x<dwidth-1;x++, rx += dx) 
    { 
     a = rx - (int) rx; 
     index0 = (int)ry * swidth + (int) rx; 
     index1 = index0 + 1; 
     index2 = index0 + swidth;  
     index3 = index0 + swidth + 1; 

     red = src[index0*4] * (1.0f-a)*(1.0f-b); 
     green = src[index0*4+1] * (1.0f-a)*(1.0f-b); 
     blue = src[index0*4+2] * (1.0f-a)*(1.0f-b); 
     alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b); 
     red += src[index1*4] * (a)*(1.0f-b); 
     green += src[index1*4+1] * (a)*(1.0f-b); 
     blue += src[index1*4+2] * (a)*(1.0f-b); 
     alpha += src[index1*4+3] * (a)*(1.0f-b); 
     red += src[index2*4] * (1.0f-a)*(b); 
     green += src[index2*4+1] * (1.0f-a)*(b); 
     blue += src[index2*4+2] * (1.0f-a)*(b); 
     alpha += src[index2*4+3] * (1.0f-a)*(b); 
     red += src[index3*4] * (a)*(b); 
     green += src[index3*4+1] * (a)*(b); 
     blue += src[index3*4+2] * (a)*(b); 
     alpha += src[index3*4+3] * (a)*(b); 

     red = red < 0 ? 0 : red > 255 ? 255 : red; 
     green = green < 0 ? 0 : green > 255 ? 255 : green; 
     blue = blue < 0 ? 0 : blue > 255 ? 255 : blue; 
     alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; 

     dest[(y*dwidth+x)*4] = (unsigned char) red; 
     dest[(y*dwidth+x)*4+1] = (unsigned char) green; 
     dest[(y*dwidth+x)*4+2] = (unsigned char) blue; 
     dest[(y*dwidth+x)*4+3] = (unsigned char) alpha; 
    } 
    index0 = (int)ry * swidth + (int) rx; 
    index1 = index0; 
    index2 = index0 + swidth;  
    index3 = index0 + swidth; 

    red = src[index0*4] * (1.0f-a)*(1.0f-b); 
    green = src[index0*4+1] * (1.0f-a)*(1.0f-b); 
    blue = src[index0*4+2] * (1.0f-a)*(1.0f-b); 
    alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b); 
    red += src[index1*4] * (a)*(1.0f-b); 
    green += src[index1*4+1] * (a)*(1.0f-b); 
    blue += src[index1*4+2] * (a)*(1.0f-b); 
    alpha += src[index1*4+3] * (a)*(1.0f-b); 
    red += src[index2*4] * (1.0f-a)*(b); 
    green += src[index2*4+1] * (1.0f-a)*(b); 
    blue += src[index2*4+2] * (1.0f-a)*(b); 
    alpha += src[index2*4+3] * (1.0f-a)*(b); 
    red += src[index3*4] * (a)*(b); 
    green += src[index3*4+1] * (a)*(b); 
    blue += src[index3*4+2] * (a)*(b); 
    alpha += src[index3*4+3] * (a)*(b); 

    red = red < 0 ? 0 : red > 255 ? 255 : red; 
    green = green < 0 ? 0 : green > 255 ? 255 : green; 
    blue = blue < 0 ? 0 : blue > 255 ? 255 : blue; 
    alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; 

    dest[(y*dwidth+x)*4] = (unsigned char) red; 
    dest[(y*dwidth+x)*4+1] = (unsigned char) green; 
    dest[(y*dwidth+x)*4+2] = (unsigned char) blue; 
    dest[(y*dwidth+x)*4+3] = (unsigned char) alpha; 
    } 
    index0 = (int)ry * swidth + (int) rx; 
    index1 = index0; 
    index2 = index0 + swidth;  
    index3 = index0 + swidth; 

    for(x=0, rx = 0;x<dwidth-1;x++, rx += dx) 
    { 
    a = rx - (int) rx; 
    index0 = (int)ry * swidth + (int) rx; 
    index1 = index0 + 1; 
    index2 = index0;  
    index3 = index0; 

    red = src[index0*4] * (1.0f-a)*(1.0f-b); 
    green = src[index0*4+1] * (1.0f-a)*(1.0f-b); 
    blue = src[index0*4+2] * (1.0f-a)*(1.0f-b); 
    alpha = src[index0*4+3] * (1.0f-a)*(1.0f-b); 
    red += src[index1*4] * (a)*(1.0f-b); 
    green += src[index1*4+1] * (a)*(1.0f-b); 
    blue += src[index1*4+2] * (a)*(1.0f-b); 
    alpha += src[index1*4+3] * (a)*(1.0f-b); 
    red += src[index2*4] * (1.0f-a)*(b); 
    green += src[index2*4+1] * (1.0f-a)*(b); 
    blue += src[index2*4+2] * (1.0f-a)*(b); 
    alpha += src[index2*4+3] * (1.0f-a)*(b); 
    red += src[index3*4] * (a)*(b); 
    green += src[index3*4+1] * (a)*(b); 
    blue += src[index3*4+2] * (a)*(b); 
    alpha += src[index3*4+3] * (a)*(b); 

    red = red < 0 ? 0 : red > 255 ? 255 : red; 
    green = green < 0 ? 0 : green > 255 ? 255 : green; 
    blue = blue < 0 ? 0 : blue > 255 ? 255 : blue; 
    alpha = alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; 

    dest[(y*dwidth+x)*4] = (unsigned char) red; 
    dest[(y*dwidth+x)*4+1] = (unsigned char) green; 
    dest[(y*dwidth+x)*4+2] = (unsigned char) blue; 
    dest[(y*dwidth+x)*4+3] = (unsigned char) alpha; 
    } 

    dest[(y*dwidth+x)*4] = src[((sheight-1)*swidth+swidth-1)*4]; 
    dest[(y*dwidth+x)*4+1] = src[((sheight-1)*swidth+swidth-1)*4+1]; 
    dest[(y*dwidth+x)*4+2] = src[((sheight-1)*swidth+swidth-1)*4+2]; 
    dest[(y*dwidth+x)*4+3] = src[((sheight-1)*swidth+swidth-1)*4+3]; 
} 

कोड यहाँ

https://github.com/MalcolmMcLean/babyxrc/blob/master/src/resize.c

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