2015-09-01 90 views
2

我正在玩弄一些不同的圖像格式,並遇到了我發現奇怪的東西。當從RGB轉換到YCbCr然後再轉換到RGB時,結果與我開始的結果非常相似(像素值的差值幾乎總是小於4)。但是,當我從YCbCr轉換爲RGB,然後再轉換回YCbCr時,我經常會得到截然不同的值。有時候數值會超過40個。正在將YCbCr轉換爲RGB可逆?

我不確定這是爲什麼。我的印象是,可以通過YCbCr表達的顏色是RGB中的顏色的一部分,但看起來這是完全錯誤的。 YCbCr中是否有一些已知的顏色子集可以轉換爲RGB然後回到原始值?

我使用的是要轉換的代碼(基於this site):

def yuv2rgb(yuv): 
    ret = [] 
    for rows in yuv: 
    row = [] 
    for y, u, v in rows: 
     c = y - 16 
     d = u - 128 
     e = v - 128 
     r = clamp(1.164*c +   1.596*e, 16, 235) 
     g = clamp(1.164*c - 0.392*d - 0.813*e, 16, 240) 
     b = clamp(1.164*c + 2.017*d   , 16, 240) 
     row.append([r, g, b]) 
    ret.append(row) 
    return ret 

def rgb2yuv(rgb): 
    ret = [] 
    for rows in rgb: 
    row = [] 
    for r, g, b in rows: 
     y = int(0.257*r + 0.504*g + 0.098*b + 16) 
     u = int(-0.148*r - 0.291*g + 0.439*b + 128) 
     v = int(0.439*r - 0.368*g - 0.071*b + 128) 
     row.append([y, u, v]) 
    ret.append(row) 
    return ret 

編輯:

我創造了這個問題的一個基本的3D圖形。所有的點都是小於10的點。它形成了一個非常有趣的形狀。 X是CB,Y是Cr和Z是Y.

Each point is a YCbCr value that converts nicely to RGB and back

+1

你已經在你的'yuv2rgb'計算中使用'y'而不是'C'。我沒有測試過,所以我不知道這是否是問題的嚴重程度。 – beaker

回答

1

據我所知,你應該能夠往返於這兩種格式以最小的精度損失轉換。

該網站you have mentioned有另一套稱爲「RGB到全範圍YCbCr」和「全範圍YCbCr到RGB」的轉換公式,我相信這些是你應該使用的,我認爲它應該使你能夠轉換向前和向後沒有任何問題。

編輯:

既然這些公式沒有爲你工作,我會分享我在Android中使用的RGB和YUV之間的轉換公式:

R = clamp(1 * Y +  0 * (U - 128) + 1.13983 * (V - 128), 0, 255); 
G = clamp(1 * Y + -0.39465 * (U - 128) + -0.5806 * (V - 128), 0, 255); 
B = clamp(1 * Y + 2.03211 * (U - 128) +  0 * (V - 128), 0, 255); 

Y = clamp(0.299 * R + 0.587 * G + 0.114 * B, 0, 255); 
U = clamp(-0.14713 * R + -0.28886 * G + 0.436 * B + 128, 0, 255); 
V = clamp(0.615 * R + -0.51499 * G + -0.10001 * B + 128, 0, 255); 

我已經只是試了一下,似乎來回工作。注意128的總和和減法,因爲這個YUV表示由無符號字節範圍(0..255)組成,RGB也是如此(如通常一樣),所以如果你真的需要(16..235)和(16 .. 240)您的YCbCr範圍,您可能需要另一個公式。

+0

感謝您的諮詢!可悲的是,使用其他公式也不起作用。例如,YCbCR值[0,0,0]變成RGB值[0,134,0],然後再轉換回[78,83,71]的YCbCR值。 – Ric

+1

@Ric我編輯了我的回覆,並且包含了我以前在android中使用的公式,您可能需要檢查它們。 – silvaren

+0

感謝您的代碼。我試過了YUV值[16,16,16]。轉換爲RGB給出[0,125,243],然後轉換回[101,198,39]。 – Ric

1

正如我在我的評論中所說的,你的第一個問題是你使用y而不是cyuv2rgb的循環內進行計算。

第二個問題是,您將RGB值限制在錯誤的範圍內:RGB應該是0..255。

的RGB計算應該是這樣的:

r = clamp(1.164*c +   1.596*e, 0, 255) 
    g = clamp(1.164*c - 0.392*d - 0.813*e, 0, 255) 
    b = clamp(1.164*c + 2.017*d   , 0, 255) 
+0

很大的錯誤!可悲的是,夾住這個範圍仍然會產生不可逆的結果。在[0,0,0]處的YCbCr值在[0,135,0]處轉到RGB,這使得最終的YCbCr值[84,88,78] – Ric

+0

@Ric'[0,0,0]不是有效的YCbCr顏色值。每一個的最小值是16. – beaker

+0

雖然'[16 16 16]'似乎又給了'[84,88,78]'...... – beaker