一、首先了解下nv12和nv21的数据排布

nv21

Y Y Y Y
Y Y Y Y
Y Y Y Y
Y Y Y Y
V U V U
V U V U

nv21
Y Y Y Y
Y Y Y Y
Y Y Y Y
Y Y Y Y
U V U V
U V U V

主要就是UV的顺序不同,交互一下UV的位置就可以互换NV12和NV21.

二、bgr(rgb)转nv21(nv12)

一般手机等移动端的数据流格式都是yuv格式,而神经网络的输入一般都是rgb格式,所以需要进行转换,这里给出c++的代码示例。

cv::Mat bgr2yuv(cv::Mat &bgr)
{
    cv::Mat img_yuv_yv12;
    int height = bgr.rows;
    int width = bgr.cols;
    cv::Mat img_yuv(height * 3 / 2, width, CV_8UC1);
    cv::cvtColor(bgr, img_yuv_yv12, CV_BGR2YUV_YV12);
    memcpy(img_yuv.data, img_yuv_yv12.data, height * width);
    char *v = (char*)img_yuv_yv12.data + height * width;
    char *u = v + height * width / 4;
    char *dst = (char*)img_yuv.data + height * width;
    for (int i = 0;i < height * width / 4; ++i)
    {
        //nv21
        dst[2 * i] = v[i];
        dst[2 * i + 1] = u[i];
        //nv12
        //dst[2 * i] = u[i];
        //dst[2 * i + 1] = v[i];
    }
    return img_yuv;
}

前面提到,交换UV的位置就可以得到NV21和NV12。

三、nv21(nv12)转BGR

int yuv2bgr(unsigned char * yuv_img, unsigned char *rgb_img,int width, int height)
{

unsigned char * ydata = yuv_img;
    unsigned char *uvdata = ydata + width * height;
    int indexY, indexU, indexV;
    unsigned char Y, U, V;
    int B, G, R;

for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            indexY = i * width + j;
            Y = ydata[indexY];

if (j % 2 == 0)
            {
                indexU = i / 2 * width + j;
                indexV = indexU + 1;
                U = uvdata[indexU];
                V = uvdata[indexV];
            }
            else
            {
                indexV = i / 2 * width + j;
                indexU = indexV - 1;
                U = uvdata[indexU];
                V = uvdata[indexV];
            }
            //nv21
            R = (unsigned char)(Y + 1.4075 * (U - 128));
            G = (unsigned char)(Y - 0.3455 * (V - 128) - 0.7169 * (U - 128));
            B = (unsigned char)(Y + 1.779 * (V - 128));
            //nv12
            //R = (unsigned char)(Y + 1.4075 * (V - 128));
            //G = (unsigned char)(Y - 0.3455 * (U - 128) - 0.7169 * (V - 128));
            //B = (unsigned char)(Y + 1.779 * (U - 128));
            
            rgb_img[indexY * 3 + 0] = clamp_g(B, 0, 255);
            rgb_img[indexY * 3 + 1] = clamp_g(G, 0, 255);
            rgb_img[indexY * 3 + 2] = clamp_g(R, 0, 255);

}
    }
    return 0;
}

四、效果

OK!

五、速度优化

nv21转bgr的平均时间(输入大小720p):

AveTime:13.7835ms

改进代码:

改进后平均时间:AveTime:5.52088ms

速度提升60%,结果完全一致。

