YUV图像用的比较多,而且YUV图像的格式众多(YUV格式可以参考YUV pixel formats),如何用OpenCV的Mat类型来存储YUV图像也是经常遇到的问题。

对于YUV444图像来说,就很简单。YUV的三个分量的采样方法一致,因此YUV三个分量的大小一致,可以用Mat的三个channel分别表示YUV即可。假设src是OpenCV默认的BGR三通道图像,和YUV444的转换如下,图像大小不变。

//If src is CV_8UC3, dest is CV_8UC3

cvtColor(src, dest, COLOR_BGR2YUV);

cvtColor(dest, src, COLOR_YUV2BGR);

YUV422用的不多(其实我没用过),先说YUV420。YUV420图像的U/V分量在水平和垂直方向上downsample,在水平和垂直方向上的数据都只有Y分量的一半。因此总体来说,U/V分量的数据量分别只有Y分量的1/4,不能作为Mat类型的一个channel。所以通常YUV420图像的全部数据存储在Mat的一个channel,比如CV_8UC1,这样对于Mat来说,图像的大小就有变化。对于MxN(rows x cols,M行N列)的BGR图像(CV_8UC3),其对应的YUV420图像大小是(3M/2)xN(CV_8UC1)。前MxN个数据是Y分量,后(M/2)xN个数据是U/V分量,UV数据各占一半。

U/V分量如何存储,和YUV420的格式有关。YUV420有所谓的420p(420planar/420面)和420sp(420 semi-planar/420半面)格式。所谓420面格式,YUV三个分量按顺序存储完一个分量所有图像数据,称为一个面,再存储下一个分量的面,因此有三个面数据。420半面格式下,只有Y分量是作为一个单独的面存储,U/V分量按照像素排列顺序交错存储,算作一个面,因此称为半面。

420p

420sp

YUV顺序

YVU顺序

UVUV交错

VUVU交错

I420/IYUV

YV12

NV12

NV21

420p或者420sp都是先存储Y分量的面,然后根据UV分量的存储顺序,又各分为两种格式。420p按照YUV的顺序存储三个面,是I420格式,或者叫IYUV格式。按照YVU的顺序存储三个面,叫YV12格式。420sp的U/V交错面,如果按照UVUV的顺序交错存储,称为NV12格式。反之,按照VUVU的顺序交错存储,称为NV21格式。

OpenCV现在从BGR到YUV420的颜色空间变化仅支持转换到420p的两种格式,不支持转换到420sp。但可以支持420p或者420sp转换到BGR。假设src是OpenCV默认的BGR三通道图像,和420p的转换如下。

//If src is BGR CV_8UC3 with size 640x960, dest is CV_8UC1 with 960x960

cvtColor(src, dest, COLOR_BGR2YUV_I420);    //dest is I420

cvtColor(dest, src, COLOR_YUV2BGR_I420);

cvtColor(src, dest, COLOR_BGR2YUV_YV12);//dest is YV12

cvtColor(dest, src, COLOR_YUV2BGR_YV12);

假设src是YUV420的420sp图像数据,到BGR的转换如下。

//If src is NV12 CV_8UC1 with size 960x960, dest is BGR CV_8UC3 with 640x960

cvtColor(src, dest, COLOR_YUV2BGR_NV12);//If src is NV21 CV_8UC1 with size 960x960, dest is BGR CV8UC3 with 640x960

cvtColor(src, dest, COLOR_YUV2BGR_NV21);

OpenCV还提供了一个cvtColorTwoPlane函数,当前仅支持从420sp转换到BGR,但是Y面和U/V交错面存储在两个Mat结构中。

下面的代码片段把height x width的YUV图像数据顺时针旋转90°存储到Mat,格式是NV12。yPixel, uPixel, vPixel分别是指向YUV数据的指针,yStride,uvStride分别是Y和UV的行stride,uvPixelStride是UV数据像素stride。代码分别把YUV数据存储到一个临时Mat中,然后调用OpenCV的transpose()和flip()函数把图像顺时针旋转90°。较新版本的OpenCV提供了函数rotate()可以做90°,180°和270°的旋转,可以使用。最后分别把旋转后的YUV数据写到Mat中,最后的格式是NV12,注意height和width交换了,UV数据是交错存储的。如果不使用OpenCV的函数,自己写一段代码来做旋转也是可以的。不过我试过了,肯定没有OpenCV的函数快。OpenCV的函数至少要比我们用循环写出来的代码快25%。所以有现成的库函数尽量使用他们。

