yuv420转yuv422(yuyv)

网上都是yuv422转yuv420,很少有yuv420转yuv422。
本次从bgr转yuv420,然后基于yuv420转yuv422

int pixeltransform::bgr2yvyu422(cv::Mat srcimg, unsigned char *pdst)
{
    //BGR To I420
    cv::Mat dstimg;
    cv::cvtColor(srcimg, dstimg, cv::COLOR_BGR2YUV_I420);

    int width = srcimg.cols;
    int height = srcimg.rows;

    int nLenY = width * height;
    int nLenU = nLenY / 4;
    unsigned char *i420bytes = dstimg.data;

    unsigned char *i420y = NULL;
    i420y = (unsigned char *)malloc(width * height);
    unsigned char *i420u = NULL;
    i420u = (unsigned char *)malloc(width * height / 4);
    unsigned char *i420v = NULL;
    i420v = (unsigned char *)malloc(width * height / 4);

    memcpy(i420y, i420bytes, nLenY);  //Y
    for (int i = 0; i < nLenU; i++) {
        i420u[i] = i420bytes[nLenY + i];          //U
        i420v[i] = i420bytes[nLenY + nLenU + i];  //V
    }

    int ySrcIndex = 0;
    int uSrcIndex = 0;
    int vSrcIndex = 0;

    int yDstIndex = 0;

    //I420 to YUYV
    for (int i = 0; i < height / 2; i++) {
        int uvWidth = width;
        for (int k = 0; k < uvWidth / 2; k++) {
            // Y
            pdst[yDstIndex] = i420y[ySrcIndex];
            pdst[yDstIndex + uvWidth * 2] = i420y[ySrcIndex + uvWidth];
            yDstIndex++;
            ySrcIndex++;

            // U
            pdst[yDstIndex] = i420u[uSrcIndex];
            pdst[yDstIndex + uvWidth * 2] = i420u[uSrcIndex];
            yDstIndex++;

            // Y
            pdst[yDstIndex] = i420y[ySrcIndex];
            pdst[yDstIndex + uvWidth * 2] = i420y[ySrcIndex + uvWidth];
            yDstIndex++;
            ySrcIndex++;

            // V
            pdst[yDstIndex] = i420v[vSrcIndex];
            pdst[yDstIndex + uvWidth * 2] = i420v[vSrcIndex];
            yDstIndex++;

            uSrcIndex += 1;
            vSrcIndex += 1;
        }
        yDstIndex += uvWidth * 2;
        ySrcIndex += uvWidth;
    }

    free(i420y);
    free(i420u);
    free(i420v);

    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YUV420换为YUV422需要进行插值操作,因为YUV420的色度分量的采样率比亮度分量低,需要将色度分量的采样率提高到与亮度分量相同的水平。 假设有一帧YUV420格式的图像,其大小为WxH,其中Y分量的大小为WxH,U和V分量的大小为W/2xH/2。将其换为YUV422格式的图像,需要将U和V分量的大小提高到WxH/2,然后进行插值操作。 具体步骤如下: 1. 将U和V分量的大小提高到WxH/2,可以使用memcpy函数进行复制操作。 2. 对于每个U和V分量的像素,将其复制到相邻的两个像素中,例如将U[i][j]复制到U[i][2*j]和U[i][2*j+1]中,V分量也做同样的操作。 3. 对于插值后的像素,使用平均值进行插值,例如对于U分量,将U[i][2*j]和U[i][2*j+1]的平均值赋值给U[i][j]。 4. 重复步骤2和步骤3,直到所有的U和V分量的像素都进行了插值操作。 5. 将YUV422格式的图像保存到文件中。 下面是用C++实现的代码: ```cpp void convertYUV420toYUV422(unsigned char* yuv420Data, unsigned char* yuv422Data, int width, int height) { int yIndex, uIndex, vIndex, y, u, v; int yuv422Size = width * height * 2; int uv422Width = width / 2; int uv422Height = height / 2; int uv420Width = width / 2; // 复制Y分量 memcpy(yuv422Data, yuv420Data, width * height); // 复制U和V分量,每个像素复制到相邻的两个像素中 for (int i = 0; i < uv422Height; i++) { for (int j = 0; j < uv422Width; j++) { uIndex = i * uv420Width + j; vIndex = i * uv420Width + j + uv420Width * uv422Height; u = yuv420Data[width * height + uIndex]; v = yuv420Data[width * height + vIndex]; yuv422Data[width * height + i * width + j * 2] = u; yuv422Data[width * height + i * width + j * 2 + 1] = v; } } // 对U和V分量进行插值操作 for (int i = 0; i < uv422Height; i++) { for (int j = 0; j < uv422Width; j++) { u = yuv422Data[width * height + i * width + j * 2]; v = yuv422Data[width * height + i * width + j * 2 + 1]; yuv422Data[width * height + i * width + j * 2] = u; yuv422Data[width * height + i * width + j * 2 + 1] = v; if (j > 0) { u = (yuv422Data[width * height + i * width + (j - 1) * 2] + u) / 2; v = (yuv422Data[width * height + i * width + (j - 1) * 2 + 1] + v) / 2; yuv422Data[width * height + i * width + j * 2 - 1] = u; yuv422Data[width * height + i * width + j * 2 - 1 + 1] = v; } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值