颜色空间转换CSConvert:RGB24转YUV420

  1. 1、参考
  2. 2、视频颜色空间标准BT601/BT709差异
  3. 3、YUV420P转BGR24
  4. 4、BGR24转YUV420P
  5. 5、测试Demo
  6. 6、效果图
  7. 7、分析
  8. THE END!

1、参考

总结各种RGB转YUV的转换公式
RGB24转YUV422转换算法
RGB24转YUV420
总结各种RGB转YUV的转换公式
Android视频编码——RGBA、RGB、BGRA、BGR转YUV420P、YUV420SP
YUV2RGB
YUV420P转换为RGB32格式
YUV与RGB互转各种公式 (YUV与RGB的转换公式有很多种,请注意区别!!!)
YUV格式学习:YUV420P、YV12、NV12、NV21格式转换成RGB24
YUV / RGB 格式及快速转换算法 YUV RGB 转换公式

2、视频颜色空间标准BT601/BT709差异

参考:【Codecs系列】视频格式国际标准:BT601/BT709/BT2020

BT.601格式的颜色空间转换:

    //YUV--->RGB
    //R = 1.164(Y - 16) + 1.596(V - 128)
    //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
    //B = 1.164(Y - 16)                  + 2.018(U - 128)

    //RGB--->YUV
    //Y = 16  + 0.257 * R + 0.504 * G + 0.098 *B          
    //U = 128 - 0.148 * R - 0.291 * G + 0.439 * B          
    //V = 128 + 0.439 * R - 0.368 * G - 0.071 * B

BT.709格式的颜色空间转换:

   // RGB--->YUV
   //  Y = 16  + 0.183 * R + 0.614 * G + 0.062 * B              
   // Cb = 128 - 0.101 * R - 0.339 * G + 0.439 * B             
   // Cr = 128 + 0.439 * R - 0.399 * G - 0.040 * B         

   // YUV--->RGB     
   //  R = 1.164 *(Y - 16) + 1.792 *(Cr - 128)                   
   //  G = 1.164 *(Y - 16) - 0.213 *(Cb - 128) - 0.534 *(Cr - 128)
   //  B = 1.164 *(Y - 16) + 2.114 *(Cb - 128)                  

3、YUV420P转BGR24

/*********************************************************************
/* Function: YUV420pToBGR24
/* Usage: colorspace convertion from YUV420P(I420) to BGR24
/* Parameters:
/*     pYUV   [In]        - source YUV data
/*    pBGR24 [Out]    - output RGB data
/*  width  [In]        - image width
/*    height [In]        - image height
/*
/* Modified: 2019.7.13
/*********************************************************************/
int YUV420pToBGR24(unsigned char *pYUV, unsigned char *pBGR24, int width, int height)
{
    int bgr[3];
    int i,j,k;
    int yIdx, uIdx, vIdx, idx;
    int len = width * height;

    if(!pYUV || !pBGR24 || width < 1 || height < 1)
       return -1;

    unsigned char* yData = pYUV;
    unsigned char* uData = &yData[len];
    unsigned char* vData = &uData[len>>2];

    for(i = 0; i < height; i++)
    {
       for(j = 0; j < width; j++)
         {
           yIdx = i*width+j;
           vIdx = (i/2)*(width/2)+(j/2);
           uIdx = vIdx;

          // BT. 601
           bgr[0] = (298*(yData[yIdx] - 16) + 517 * (uData[uIdx] - 128) + (1<<7)) >> 8; // b分量值
           bgr[1] = (298*(yData[yIdx] - 16) - 208 * (vData[vIdx] - 128) - 100 * (uData[uIdx] - 128) + (1<<7))>>8;// g分量值
           bgr[2] = (298*(yData[yIdx] - 16) + 409 * (vData[vIdx] - 128) + (1<<7))>>8; // r分量值

         for(k=0; k<3; k++)
         {
            idx = (i*width+j)*3+k;
            pBGR24[idx] = CLIP_COLOR(bgr[k]);
         }
      }
    }
    return 0;
}

4、BGR24转YUV420P