//Original image with size height x width//int32_t width, height; original image width and height//uint8_t *yPixel, *uPixel, *vPixel; pointers to YUV data//int32_t yStride, uvStride, uvPixelStride; line stride and uv pixel stride

cv::Mat yuv_nv12(width * 3 / 2, height, CV_8UC1)inti, j;int height2 = height / 2, width2 = width / 2;

cv::Mat y_temp(height, width, CV_8UC1);

cv::Mat u_temp(height2, width2, CV_8UC1);

cv::Mat v_temp(height2, width2, CV_8UC1);//Get Y data and rotate

line_src =yPixel;for (i = 0; i < height; i++) {

line_dest=y_temp.ptr(i);

memcpy(line_dest, line_src, width);

line_src+=yStride;

}

cv::transpose(y_temp, y_temp);

cv::flip(y_temp, y_temp,1);//Get U data and rotate

line_src =uPixel;for (i = 0; i < height2; i++) {

line_dest=u_temp.ptr(i);

uchar*ptr =line_src;for (j = 0; j < width2; j++) {*line_dest++ = *ptr;

ptr+=uvPixelStride;

}

line_src+=uvStride;

}

cv::transpose(u_temp, u_temp);

cv::flip(u_temp, u_temp,1);//Get V data and rotate

line_src =vPixel;for (i = 0; i < height2; i++) {

line_dest=v_temp.ptr(i);

uchar*ptr =line_src;for (j = 0; j < width2; j++) {*line_dest++ = *ptr;

ptr+=uvPixelStride;

}

line_src+=uvStride;

}

cv::transpose(v_temp, v_temp);

cv::flip(v_temp, v_temp,1);//Write Y data to yuv_nv12

for (i = 0; i < width; i++) {

line_dest=yuv_nv12.ptr(i);

line_src=y_temp.ptr(i);

memcpy(line_dest, line_src, height);

}//Write UV data to yuv_nv12

cv::MatIterator_ it((cv::Mat_*)&yuv_nv12, width);

cv::MatIterator_ u_src_it = u_temp.begin();

cv::MatIterator_ v_src_it = v_temp.begin();int wh2 = width2 *height2;for (i = 0; i < wh2; i++) {*it++ = *u_src_it++;*it++ = *v_src_it++;

}

至于YUV422图像,我没有试过。OpenCV不支持从BGR转到YUV422,但是可以从YUV422转会BGR。大概看了下,YUV422图像用Mat类型存储应该也是用一个channel来存储所有YUV数据,而且应该是用所谓的紧凑格式(packed format),而不是前面提到的面格式(planar format)。所谓紧凑格式,就是对每个像素的YUV三个分量按照一定的顺序交错存储,每4个数据组成一个所谓的宏像素。因为YUV422垂直方向没有downsample,只有水平方向有,所以每两个Y对应一个U和一个V,组成一个宏像素。比如UYVY格式(按照UYVY交错存储),YUY2格式(按照YUYV交错存储),YVYU格式等等。它们都有对应的转BGR的code,比如COLOR_YUV2BGR_UYVY,不一一列举了。

