2011-11-07 55 views
5

Tôi đã cố gắng giải quyết YUV422 thành vấn đề chuyển đổi RGB trong khoảng một tuần. Tôi đã truy cập nhiều trang web khác nhau và đã nhận các công thức khác nhau từ mỗi trang web. Nếu bất cứ ai khác có bất cứ đề nghị nào tôi sẽ vui mừng khi nghe về họ. Các công thức bên dưới cung cấp cho tôi hình ảnh có màu tím hoặc màu xanh lá cây tổng thể. Tính đến thời điểm này tôi đã không thể tìm thấy một công thức cho phép tôi lấy lại một hình ảnh RGB thích hợp. Tôi đã bao gồm tất cả các đoạn mã khác nhau của tôi bên dưới.Sửa YUV422 sang chuyển đổi 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));*/ 
    } 

Bất kỳ trợ giúp nào được đánh giá cao.

+1

Nguồn dữ liệu YUV là gì và điểm đến là gì? Ví dụ, nếu đích đến là Windows, bạn cần sử dụng thứ tự BGR hơn là RGB. –

+0

YUV đến từ thẻ chụp Decklink Intensity Pro. Tôi cũng đã cố gắng để lật các giá trị BGR/RGB và nó đã không giúp đỡ. Điều này đang được thực hiện trên một hộp Windows – Seb

+0

Nếu bạn đang sử dụng SDK decklink, tại sao bạn không chỉ đơn giản là sử dụng phương pháp ConvertFrame là một phần của API? – ronag

Trả lời

5

Một số manh mối để giúp bạn:

Bạn đang nhầm lẫn Cr với Cb.

Giả sử UYVY/422

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

tính chuyển đổi của bạn là lạ, và không chính xác cho HD.

Đối với 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))); 

Đối với 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))); 

Bạn chỉ có thể sử dụng ConvertFrame mà là một phần của Biên soạn SDK.

+0

cảm ơn câu trả lời của bạn đã giúp tôi. Câu hỏi: HD có nghĩa là 1280x720 hoặc 1920x1080? những gì về 4k? btw thứ tự Y1CrY2Cb đã làm việc cho tôi với yuy2! mặc dù dựa trên msdn Cb là 'u' và nó được cho là Y1CbY2Cr nhưng làm điều đó cho thấy màu xanh thay cho màu đỏ! bạn có thể giải thích tại sao thứ tự bị xoắn? hoặc msdn Cb = 'u' không hợp lệ? 1 –

1

Giả sử đóng gói 422 Tôi không thấy bất kỳ khối nào của bạn lấy mẫu dữ liệu đầu vào chính xác. Trong gói 422 dữ liệu đầu vào sẽ đi Y1U1Y2V1 Y3U2Y4V2 trong đó ảnh tổng thể là ảnh Y (luma) ở độ phân giải đầy đủ và mỗi ảnh U và V ở độ phân giải ngang một nửa.

Đây là nơi tôi sẽ bắt đầu: Giải nén các giá trị luân phiên của các đầu vào và trích xuất một hình ảnh màu xám:

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]; 
} 

khi bạn đã có điều chỉnh để tạo ra một hình ảnh màu xám sau đó giới thiệu U và V bằng cách nhìn vào pData[j+1]pData[j+3] (hoặc, ngay cả pixel, pData[j-1]pData[j+1]). Đơn giản hóa đó là lý do tại sao một số thuật toán thực hiện hai điểm ảnh YUV tại một thời điểm.

Khi rằng hoạt động xem xét trích xuất hình ảnh U và V và định dạng lại chúng thành độ phân giải đầy đủ để tạo ra hình ảnh 444. Chỉ cần nhân bản U và V cho các pixel liền kề giống như nâng cấp bằng cách nhân đôi pixel.

(Lưu ý rằng các thỏa thuận khác như 420 thậm chí còn phức tạp hơn đồng chọn địa điểm)

+0

Điều này đã cho tôi một hình ảnh thang độ xám, nhưng mọi thứ có vẻ như một hiệu ứng Gaussian blur được áp dụng cho nó. – Seb

0

Tôi cũng phải vật lộn với việc chuyển đổi

// 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); 

uvsbyte, và y chỉ là một byte.

+0

Bạn có nói đây là chuyển đổi đúng hay bạn đang cố gắng sử dụng chuyển đổi này? –

+0

Đây là phiên bản chính xác –

3

Vấn đề của bạn là có rất nhiều định dạng YUV422 ngoài đó. Bạn phải tìm chính xác (chỉ số FOURCC cho video cụ thể bạn đang sử dụng), và sau đó tìm ra cách chính xác để giải mã nó.

Điều bạn có thể làm là lưu một số video từ bảng của mình, mở nó trong VLC và xem chi tiết Codec để tìm chính xác FOURCC được sử dụng.

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

Các vấn đề liên quan