2011-08-12 15 views
11

पीआईएल v1.1.7 द्वारा उपयोग किए गए एल्गोरिदम को 'धोया गया' परिणाम मिलते हैं। ffmpeg का उपयोग कर एक ही स्रोत डेटा को परिवर्तित करते समय यह सही दिखता है। mplayer का उपयोग ffmpeg पर समान परिणाम देता है (शायद वे नीचे एक ही लाइब्रेरी का उपयोग करते हैं)। इससे मेरा मानना ​​है कि पीआईएल कलर स्पेस रूपांतरणों को भर रहा है। रूपांतरण libImaging/ConvertYCbCr.c के स्रोत वाली प्रतीत हो रहा है:पीआईएल का कलर स्पेस रूपांतरण वाईसीबीसीआर -> आरजीबी

/* JPEG/JFIF YCbCr conversions 

    Y = R * 0.29900 + G * 0.58700 + B * 0.11400 
    Cb = R * -0.16874 + G * -0.33126 + B * 0.50000 + 128 
    Cr = R * 0.50000 + G * -0.41869 + B * -0.08131 + 128 

    R = Y +      + (Cr - 128) * 1.40200 
    G = Y + (Cb - 128) * -0.34414 + (Cr - 128) * -0.71414 
    B = Y + (Cb - 128) * 1.77200 

*/ 

इस स्रोत में सिर्फ एक टिप्पणी है, बेशक यह सी कोड है और वास्तविक समारोह देखने तालिकाओं के साथ लागू किया गया है गुणा मैट्रिक्स नहीं (static INT16 R_Cr आदि संक्षिप्तता के लिए कतरना):

void 
ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels) 
{ 
    int x; 
    UINT8 a; 
    int r, g, b; 
    int y, cr, cb; 

    for (x = 0; x < pixels; x++, in += 4, out += 4) { 

     y = in[0]; 
     cb = in[1]; 
     cr = in[2]; 
     a = in[3]; 

     r = y + ((   R_Cr[cr]) >> SCALE); 
     g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE); 
     b = y + ((B_Cb[cb]   ) >> SCALE); 

     out[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r; 
     out[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g; 
     out[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b; 
     out[3] = a; 
    } 
} 

मैं googled है लेकिन वहाँ 'सही' जिस तरह से इस रंग अंतरिक्ष रूपांतरण करने के बारे में भ्रम की स्थिति का एक बहुत हो रहा है। तो मेरा सवाल है, उपर्युक्त सही है - और यदि नहीं तो बेहतर तरीका क्या है?


संपादित करें: मार्क Ransom द्वारा प्रदान की लिंक पढ़ने के बाद, मुझे पता चला कि परस्पर विरोधी परिभाषाओं कि क्या आप YCbCr की पूरी रेंज का उपयोग करें या मान्य श्रेणी के लिए बाहर क्लैंप के आधार पर मौजूद हैं। अधिक जानकारी के लिए नीचे दिए गए लिंक देखें:

यह जनहित याचिका संस्करण गलत कलन विधि का उपयोग कर रहा है लगता है, इसलिए मैं रूपांतरण जो सही देता है के लिए अपने खुद के समारोह उपलब्ध कराई गई परिणाम देख रहे हैं ("एसडीटीवी" संस्करण)।

from numpy import dot, ndarray, array 

def yuv2rgb(im, version='SDTV'): 
    """ 
    Convert array-like YUV image to RGB colourspace 

    version: 
     - 'SDTV': ITU-R BT.601 version (default) 
     - 'HDTV': ITU-R BT.709 version 
    """ 
    if not im.dtype == 'uint8': 
     raise TypeError('yuv2rgb only implemented for uint8 arrays') 

    # clip input to the valid range 
    yuv = ndarray(im.shape) # float64 
    yuv[:,:, 0] = im[:,:, 0].clip(16, 235).astype(yuv.dtype) - 16 
    yuv[:,:,1:] = im[:,:,1:].clip(16, 240).astype(yuv.dtype) - 128 

    if version.upper() == 'SDTV': 
     A = array([[1.,     0., 0.701   ], 
        [1., -0.886*0.114/0.587, -0.701*0.299/0.587], 
        [1., 0.886,        0.]]) 
     A[:,0] *= 255./219. 
     A[:,1:] *= 255./112. 
    elif version.upper() == 'HDTV': 
     A = array([[1.164,  0., 1.793], 
        [1.164, -0.213, -0.533], 
        [1.164, 2.112,  0.]]) 
    else: 
     raise Exception("Unrecognised version (choose 'SDTV' or 'HDTV')") 

    rgb = dot(yuv, A.T) 
    result = rgb.clip(0, 255).astype('uint8') 

    return result 
+1

क्या यह http://en.wikipedia.org/wiki/YCbCr पर किसी एक तंत्र से मेल खाता है? –

उत्तर

7

आप विकिपीडिया की परिभाषाओं को देखें, तो आप YCbCr के लिए दो परस्पर विरोधी परिभाषाओं देखते हैं कि देख सकते हैं: भविष्य पाठकों के लिए उपयोग करने के लिए कोड, नीचे शामिल थे। ITU-R BT.601 परिभाषा फुटरूम और हेडरूम प्रदान करने के लिए मान 16-235 के मान को संपीड़ित करती है, जबकि JPEG संस्करण पूर्ण सीमा 0-255 का उपयोग करता है। यदि आप जेपीईजी के सूत्र के उपयोग से बीटी.601 स्पेस में मूल्यों को डीकोड करना चाहते थे, तो परिणाम निश्चित रूप से धोया जाएगा।

+1

धन्यवाद, यह मुझे सही रास्ते पर मिला, और मुझे यहां विभिन्न मानकों (ऑक्सीमोरॉन?) का स्पष्ट स्पष्टीकरण मिला -> http://www.equasys.de/colorconversion.html – wim

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