2011-11-07 46 views
5

我一直在試圖解決一個YUV422到RGB轉換問題約一個星期。我訪問過許多不同的網站,並從每個網站獲得不同的公式。如果任何人有任何建議,我會很高興聽到他們。下面的公式給我一個圖像,其中全部是紫色或綠色。從這一刻起,我一直無法找到一個能讓我找回正確的RGB圖像的公式。我在下面列出了我所有的各種代碼。正確的YUV422到RGB轉換

//for(int i = 0; i < 1280 * 720 * 3; i=i+3) 
    //{ 
    // /*m_RGB->imageData[i] = pData[i] + pData[i+2]*((1 - 0.299)/0.615); 
    // m_RGB->imageData[i+1] = pData[i] - pData[i+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[i+2]*((0.299*(1 - 0.299))/(0.615*0.587)); 
    // m_RGB->imageData[i+2] = pData[i] + pData[i+1]*((1 - 0.114)/0.436);*/ 

    // m_RGB->imageData[i] = pData[i] + 1.403 * (pData[i+1] - 128); 
    // m_RGB->imageData[i+1] = pData[i] + 0.344 * (pData[i+1] - 128) - 0.714 * (pData[i+2] - 128); 
    // m_RGB->imageData[i+2] = pData[i] + 1.773 * (pData[i+2] - 128); 
    //} 

    for(int i = 0, j=0; i < 1280 * 720 * 3; i+=6, j+=4) 
    { 
     /*m_RGB->imageData[i] = pData[j] + pData[j+3]*((1 - 0.299)/0.615); 
     m_RGB->imageData[i+1] = pData[j] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587)); 
     m_RGB->imageData[i+2] = pData[j] + pData[j+1]*((1 - 0.114)/0.436); 
     m_RGB->imageData[i+3] = pData[j+2] + pData[j+3]*((1 - 0.299)/0.615); 
     m_RGB->imageData[i+4] = pData[j+2] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587)); 
     m_RGB->imageData[i+5] = pData[j+2] + pData[j+1]*((1 - 0.114)/0.436);*/ 

     /*m_RGB->imageData[i] = pData[j] + 1.403 * (pData[j+3] - 128); 
     m_RGB->imageData[i+1] = pData[j] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128); 
     m_RGB->imageData[i+2] = pData[j] + 1.773 * (pData[j+1] - 128); 
     m_RGB->imageData[i+3] = pData[j+2] + 1.403 * (pData[j+3] - 128); 
     m_RGB->imageData[i+4] = pData[j+2] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128); 
     m_RGB->imageData[i+5] = pData[j+2] + 1.773 * (pData[j+1] - 128);*/ 

     BYTE Cr = pData[j+3] - 128; 
     BYTE Cb = pData[j+1] - 128; 
     /*m_RGB->imageData[i] = pData[j] + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5); 
     m_RGB->imageData[i+1] = pData[j] - ((Cb >> 2) + (Cb >> 4) + (Cb >> 5)) - ((Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5)); 
     m_RGB->imageData[i+2] = pData[j] + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6); 
     m_RGB->imageData[i+3] = pData[j+2] + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5); 
     m_RGB->imageData[i+4] = pData[j+2] - ((Cb >> 2) + (Cb >> 4) + (Cb >> 5)) - ((Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5)); 
     m_RGB->imageData[i+5] = pData[j+2] + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);*/ 

     /*int R1 = clamp(1 * pData[j] + 0 * Cb + 1.4 * Cr, 0, 255), R2 = clamp(1 * pData[j+2] + 0 * Cb + 1.4 * Cr, 0, 255); 
     int G1 = clamp(1 * pData[j] - 0.343 * Cb - 0.711 * Cr, 0, 255), G2 = clamp(1 * pData[j+2] - 0.343 * Cb - 0.711 * Cr, 0, 255); 
     int B1 = clamp(1 * pData[j] + 1.765 * Cb + 0 * Cr, 0, 255), B2 = clamp(1 * pData[j+2] + 1.765 * Cb + 0 * Cr, 0, 255);*/ 

     /*int R1 = clamp(pData[j] + 1.403 * (pData[j+3] - 128), 0, 255), R2 = clamp(pData[j+2] + 1.403 * (pData[j+3] - 128), 0, 255); 
     int G1 = clamp(pData[j] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128), 0, 255), G2 = clamp(pData[j+2] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128), 0, 255); 
     int B1 = clamp(pData[j] + 1.773 * (pData[j+1] - 128), 0, 255), B2 = clamp(pData[j+2] + 1.773 * (pData[j+1] - 128), 0, 255);*/ 

     int R1 = clamp((298 * (pData[j] - 16) + 409 * (pData[j+3] - 128) + 128) >> 8, 0, 255), R2 = clamp((298 * (pData[j+2] - 16) + 409 * (pData[j+3] - 128) + 128) >> 8, 0, 255); 
     int G1 = clamp((298 * (pData[j] - 16) - 100 * (pData[j+1] - 128) - 208 * (pData[j+3] - 128) + 128) >> 8, 0, 255), G2 = clamp((298 * (pData[j+2] - 16) - 100 * (pData[j+1] - 128) - 208 * (pData[j+3] - 128) + 128) >> 8, 0, 255); 
     int B1 = clamp((298 * (pData[j] - 16) + 516 * (pData[j+1] - 128) + 128) >> 8, 0, 255), B2 = clamp((298 * (pData[j+2] - 16) + 516 * (pData[j+1] - 128) + 128) >> 8, 0, 255); 

     //printf("R: %d, G: %d, B: %d, R': %d, G': %d, B': %d \n", R1, G1, B1, R2, G2, B2); 

     m_RGB->imageData[i] = (char)R1; 
     m_RGB->imageData[i+1] = (char)G1; 
     m_RGB->imageData[i+2] = (char)B1; 
     m_RGB->imageData[i+3] = (char)R2; 
     m_RGB->imageData[i+4] = (char)G2; 
     m_RGB->imageData[i+5] = (char)B2; 

     /*m_RGB->imageData[i] = (char)(clamp(1.164 * (pData[j] - 16) + 1.793 * (Cr), 0, 255)); 
     m_RGB->imageData[i+1] = (char)(clamp(1.164 * (pData[j] - 16) - 0.534 * (Cr) - 0.213 * (Cb), 0, 255)); 
     m_RGB->imageData[i+2] = (char)(clamp(1.164 * (pData[j] - 16) + 2.115 * (Cb), 0, 255)); 
     m_RGB->imageData[i+3] = (char)(clamp(1.164 * (pData[j+2] - 16) + 1.793 * (Cr), 0, 255)); 
     m_RGB->imageData[i+4] = (char)(clamp(1.164 * (pData[j+2] - 16) - 0.534 * (Cr) - 0.213 * (Cb), 0, 255)); 
     m_RGB->imageData[i+5] = (char)(clamp(1.164 * (pData[j+2] - 16) + 2.115 * (Cb), 0, 255));*/ 
    } 