/*********************************************************************
/* Function: BGR24toYUV420P
/* Usage: colorspace convertion from BGR24 to YUV420P(I420)
/* Parameters:
/*     pBGR24  [In]        - source RGB data
/*    pYUV    [Out]        - output YUV data
/*  width   [In]        - image width
/*    height  [In]        - image height
/*
/* Modified: 2019.7.13
/*********************************************************************/
int BGR24toYUV420P(unsigned char *pBGR24, unsigned char *pYUV, int width, int height)
{
    int i,j,index;
    unsigned char *bufY, *bufU, *bufV, *bufRGB;
    unsigned char y, u, v, r, g, b;

    if(!pYUV || !pBGR24 || width < 1 || height < 1)
       return -1;

    memset(pYUV, 0 ,width*height*3/2*sizeof(unsigned char));

    bufY = pYUV;
    bufU = bufY + width*height;
    bufV = bufU + (width*height*1/4);

    for(j=0; j < height; j++)
    {
          bufRGB = pBGR24 + width*j*3;
      for(i=0; i < width; i++)
       {
         index = j*width+i;
         b = *(bufRGB++);
         g = *(bufRGB++);
         r = *(bufRGB++);

         y = (unsigned char)((66  * r + 129 * g + 25  * b + 128) >> 8) + 16;
         u = (unsigned char)((-38 * r - 74  * g + 112 * b + 128) >> 8) + 128;
         v = (unsigned char)((112 * r - 94  * g - 18  * b + 128) >> 8) + 128;

         *(bufY++) = CLIP_COLOR(y);
         if(j%2==0 && index%2==0)
          {  
              *(bufU++) = CLIP_COLOR(u);
              *(bufV++) = CLIP_COLOR(v);
          }
       }
    }
    return 0;
}

5、测试Demo

//Demo: This demo used to test YUV2BGR and BGR2YUV
int main(int argc, char *argv[])
{
    FILE *fin, *fou;
    unsigned char *pInYUVBuf, *pYBuf, *pUBuf, *pVBuf;
    unsigned char *pBGRBuf;

    int index, framesize;

    if (argc < 4)
    {
        printf("Usage: ./BGR24toYUV420P.exe inputYUV outputYUV width height\n");
        return -1;
    }

    char* input = argv[1];
    char* output = argv[2];

    int width = atoi(argv[3]);
    int height = atoi(argv[4]);

    Mat mBGR_to_show = Mat(height, width, CV_8UC3);

    fin = fopen(input, "rb");
    if(NULL == fin)
    {
        printf("[demo] error: open fin failed!!!\n");
        return -1;
    }

    fou = fopen(output, "wb");
    if(NULL == fou)
    {
        printf("[demo] error: open fou failed!!!\n");
        return -1;
    }

    pInYUVBuf = (unsigned char*) malloc(width*height*3/2); // YUV buffer
    if(NULL == pInYUVBuf)
    {
        printf("[demo] error: open pInYUVBuffer failed!!!\n");
        return -1;
    }
    pYBuf = pInYUVBuf;
    pUBuf = pYBuf + width*height;
    pVBuf = pUBuf + width*height/4;

    framesize = width*height*3/2;

    pBGRBuf = (unsigned char*) malloc(width*height*3); // BGR buffer
    if(NULL == pBGRBuf)
    {
        printf("[demo] error: open pBGRBuf failed!!!\n");
        return -1;
    }

    index = 0;
    while(framesize == fread(pInYUVBuf,1,width*height*3/2,fin))
    {
        YUV420pToBGR24(pInYUVBuf, pBGRBuf, width, height);
        memcpy(mBGR_to_show.data, pBGRBuf, sizeof(unsigned char)*width*height*3);

        namedWindow("RGB", CV_WINDOW_NORMAL);
        imshow("RGB", mBGR_to_show);
        waitKey(2);

        BGR24toYUV420P(pBGRBuf, pInYUVBuf, width, height);
        fwrite(pInYUVBuf, 1, width*height*3/2, fou);

        index++;
        printf("[demo] info: %d frame process ok!!!\n", index);

    }

    system("pause");
    return 0;   
}

6、效果图

测试Demo运行过程

YUV比较

7、分析

将YUV420P转换成BGR24,然后再转换到YUV420P,会有一定的损失,转换的后的YUV与原始YUV会有1~5个像素值的差异 。


THE END!


本博文只能阅读,谢绝转载,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2963033731@qq.com

文章标题:颜色空间转换CSConvert:RGB24转YUV420

字数:1k

本文作者:Soaring Lee

发布时间:2019-07-12, 22:13:47

最后更新:2021-06-14, 12:13:44

原始链接:https://soaringleefighting.github.io/2019/07/12/【Codecs系列】颜色空间转换CSConvert:RGB24转YUV420P/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏

相册