OpenCV - 无法正确显示 YUV 图像

OpenCV - Failing to display YUV image correctly

我正在编写一个程序,简要地执行以下操作:

  1. 从 .yuv 文件读取 YUV 4:2:0 帧
  2. 将帧从 YUV 转换为 RGB
  3. 对RGB帧进行一些操作
  4. 显示RGB帧
  5. 重复前面的步骤,直到 .yuv 文件中没有剩余帧

我目前省略了第3步,我现在不对RGB帧进行任何操作。因为我的程序没有以正确的颜色显示框架。

这是我使用 OpenCV 2.1 的代码:

我的代码有什么问题??

我还添加了第一帧的实际颜色和错误颜色的图片。错误的彩色图片是从 YUV 转换为 BGR (CV_YCrCb2BGR) 的结果。但是不幸的是,从 YUV 转换为 RGB (CV_YCrCb2RGB) 没有帮助。

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

第一帧的实际颜色,从 YUV 播放器获取:

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

第一帧颜色错误,我的程序输出:

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

找到了!实际上我发现它已经两个多星期了但是在这里:我正在将 V 组件调整为 Y 组件。

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

经验教训:

永远不要只用一个字母命名变量,单词永远是最好的。