Search code examples
opencvrgbyuv

OpenCV - Failing to display YUV image correctly


I am writing a program that does the following in brief:

  1. read YUV 4:2:0 frame from .yuv file
  2. convert frame from YUV to RGB
  3. make some operations on RGB frame
  4. display the RGB frame
  5. repeat the previous steps until there is no frame left in the .yuv file

I omitted the 3rd step currently, I do not make any operations on RGB frames right now. Because my program does not display the frame in correct colors.

Here is my code which is using OpenCV 2.1:

What is wrong with my code??

I also added pictures of actual colors and wrong colors of the first frame. Wrong colored picture is result of conversion from YUV to BGR (CV_YCrCb2BGR). But converting from YUV to RGB (CV_YCrCb2RGB) does not help, unfortunately.

int main()
{
    int iFrameWidth = 640;
    int iFrameHeight = 480;

    .
    .
    .

    FILE *fYUV0 = fopen( "C:\\YUV_Videos\\flamenco2_0.yuv", "rb" );

    char *cFileBuffer0 = new char[ iFrameWidth*iFrameHeight*3/2 ];

    IplImage *iplY420Frame = cvCreateImageHeader( cvSize(iFrameWidth  , iFrameHeight  ), IPL_DEPTH_8U, 1 );
    IplImage *iplU420Frame = cvCreateImageHeader( cvSize(iFrameWidth/2, iFrameHeight/2), IPL_DEPTH_8U, 1 );
    IplImage *iplV420Frame = cvCreateImageHeader( cvSize(iFrameWidth/2, iFrameHeight/2), IPL_DEPTH_8U, 1 );

    IplImage *iplY444Frame = cvCreateImage( cvSize(iFrameWidth, iFrameHeight), IPL_DEPTH_8U, 1 );
    IplImage *iplU444Frame = cvCreateImage( cvSize(iFrameWidth, iFrameHeight), IPL_DEPTH_8U, 1 );
    IplImage *iplV444Frame = cvCreateImage( cvSize(iFrameWidth, iFrameHeight), IPL_DEPTH_8U, 1 );

    IplImage *iplYUV444Frame = cvCreateImage( cvSize(iFrameWidth, iFrameHeight), IPL_DEPTH_8U, 3 );

    IplImage *iplRGBFrame0 = cvCreateImage( cvSize(iFrameWidth, iFrameHeight), IPL_DEPTH_8U, 3 );

    .
    .
    .

    while( fread(cFileBuffer0, 1, iFrameWidth*iFrameHeight*3/2, fYUV0) )
    {
        cvSetData( iplY420Frame, cFileBuffer0, iFrameWidth );
        cvSetData( iplU420Frame, cFileBuffer0 + iFrameWidth*iFrameHeight, iFrameWidth/2 );
        cvSetData( iplV420Frame, cFileBuffer0 + iFrameWidth*iFrameHeight*5/4, iFrameWidth/2 );      
        cvResize( iplY420Frame, iplY444Frame );
        cvResize( iplU420Frame, iplU444Frame );
        cvResize( iplV420Frame, iplY444Frame );
        cvMerge( iplY444Frame, iplU444Frame, iplV444Frame, NULL, iplYUV444Frame );
        cvCvtColor( iplYUV444Frame, iplRGBFrame0, CV_YCrCb2BGR );

        .
        .
        .

        cvNamedWindow( "View0" );
        cvShowImage( "View0", iplRGBFrame0 );
        cvWaitKey( 1000/25 );
    }//end-of-while

    cvDestroyWindow( "View0" );
    return 0;
}//end-of-main

Actual colors of the first frame, acquired from a YUV Player:

http://i59.tinypic.com/2n7ee6h.jpg

Wrong colors of the first frame, output of my program:

http://i58.tinypic.com/29lzcqp.jpg


Solution

  • I have found it! Actually it has been more than two weeks since I found it but here it is: I was resizing V component into Y component.

    ...
    cvResize( iplY420Frame, iplY444Frame );
    cvResize( iplU420Frame, iplU444Frame );
    cvResize( iplV420Frame, iplY444Frame ); // iplY444Frame must be corrected as iplV444Frame
    ...
    

    Lessons learned:

    Never name variables with only one letter, words are always the best.