首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >利用NVIDIA库将YUV420(I420)图像转换为BGR时,如何确定YUV420的步长(行大小)

利用NVIDIA库将YUV420(I420)图像转换为BGR时,如何确定YUV420的步长(行大小)
EN

Stack Overflow用户
提问于 2022-08-31 07:52:24
回答 1查看 153关注 0票数 0

我是一个更新的cuda和它的图像,信号处理库:NPP,现在我试图将YUV420转换成BGR,使用以下功能:

代码语言:javascript
运行
复制
NppStatus nppiYUV420ToBGR_8u_P3C3R(const Npp8u * const pSrc[3], int rSrcStep[3], Npp8u * pDst, int nDstStep, NppiSize oSizeROI);

但是我不能决定rSrcStep,我知道它是每个组件的行大小,YUV,但我不确定我是否真的理解它,原来的图像大小是1920x1080 (wxh),我使用opencv Mat来包含YUV图像

代码语言:javascript
运行
复制
cv::Mat(cv::Size(1920,1080*3/2), CV_8UC1, (void*)data)

,对于第一个函数的参数rSrcStep,我尝试rSrcStep={1920,1920/2,1920/2},但是它返回NPP_STEP_ERROR。

ps:对于nDestStep,我使用下面的函数来分配dest buff,并同时获得步骤

代码语言:javascript
运行
复制
Npp8u  * 

    nppiMalloc_8u_C3(int nWidthPixels, int nHeightPixels, int * pStepBytes);

1080*(3/2),因为当原始RGB图像为w*h时,YUV420大小为w_h_3/2字节

EN

回答 1

Stack Overflow用户

发布于 2022-08-31 21:29:50

rSrcStepnDstStep设置为以下值:

代码语言:javascript
运行
复制
int rSrcStep[3] = { COLS, COLS / 2, COLS / 2 };
int nDstStep = COLS * 3;

在哪里COLS = 1920

在YUV420平面格式(I420)中,Y通道的分辨率为全分辨率,U和V通道在每个轴上的分辨率为半分辨率。

示例:

是:

U:

V:

假设数据在内存中是连续的,Y的步长(以字节为单位)等于图像宽度,而U和V的步长等于宽度/2。

测试:

测试代码使用FFmpeg构建原始I420格式的输入映像,并使用FFmpeg将原始BGR输出转换为PNG映像。

代码语言:javascript
运行
复制
#include <stdint.h>
#include <stdio.h>
#include "nppi.h"

#define COLS 192
#define ROWS 108

uint8_t Y[COLS * ROWS];       //Y color channel in host memory
uint8_t U[COLS * ROWS / 4];   //U color channel in host memory
uint8_t V[COLS * ROWS / 4];   //V color channel in host memory

uint8_t BGR[COLS * ROWS * 3];   //BGR output image in host memory

int main()
{
    //Read Y, U, V planes to host memory buffers.
    //Build input sample using FFmpeg first:
    //ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=1 -pix_fmt yuvj420p -f rawvideo in.yuv420p
    ////////////////////////////////////////////////////////////////////////////
    FILE* f = fopen("in.yuv420p", "rb");
    fread(Y, 1, COLS * ROWS, f);
    fread(U, 1, COLS * ROWS / 4, f);
    fread(V, 1, COLS * ROWS / 4, f);
    fclose(f);
    ////////////////////////////////////////////////////////////////////////////

    //Allocate device memory, and copy Y,U,V from host to device.
    ////////////////////////////////////////////////////////////////////////////
    Npp8u* gpuY, * gpuU, * gpuV, * gpuBGR;
    cudaMalloc(&gpuY, COLS * ROWS);
    cudaMalloc(&gpuU, COLS * ROWS / 4);
    cudaMalloc(&gpuV, COLS * ROWS / 4);
    cudaMalloc(&gpuBGR, COLS * ROWS * 3);
    cudaMemcpy(gpuY, Y, COLS * ROWS, cudaMemcpyHostToDevice);
    cudaMemcpy(gpuU, U, COLS * ROWS / 4, cudaMemcpyHostToDevice);
    cudaMemcpy(gpuV, V, COLS * ROWS / 4, cudaMemcpyHostToDevice);
    ////////////////////////////////////////////////////////////////////////////


    //Execute nppiYUV420ToBGR_8u_P3C3R
    ////////////////////////////////////////////////////////////////////////////
    const Npp8u* const pSrc[3] = { gpuY, gpuU, gpuV };
    int rSrcStep[3] = { COLS, COLS / 2, COLS / 2 };
    int nDstStep = COLS * 3;
    NppiSize oSizeROI = { COLS, ROWS };

    NppStatus sts = nppiYUV420ToBGR_8u_P3C3R(pSrc,      //const Npp8u* const pSrc[3], 
                                             rSrcStep,  //int rSrcStep[3], 
                                             gpuBGR,    //Npp8u *pDst, 
                                             nDstStep,  //int nDstStep, 
                                             oSizeROI); //NppiSize oSizeROI);

    if (sts != NPP_SUCCESS) 
    {
        printf("Error: nppiResize_8u_C3R status = %d\n", (int)sts);
    }
    ////////////////////////////////////////////////////////////////////////////


    // Copy BGR output from device to host, and save BGR output to binary file
    // After saving, use FFmpeg to convert the output image from binary to PNG:
    // ffmpeg -y -f rawvideo -video_size 192x108 -pixel_format bgr24 -i out.bgr out.png
    ////////////////////////////////////////////////////////////////////////////
    cudaMemcpy(BGR, gpuBGR, COLS * ROWS * 3, cudaMemcpyDeviceToHost);
    f = fopen("out.bgr", "wb");
    fwrite(BGR, 1, COLS * ROWS * 3, f);
    fclose(f);
    ////////////////////////////////////////////////////////////////////////////


    cudaFree(&gpuY);
    cudaFree(&gpuU);
    cudaFree(&gpuV);
    cudaFree(&gpuBGR);

    return 0;
}

输出(out.png):

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73552560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档