使用libyuv缩放1860x1920 YUV420P图像出现绿条纹异常求助
YUV420P缩放后出现绿条纹的问题修复
你的代码里有几个核心错误,直接导致了YUV数据错位,出现绿条纹:
错误点分析
- Y分量长度计算错误:你用
src_width * src_width计算Y分量的字节数,这完全错误。Y分量的大小应该是源宽度 × 源高度,而非宽度平方。 - UV分量起始位置错误:基于上面的错误,U、V分量的起始地址计算全部偏离,导致UV数据读取错位。
- I420Scale的源高度参数传错:调用
I420Scale时,你把源高度传成了src_width,应该传入实际的源高度src_height。 - 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
相关产品推荐
相关产品推荐

