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

如何使用OpenCV将YV12图像转为BGRA?非连续三分量平面怎么处理

实现方案

当YV12的Y、U、V分量分别存储在三个独立非连续平面时,你可以选择以下两种方式调用cvtColor完成转换:


方案1:全版本兼容,仅需一次内存拷贝(推荐)

该方案兼容性最强,常规分辨率下内存拷贝开销可忽略,是生产环境常用选择:

// 提前定义你持有的独立平面参数:
// uint8_t* y_ptr:Y分量起始指针
// int y_stride:Y分量每行实际占用字节数(步长)
// uint8_t* v_ptr:V分量起始指针(YV12格式V分量顺序在U之前)
// int v_stride:V分量每行步长
// uint8_t* u_ptr:U分量起始指针
// int u_stride:U分量每行步长
// int width:图像宽度,int height:图像高度,需为偶数

int uv_width = width / 2;
int uv_height = height / 2;

// 1. 申请连续的YV12格式缓冲区
cv::Mat yuv_continuous(height * 3 / 2, width, CV_8UC1);

// 2. 逐行拷贝Y分量到连续缓冲区
for (int row = 0; row < height; row++) {
    memcpy(yuv_continuous.ptr<uint8_t>(row), y_ptr + row * y_stride, width);
}

// 3. 逐行拷贝V分量到连续缓冲区
uint8_t* v_dst = yuv_continuous.ptr<uint8_t>(height);
for (int row = 0; row < uv_height; row++) {
    memcpy(v_dst + row * width, v_ptr + row * v_stride, uv_width);
}

// 4. 逐行拷贝U分量到连续缓冲区
uint8_t* u_dst = yuv_continuous.ptr<uint8_t>(height + uv_height);
for (int row = 0; row < uv_height; row++) {
    memcpy(u_dst + row * width, u_ptr + row * u_stride, uv_width);
}

// 5. 调用原有转换逻辑即可
cv::Mat dst;
// OpenCV 3.x及以下用CV_YUV2BGRA_YV12,4.x及以上用cv::COLOR_YUV2BGRA_YV12
cv::cvtColor(yuv_continuous, dst, CV_YUV2BGRA_YV12);

方案2:零拷贝方案(适合内存紧张的嵌入式场景)

该方案无需额外申请连续缓冲区,直接复用原有三个平面的内存,仅支持OpenCV 3.4及以上版本:

int uv_width = width / 2;
int uv_height = height / 2;

// 1. 直接构造三个分量的Mat,复用原有内存,非连续平面只需传入正确步长即可
cv::Mat y_mat(height, width, CV_8UC1, y_ptr, y_stride);
cv::Mat v_mat(uv_height, uv_width, CV_8UC1, v_ptr, v_stride);
cv::Mat u_mat(uv_height, uv_width, CV_8UC1, u_ptr, u_stride);

// 2. 将U、V分量上采样到和Y分量相同分辨率
cv::Mat v_up, u_up;
cv::resize(v_mat, v_up, cv::Size(width, height), 0, 0, cv::INTER_NEAREST);
cv::resize(u_mat, u_up, cv::Size(width, height), 0, 0, cv::INTER_NEAREST);

// 3. 按Y、V、U顺序合并为三通道YUV Mat
std::vector<cv::Mat> yuv_channels = {y_mat, v_up, u_up};
cv::Mat yuv_mat;
cv::merge(yuv_channels, yuv_mat);

// 4. 转换为BGRA格式
cv::Mat dst;
// OpenCV 3.x及以下用CV_YCrCb2BGRA,4.x及以上用cv::COLOR_YCrCb2BGRA
cv::cvtColor(yuv_mat, dst, CV_YCrCb2BGRA);

注意:如果转换后图像颜色异常,首先检查U、V分量的顺序是否正确,YV12的V分量顺序在U之前,如果你的存储顺序是U在前V在后,需要将转换码替换为对应I420格式的常量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:24:05