任何幫助,非常感謝。

+1

什麼是YUV數據的來源,什麼是目的地?例如,如果目標是Windows,則需要使用BGR順序而不是RGB。 –

+0

YUV來自Decklink Intensity Pro採集卡。我也嘗試翻轉BGR/RGB值,但沒有幫助。這是在Windows盒子上完成的 – Seb

+0

如果您使用的是decklink SDK,爲什麼不簡單地使用作爲API一部分的ConvertFrame方法? – ronag

回答

5

一些線索,以幫助你前進:

您正在使用的Cb混淆鉻。

假設UYVY/422

Y1 = data[j+0]; 
Cr = data[j+1]; 
Y2 = data[j+2]; 
Cb = data[j+3]; 

您的轉換計算是奇怪的,和不正確的高清。

對於SD

R = max(0, min(255, 1.164(Y - 16) + 1.596(Cr - 128))); 
G = max(0, min(255, 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128))); 
B = max(0, min(255, 1.164(Y - 16) + 2.018(Cr - 128))); 

對於HD

R = max(0, min(255, 1.164(Y - 16) + 1.793(Cr - 128))); 
G = max(0, min(255, 1.164(Y - 16) - 0.534(Cr - 128) - 0.213(Cb - 128))); 
B = max(0, min(255, 1.164(Y - 16) + 2.115(Cr - 128))); 

你可以簡單地使用ConvertFrame這是DECKLINK SDK的一部分。

+0

謝謝你的回答幫助我。問題:高清是指1280x720或1920x1080?那麼4k呢?順便說一句Y1CrY2Cb爲yuy2工作我!雖然基於MSDN Cb是'你',它應該是Y1CbY2Cr,但這樣做顯示藍色,而不是紅色!你能解釋爲什麼訂單扭曲嗎?或者msdn Cb ='u'無效?1 –

1

假設打包422我沒有看到任何塊正確地採樣輸入數據。在打包422中,輸入數據將變爲Y1U1Y2V1Y3U2Y4V2,其中整個圖像是全分辨率的Y(亮度)圖像,並且每個U和V各有一個水平分辨率的一半。

此處,我將開始:打開輸入的交替值,並提取灰度圖像:

for (uint i = 0, j = 0; i < 1280 * 720 * 3; i += 3, j += 2) { 
    m_RGB->imageData[i] = pData[j]; 
    m_RGB->imageData[i+1] = pData[j]; 
    m_RGB->imageData[i+2] = pData[j]; 
} 

一旦你有一個調整的產生灰度圖像,然後通過看pData[j+1]pData[j+3]引進U和V (或者在偶數像素上,pData[j-1]pData[j+1])。簡化這就是爲什麼一些算法一次執行兩個YUV像素。

工作考慮提取U和V圖像,並適當地重新採樣他們到全分辨率產生444圖像。簡單地爲相鄰像素複製U和V就像通過複製像素來升級。

(注420一樣,其他安排擁有更爲複雜的共址)

+0

這給我一個灰度圖像,但看起來好像高斯模糊被應用到它。 – Seb

0

我也掙扎與轉換

// Get the bytes 
var u = bytes[0]; 
var y1 = bytes[1]; 
var v = bytes[2]; 
var y2 = bytes[3]; 

// Convert, cast to signed byte is important! 
var r = y + (1.403 * (sbyte)v); 
var g = y - (0.344 * (sbyte)u) - (0.714 * (sbyte)v); 
var b = y + (1.770 * (sbyte)u); 

if (r < 0) 
    r = 0; 
else if (r > 255) 
    r = 255; 

if (g < 0) 
    g = 0; 
else if (g > 255) 
    g = 255; 

if (b < 0) 
    b = 0; 
else if (b > 255) 
    b = 255; 

return Color.FromArgb((byte)r, (byte)g, (byte)b); 

uvsbytey只是一個byte

+0

您是說這是正確的轉換還是您試圖使用此轉換掙扎? –

+0

這是正確的版本 –

3

你的問題是,有很多YUV422格式。您必須找到確切的一個(您正在使用的特定視頻的FOURCC索引),然後找出正確的解碼方法。

你可以做的是從你的主板上保存一些視頻,在VLC中打開它,然後查看編解碼器的詳細信息以找到確切使用的FOURCC。

http://www.fourcc.org/yuv.php