opencv 解析yuv_OpenCV Mat格式存储YUV图像相关推荐

  1. 将.mat格式的高光谱图像转换成png或jpg格式

    将.mat格式的高光谱图像转换成png或jpg格式 使用MATLAB打开.mat文件,并读取高光谱图像数据. 如果高光谱图像数据为三维矩阵,将其转置为(宽度,高度,波段数)的形式.这是因为MATLAB ...

  2. plt.imshow()显示以ndarray格式存储的图像数据

    1 plt.imshow()详细介绍:常用参数为红色标注 输入可以是实际的RGB(A)数据,也可以是2D标量数据,这些数据将被渲染为伪彩色图像.为了显示灰度图像,使用参数设置颜色映射:cmap='gr ...

  3. opencv 解析yuv_opencv yuv

    场景:opencv 怎么缩放 YUV420 数据 opencv 如何缩放 YUV420 数据 我从文件中读取 一帧 yuv420 的数据,保存到一个数组中, 请问 如何使用opencv 对yuv数据进 ...

  4. 一文掌握 YUV 图像的基本处理

    YUV 图片 YUV 的由来 YUV 是一种色彩编码模型,也叫做 YCbCr,其中 "Y" 表示明亮度(Luminance),"U" 和 "V&quo ...

  5. 使用VS2010调用matlab的mat格式文件

    做实验需要将matlab实现的meanshift的结果中的region的Iabels矩阵,需要把labels.mat读入VS2010中,实现功能,在此把实现过程记录下来. C++读取mat文件的步骤如 ...

  6. 如何用matlab实现矩阵与mat格式、xlsx格式文件互转

    目录 一.前言 二..mat格式 三..xlsx格式 四.出现load('file.mat') 数据变成struct结构体的问题 一.前言 当我们利用matlab去处理我们的实验数据时,常常需要读取m ...

  7. 分析比较图像RGB格式和YUV格式的存储概率分布

    分析比较图像RGB格式和YUV格式的存储概率分布 实验思路 两个图片文件down.yuv和down.rgb均为二进制存储的图片文件,像素为256* 256.yuv为4:2:0格式,即1份y对应0.25 ...

  8. 独家|OpenCV 1.1 Mat - 基本图像容器(附链接)

    翻译:陈之炎 校对:吴振东.林夕本文约3600字,建议阅读10分钟本文为大家系统地介绍了OpenCV官方教程. 写在前边 让读者朋友们较为系统地了解和学习OpenCV官方教程,数据派THU翻译组联合研 ...

  9. opencv 解析yuv_通过OpenCV读取并显示YUV视频文件

    前言 Opencv中通常是读取 avi 格式的视频文件,下面程序是直接读取 YUV格式的视频文件并显示出来. 这里需要将YUV读取出来,使用Mat格式保存再使用 cv::cvtColor() 将每帧的 ...

最新文章

  1. 计算机网络——OSI与TCPIP体系架构、功能及协议
  2. 区块链基础知识系列第5课 Hyperledger fabric1.0网络中transaction产生以及流转过程
  3. shell脚本编程测试类型下
  4. oracle密码不能重复用_重复码
  5. 5g存储服务器是什么项目,5G时代对服务器有什么要求?
  6. 【Pytorch】 .item()==>得到元素张量里面的一个元素值,便可以循环、查看...操作
  7. 苹果maccmsv10和redis memcached缓存的若干问题解决!
  8. httos双向认证配置_APP爬虫双向认证抓包的两种方法
  9. 有关单元测试的 5 个建议
  10. [C4] 前馈神经网络(Feedforward Neural Network)
  11. java解释器是哪个命令_宽恕命令解释器的最佳Java库(IES)
  12. 输入法候选词排列的两种新方式
  13. cuda和cudnn各版本下载地址
  14. 微信飞机小游戏java_Shoot Plane 仿微信打飞机游戏的java实现
  15. 【前端】三种方法将文字垂直居中
  16. 如何解决3G模块和USB转串口冲突问题
  17. arthas profiler诊断服务性能
  18. 内存管理(15)——UI(20)——DeleteObject
  19. 从NCE loss到InfoNCE loss
  20. 虚拟主机cPanel面板查看服务器的访问日志

热门文章

  1. 用神经网络二分类吸引子与排斥子
  2. linux ip addr peer,Linux网络IP设置
  3. ie8不兼容java项目_[Java教程]ie8以下不兼容document.getElementsByName解决方法
  4. mysql -u -p -d_mysqld_exporter监控mysql
  5. 【CoppeliaSim】使用 Lua 语言控制四旋翼无人机运行
  6. 【数理知识】《数值分析》李庆扬老师-第9章-常微分方程初值问题数值解法
  7. 在隧道内放置多个地感线圈,车辆通过时、对通过的相邻两个线圈的脉冲信号数据进行实时采集,首先利用云模型算法,计算得到车速的估计值
  8. 10 在Spring Cloud中使用Hystrix
  9. CrazyWing:Python自动化运维开发实战 九、Python数据类型之列表
  10. Servlet3.1规范翻译 - 应用生命周期事件