You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NVIDIA NPP库转换YUV420到BGR时如何正确设置rSrcStep参数

解决nppiYUV420ToBGR_8u_P3C3R的NPP_STEP_ERROR问题

问题原因

你手动设置的rSrcStep={1920,1920/2,1920/2}不符合NPP的要求,核心问题在于:OpenCV的cv::Mat为了内存对齐,实际步长(step[0])并不等于图像的像素宽度,而NPP函数对输入步长的内存对齐有严格要求。

正确的rSrcStep设置方法

I420(YUV420P)是平面格式,Y、U、V三个平面在内存中连续存储,且共享同一个Mat的步长(因为整个YUV数据被打包进了一个单通道Mat)。正确的做法是从Mat中提取每个平面的指针和实际步长:

cv::Mat yuvMat(cv::Size(1920, 1080*3/2), CV_8UC1, (void*)data);

// 分离Y、U、V平面的起始指针
Npp8u* pSrcY = yuvMat.data;
Npp8u* pSrcU = yuvMat.data + 1920 * 1080; // Y平面总字节数:宽×高
Npp8u* pSrcV = pSrcU + (1920/2) * (1080/2); // U平面总字节数:(宽/2)×(高/2)

// 获取Mat的实际步长(内存对齐后的数值)
int matStep = yuvMat.step[0];

// 组装rSrcStep数组,三个平面的步长都等于matStep
int rSrcStep[] = {matStep, matStep, matStep};

关键说明

  • I420格式中,U和V平面的像素宽度是原图的一半,但它们存储在同一个连续内存块中,所以步长和Y平面一致,由Mat的内存对齐规则决定,而非单个平面的像素宽度。
  • NPP要求输入步长满足内存对齐(通常是4/8字节的倍数),OpenCV的Mat默认会自动处理内存对齐,直接使用yuvMat.step[0]就能满足要求。

完整调用示例

// 定义ROI尺寸
NppiSize roiSize = {1920, 1080};

// 分配目标BGR内存,获取目标步长
Npp8u* pDstBGR = nullptr;
int nDestStep = 0;
pDstBGR = nppiMalloc_8u_C3(roiSize.width, roiSize.height, &nDestStep);

// 调用转换函数
NppStatus status = nppiYUV420ToBGR_8u_P3C3R(
    pSrcY, rSrcStep[0],
    pSrcU, rSrcStep[1],
    pSrcV, rSrcStep[2],
    pDstBGR, nDestStep,
    roiSize
);

// 错误检查与内存释放
if (status != NPP_NO_ERROR) {
    // 处理错误,比如打印错误码
}
nppiFree(pDstBGR);

内容的提问来源于stack exchange,提问作者wangz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:36:43