c ++ - Konverterer YUV til BGR eller RGB i OpenCV

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et tv-capture-kort, der har et feed, der kommer ind som et YUV-format. Jeg har set andre stillinger her ligner dette spørgsmål og forsøgt at prøve alle mulige metoder, men ingen af ​​dem gav et klart billede. I øjeblikket var de bedste resultater med OpenCV cvCvtColor(scr, dst, CV\_YUV2BGR) funktionsopkald.


Jeg er for øjeblikket uvidende om YUV-format og for at være ærlig forvirrer mig lidt, da det ser ud til at det gemmer 4 kanaler, men er kun 3? Jeg har medtaget et billede fra opfangningskortet for at håbe, at nogen kan forstå, hvad der muligvis foregår, som jeg kunne bruge til at udfylde emnerne.


YUV til BGR konverteret billede


Foderet kommer ind via et DeckLink Intensity Pro-kort og åbnes i en C ++-applikation ved brug af OpenCV i et Windows 7-miljø.


Opdater


Jeg har set på en wikipediaartikel om disse oplysninger og forsøgt at bruge formlen i min ansøgning. Nedenfor er kodeblokken med den modtagne udgang fra den. Eventuelle råd er meget værdsat.


BYTE* pData;

    videoFrame->GetBytes((void**)&pData);

    m\_nFrames++;

    printf("Num Frames executed: \%d
", m\_nFrames);

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


Forsøgt RGB-konvertering

Bedste reference


Det ser ud til, at du 'dekoderer en YUV422-strøm som YUV444. Prøv denne ændring til den kode, du gav:


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


Jeg er ikke sikker på, at du har dine konstanter korrekt, men i værste fald vil dine farver være slukket - billedet skal være genkendeligt.

Andre referencer 1


I nyere version af OPENCV er der en indbygget funktion, der kan bruges til at gøre YUV til RGB konvertering


cvtColor(src,dst,CV\_YUV2BGR\_YUY2);


Angiv YUV formatet efter underskriften, som denne CV\_YUYV2BGR\_xxxx

Andre referencer 2


BlackMagic Intensity-softwaren returnerer YUVY '-format i bmdFormat8BitYUV, så 2 kilder pixels bliver komprimeret til 4byte - jeg tror ikke openCVs cvtColor kan håndtere dette.


Du kan enten gøre det selv eller bare ringe til Intensity software ConvertFrame () funktionen


rediger: Y U V gemmes normalt som

Indtast billedbeskrivelse her


Der er en Y (lysstyrke) for hver pixel, men kun en U og V (farve) for hver alternativ pixel i rækken.


Så hvis data er en usigneret char, der peger på begyndelsen af ​​hukommelsen som vist ovenfor.


pixel 1, Y=data

Andre referencer 3

U=data [[+1]] V=data [[+3]]

pixel 2, Y=data [[+2]] U=data [[+1]] V=data [[+3]]


Brug derefter de YUV-> RGB-koefficienter, du brugte i din prøvekode.

Andre referencer 4


Det kan være den forkerte vej, men mange mennesker (jeg mener ingeniører) blander YUV med YCbCr.


Forsøge at


cvCvtColor(src, dsc, CV\_YCbCr2RGB) 


eller CV\_YCrCb2RGB eller måske en mere eksotisk type.

Andre referencer 5


Måske er nogen forvirret af farvemodeller YCbCr og YUV.
Opencv håndterer ikke YCbCr . I stedet har det YCrCb , og det implementeret på samme måde som YUV i opencv.


Fra opencv kilder https://github.com/Itseez/opencv/blob/2.4/modules/imgproc/src/color.cpp#L3830:[15]


case CV\_BGR2YCrCb: case CV\_RGB2YCrCb:
case CV\_BGR2YUV: case CV\_RGB2YUV:
    // ...
    // 1 if it is BGR, 0 if it is RGB
    bidx = code == CV\_BGR2YCrCb || code == CV\_BGR2YUV ? 0 : 2; 
    //... converting to YUV with the only difference that brings 
    //    order of Blue and Red channels (variable bidx)


Men der er endnu en ting at sige.

Der er i øjeblikket en fejl ved konvertering CV\_BGR2YUV og CV\_RGB2YUV i OpenCV-afdelingen 2.4. *. [16]


På nuværende tidspunkt anvendes denne formel i implementering:


Y = 0.299B + 0.587G + 0.114R
U = 0.492(R-Y)
V = 0.877(B-Y)


Hvad det skal være (ifølge wikipedia): [17]


Y = 0.299R + 0.587G + 0.114B
U = 0.492(B-Y)
V = 0.877(R-Y)


Kanalerne Røde og Blå er fejlplaceret i den implementerede formel.


Mulig løsning for at konvertere BGR-> YUV, mens fejlen ikke er løst:


  cv::Mat source = cv::imread(filename, CV\_LOAD\_IMAGE\_COLOR);
  cv::Mat yuvSource;    
  cvtColor(source, yuvSource, cv::COLOR\_BGR2RGB); // rearranges B and R in the appropriate order
  cvtColor(yuvSource, yuvSource, cv::COLOR\_BGR2YUV);
  // yuvSource will contain here correct image in YUV color space