OpenCV将BGR转换为NV12

NV12的格式为YYYYYYYY..UVUV..,OpenCV使用imread读出来的图像是BGR格式,但没有提供BGR直接转NV12的方法,只能先转成YUV_I420,再间接得到YUV_NV12。

cv::Mat BGR2YUV_NV12(const cv::Mat &src) {
    auto src_h = src.rows;
    auto src_w = src.cols;
    cv::Mat dst(src_h * 1.5, src_w, CV_8UC1);
    cv::cvtColor(src, dst, cv::COLOR_BGR2YUV_I420);  // I420: YYYY...UU...VV...

    auto n_y = src_h * src_w;
    auto n_uv = n_y / 2;
    auto n_u = n_y / 4;
    std::vector<uint8_t> uv(n_uv);
    std::copy(dst.data+n_y, dst.data+n_y+n_uv, uv.data());
    for (auto i = 0; i < n_u; i++) {
        dst.data[n_y + 2*i] = uv[i];            // U
        dst.data[n_y + 2*i + 1] = uv[n_u + i];  // V
    }
    return dst;
}

可以使用如下代码将YUV_I420进行保存:

FILE* outfile = fopen("img.yuv", "wb+");
fwrite(dst.data, 1, dst.rows*dst.cols*3/2, outfile);
fclose(outfile);

播放yuv图像,想得到正确结果,必须I420格式:

ffplay -f rawvideo -video_size 1920x1080 img.yuv

关于yuv的介绍可以参考这两篇文章:

图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
https://blog.csdn.net/byhook/article/details/84037338
视音频数据处理入门:RGB、YUV像素数据处理
https://blog.csdn.net/leixiaohua1020/article/details/50534150

作者简介

我是阿德,一名五年工作经验的软件开发工程师,985高校非科班程序员,热爱编程与开源,

此公众号【程序员阿德】专注于分享各种计算机干货,包括但不限于计算机组成原理、数据结构与算法、计算机网络、操作系统、数据库、Linux等。

相信你能够在这里有所收获,精进为一名优秀程序员,我们一起加油~

现在关注公众号 [程序员阿德] ,回复【书籍】可以获取我精心挑选的10本经典计算机电子书,加速你的成长。

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BGR图像转换NV12格式可以通过以下步骤完成: 1. 使用OpenCV的cvtColor函数将BGR图像转换为YUV格式。例如: ``` cv::Mat bgrImage = cv::imread("input_image.jpg"); cv::Mat yuvImage; cv::cvtColor(bgrImage, yuvImage, cv::COLOR_BGR2YUV_I420); ``` 2. 将I420格式的YUV图像转换NV12格式。NV12格式与I420格式的区别是UV分量的存储方式不同。在I420中,U和V分量是交错存储的,而在NV12中,U和V分量是连续存储的。以下是将I420格式的YUV图像转换NV12格式的代码: ``` int width = bgrImage.cols; int height = bgrImage.rows; // Get the number of pixels in the image int numPixels = width * height; // Calculate the size of the U and V planes int uvSize = numPixels / 4; // Get pointers to the Y, U, and V planes uchar* yPlanePtr = yuvImage.data; uchar* uPlanePtr = yPlanePtr + numPixels; uchar* vPlanePtr = uPlanePtr + uvSize; // Create a new buffer for the NV12 image std::vector<uchar> nv12Image(numPixels + uvSize); // Copy the Y plane to the NV12 buffer std::copy(yPlanePtr, yPlanePtr + numPixels, nv12Image.begin()); // Interleave the U and V planes and copy them to the NV12 buffer for (int i = 0; i < uvSize; i++) { nv12Image[numPixels + i * 2] = uPlanePtr[i]; nv12Image[numPixels + i * 2 + 1] = vPlanePtr[i]; } // Create a new Mat object for the NV12 image and copy the buffer to it cv::Mat nv12Mat(height + height / 2, width, CV_8UC1, nv12Image.data()); ``` 现在,您可以将`nv12Mat`用作NV12格式的图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值