yuv数据(nv12和nv21)和RGB数据之间转换的c++代码相关推荐

  1. YUV420P、YUV420SP、NV12、NV21和RGB互相转换并存储为JPEG以及PNG图片

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  2. 【音视频数据数据处理 7】【RGB/BMP篇】生成24色 RGB24图 和 BMP图

    [音视频数据数据处理 7][RGB篇]生成一张24色 RGB24图 和 BMP图 一.生成24色 RGB24图代码实现 二.生成24色 BMP图代码实现 先上24色图,及其对应的RGB值. 本文地址: ...

  3. 【nv12 格式转换】不同图像数据格式之间转换代码实操

    文章目录 1 问题先行 2 nv12介绍 2.1 YUV格式 2.2 NV12排布 3 不同数据格式之间转换实操 4 参考链接 1 问题先行 nv12是什么格式?和常见的rgb/bgr有什么关系吗?他 ...

  4. 音视频数据处理入门:原始视频格式YUV,NV12,NV21,YV12,YU12(I420)

    我们知道,在Camera中设置Preview的回调函数onPreviewFrame时谷歌推荐我们使用NV21,YV12两种格式,因为这两种格式几乎在所有的设备里都通用.然而,视频的格式远远不止这俩种, ...

  5. 【Android Camera2】玩转图像数据 -- NV21图像旋转,镜像,转rgba代码分析,性能优化

    [Android Camera2]玩转图像数据 业务场景介绍 NV21数据旋转 逐像素遍历法 NV21数据镜像 逐像素遍历法 中心翻转法 NV21转RGB/RGBA数据 逐像素遍历法 NV21组合操作 ...

  6. FFmpeg(六) 播放视频之GLSurfaceView显示RGB数据

    一.播放视频说明 1.两种方式播放视频 ①shader播放YUV,后面再介绍. ②RGB直接显示数据,简单.性能差,用到FFmpeg的格式转换,没有shader效率高.本文介绍这个方式. 2.GLSu ...

  7. 如何将yuv420p图像数据转换为RGB数据并使用opencv保存为jpg图片

    yuv420是用4个byte存储4个Y的信息,用1个Byte存储U的信息,一个Byte存储V的信息, 这4个Y共用这2个U和V ,也就是用6个Byte 存储4个像素信息,也就是一个像素需要12个Bit ...

  8. 项目中利用AnyChat SDK实现将RGB数据作为视频源的实时推送功能

    一.前期调研工作: 查看官网简介www.anychat.cn 可以知道AnyChat支持外部音视频功能,具体描述如下: AnyChat Platform Core SDK V4.2版本增加了外部音视频 ...

  9. java bmp rgb数组_将RGB数据写入BMP位图文件

    CFile file; //定义一个文件对象 _ASSERTE(file.Open(CString("E:\\94.bmp"), CFile::modeRead));//打开文件 ...

最新文章

  1. Emoji表情图标在iOS与PHP之间通信及MySQL存储
  2. C#中IEnumerableT.Aggregate()的简单使用
  3. 线性回归(单神经元,多神经元)和多层感知机(多个神经元)对比
  4. 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP
  5. 2017-07-12 周三 今日总结
  6. 聊一聊数学中的基本定理(四)——微积分基本定理
  7. android listview表格分页显示,android实现listview分页的方法
  8. Win11如何增强麦克风?Win11增强麦克风的设置
  9. IE查看源文件重定向到 桌面的解决方法
  10. LM317,线性稳压电源总结
  11. 前端工程师项目能力精选文章50篇
  12. java 组件是什么意思_java中组件是什么意思?
  13. 程序员外包到底怎么了?
  14. android 自动锁屏设置,如何才能使安卓手机不自动锁屏?改成自动黑屏,谢谢
  15. docker push 过程 distribution源码 分析
  16. 英语学习单词篇(14)
  17. 标签打印软件如何设置不规则标签纸
  18. 手把手教你撸最新Youtube视频 拖拽动画效果
  19. wpa.b.qq.com/cgi/wpa.php,QQ在线状态代码
  20. Oracle数据同步解决方案之databus

热门文章

  1. Java基于ssm的超市多商家系自提系统
  2. NAND Flash SLC、MLC技术解析
  3. skywalking—docker镜像构建k8s部署
  4. java工具封装树形对象,常用于菜单 json树逆向生成list集合
  5. B站马士兵python入门基础版详细笔记(6)
  6. leetcode1646. 获取生成数组中的最大值
  7. 晨读一年的复盘会议_一年后,在家中远程办公,网真和视频会议
  8. DOS命令行 定时关机取消定时关机
  9. jQuery实现简单实用的H5(手机端)下拉分页加载(所谓的懒加载!!!)
  10. 2022最新SpringBoot2.X仿B站项目part1笔记