nv12图像转RGB888的几种公式

 

NV12 是一种 YUV420 格式,常用于视频编码和处理。在 NV12 格式中,像素数据按照特定的排列方式进行存储。具体来说,NV12 格式将亮度(Y)分量存储在一个平面中,而色度(UV)分量交错存储在另一个平面中。

下面是 NV12 图像排列的简要说明和示意图:

  1. 亮度平面(Y plane):亮度数据以连续的方式存储在一个平面中,每个像素对应一个亮度值。

  2. 色度平面(UV plane):色度数据以交错的方式存储在另一个平面中。对于每个 2x2 的亮度块,只有一个色度块(包含两个色度值)与之对应。

示意图:

 Y平面(亮度):
    +---+---+---+---+
    | Y0| Y1| Y2| Y3|
    +---+---+---+---+
    | Y4| Y5| Y6| Y7|
    +---+---+---+---+
    | Y8| Y9|Y10|Y11|
    +---+---+---+---+
    |Y12|Y13|Y14|Y15|
    +---+---+---+---+

    UV平面(色度):
    +---+---+
    | U0| V0|
    +---+---+
    | U1| V1|
    +---+---+
    | U2| V2|
    +---+---+
    | U3| V3|
    +---+---+

1.公式1

    int frameSize = width * height;
    int y, u, v;
    int r, g, b;
    int index = 0;

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            y = (int)nv12_data[i * width + j];
            u = (int)nv12_data[frameSize + (i / 2) * width + j / 2 * 2];
            v = (int)nv12_data[frameSize + (i / 2) * width + j / 2 * 2 + 1];

            int v_r = v - 128;
            r = y + v_r + ((v_r * 103) >> 8);
            r = range_limit(r);

            int u_g = u - 128;
            int v_g = v - 128;
            g = y + ((u_g * 88) >> 8) - ((v_g * 183) >> 8);
            g = range_limit(g);

            u_g = u - 128;
            b = y + u_g + ((u_g * 198) >> 8);
            b = range_limit(b);


            QRgb pixelValue = qRgb(r, g, b);

            //设置像素值
            qimage->setPixel(j, i, pixelValue);

        }
    }

2.公式2

    int frameSize = width * height;
    int y, u, v;
    int r, g, b;
    int index = 0;

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            y = (int)nv12_data[i * width + j];
            u = (int)nv12_data[frameSize + (i / 2) * width + j / 2 * 2];
            v = (int)nv12_data[frameSize + (i / 2) * width + j / 2 * 2 + 1];

            r = y + 1.402 * (v - 128);
            g = y - 0.344 * (u - 128) - 0.714 * (v - 128);
            b = y + 1.772 * (u - 128);

           if (r < 0) r = 0;
           if (g < 0) g = 0;
           if (b < 0) b = 0;
           if (r > 255) r = 255;
           if (g > 255) g = 255;
           if (b > 255) b = 255;


            QRgb pixelValue = qRgb(r, g, b);

            //设置像素值
            qimage->setPixel(j, i, pixelValue);

        }
    }

3.公式3

    int y_size = width * height;
    int uv_size = (width / 2) * (height / 2);

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int index = i * width + j;
            int Y = nv12_data[index];
            int U = nv12_data[y_size + (i/2) * (width/2) + (j/2)] - 128;
            int V = nv12_data[y_size + uv_size + (i/2) * (width/2) + (j/2)] - 128;

            int R = (int)(Y + 1.402 * V);
            int G = (int)(Y - 0.344136 * U - 0.714136 * V);
            int B = (int)(Y + 1.772 * U);

            R = R < 0 ? 0 : (R > 255 ? 255 : R);
            G = G < 0 ? 0 : (G > 255 ? 255 : G);
            B = B < 0 ? 0 : (B > 255 ? 255 : B);

            int rgb_index = index * 3;
           QRgb pixelValue = qRgb(R, G, B);

            //设置像素值
            qimage->setPixel(j, i, pixelValue);
        }
    }

4.公式4

    int imageSize = width * height;
      int chromaSize = imageSize / 2;

      unsigned char* pY = nv12_data; // Y 分量在前,位置固定
      unsigned char* pUV = nv12_data + imageSize; // UV 分量在后面,位置可以计算出来

      int uvIndex = 0;

      for (int y = 0; y < height; y++)
      {
          for (int x = 0; x < width; x++)
          {
              int yIndex = y * width + x;
              int uvOffset = (y / 2) * width + (x / 2) * 2;

              int colorY = pY[yIndex];
              int colorU = pUV[uvOffset];
              int colorV = pUV[uvOffset + 1];

              int colorR = (int)(colorY + 1.370705 * (colorV - 128));
              int colorG = (int)(colorY - 0.698001 * (colorV - 128) - 0.337633 * (colorU - 128));
              int colorB = (int)(colorY + 1.732446 * (colorU - 128));

              colorR = qBound(0, colorR, 255);
              colorG = qBound(0, colorG, 255);
              colorB = qBound(0, colorB, 255);

              int pixelIndex = yIndex * 3;

              qimage->bits()[pixelIndex + 0] = colorR;
              qimage->bits()[pixelIndex + 1] = colorG;
              qimage->bits()[pixelIndex + 2] = colorB;

              if (x % 2 == 0 && y % 2 == 0) uvIndex++;
          }
      }

 

你可能感兴趣的:(IMAGE,图像处理)