我是一个更新的cuda和它的图像,信号处理库:NPP,现在我试图将YUV420转换成BGR,使用以下功能:
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图像
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,并同时获得步骤
Npp8u *
nppiMalloc_8u_C3(int nWidthPixels, int nHeightPixels, int * pStepBytes);
1080*(3/2),因为当原始RGB图像为w*h时,YUV420大小为w_h_3/2字节
发布于 2022-08-31 21:29:50
将rSrcStep
和nDstStep
设置为以下值:
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映像。
#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
):
https://stackoverflow.com/questions/73552560
复制相似问题