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

使用libyuv缩放1860x1920 YUV420P图像出现绿条纹异常求助

YUV420P缩放后出现绿条纹的问题修复

你的代码里有几个核心错误,直接导致了YUV数据错位,出现绿条纹:

错误点分析

  1. Y分量长度计算错误:你用src_width * src_width计算Y分量的字节数,这完全错误。Y分量的大小应该是源宽度 × 源高度,而非宽度平方。
  2. UV分量起始位置错误:基于上面的错误,U、V分量的起始地址计算全部偏离,导致UV数据读取错位。
  3. I420Scale的源高度参数传错:调用I420Scale时,你把源高度传成了src_width,应该传入实际的源高度src_height。
  4. U分量长度计算错误:计算V分量起始位置时,同样误用了宽度平方,正确的U分量大小是(源宽度/2) × (源高度/2),即src_width*src_height/4。

修正后的代码

#define ALIGN32(n) (((n) >> 5) << 5)
// yuv420_image 是装载了YUV420P数据的cv::Mat
int src_width = yuv420_image.cols;
// 从Mat的总行数反推原始图像高度(YUV420P总行数是height*3/2)
int src_height = yuv420_image.rows * 2 / 3;

const uint8_t* src = yuv420_image.data;
const uint8_t* src_y = src;
// Y分量大小:src_width * src_height
const uint8_t* src_u = src_y + src_width * src_height;
// U分量大小:(src_width/2)*(src_height/2) = src_width*src_height/4
const uint8_t* src_v = src_u + src_width * src_height / 4;

// 计算目标尺寸(按1/4缩放后对齐32)
const int kScaleRatio = 4;
int dst_width = ALIGN32(src_width / kScaleRatio);
int dst_height = ALIGN32(src_height / kScaleRatio);

// 创建目标YUV420P的Mat,总行数是dst_height*3/2
cv::Mat yuv420_scaled(dst_height * 3 / 2, dst_width, CV_8UC1);
uint8_t* dst = yuv420_scaled.data;
uint8_t* dst_y = dst;
uint8_t* dst_u = dst_y + dst_width * dst_height;
uint8_t* dst_v = dst_u + dst_width * dst_height / 4;

// 调用I420Scale,注意源高度参数传src_height而非src_width
int result = libyuv::I420Scale(
    src_y, src_width,
    src_u, src_width / 2,
    src_v, src_width / 2,
    src_width, src_height,  // 这里修正源高度为src_height
    dst_y, dst_width,
    dst_u, dst_width / 2,
    dst_v, dst_width / 2,
    dst_width, dst_height,
    libyuv::FilterModeEnum::kFilterNone);

额外说明

  • 验证Mat装载YUV数据是否正确:确保yuv420_image的cols等于原始图像宽度1860,rows等于1920×3/2=2880,数据格式为CV_8UC1。
  • ALIGN32的作用是保证尺寸对齐到32字节,部分硬件编码/渲染要求对齐,这个逻辑本身没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:30:36