opencv 解析yuv_OpenCV Mat格式存储YUV图像
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图像相关推荐
- 将.mat格式的高光谱图像转换成png或jpg格式
将.mat格式的高光谱图像转换成png或jpg格式 使用MATLAB打开.mat文件,并读取高光谱图像数据. 如果高光谱图像数据为三维矩阵,将其转置为(宽度,高度,波段数)的形式.这是因为MATLAB ...
- plt.imshow()显示以ndarray格式存储的图像数据
1 plt.imshow()详细介绍:常用参数为红色标注 输入可以是实际的RGB(A)数据,也可以是2D标量数据,这些数据将被渲染为伪彩色图像.为了显示灰度图像,使用参数设置颜色映射:cmap='gr ...
- opencv 解析yuv_opencv yuv
场景:opencv 怎么缩放 YUV420 数据 opencv 如何缩放 YUV420 数据 我从文件中读取 一帧 yuv420 的数据,保存到一个数组中, 请问 如何使用opencv 对yuv数据进 ...
- 一文掌握 YUV 图像的基本处理
YUV 图片 YUV 的由来 YUV 是一种色彩编码模型,也叫做 YCbCr,其中 "Y" 表示明亮度(Luminance),"U" 和 "V&quo ...
- 使用VS2010调用matlab的mat格式文件
做实验需要将matlab实现的meanshift的结果中的region的Iabels矩阵,需要把labels.mat读入VS2010中,实现功能,在此把实现过程记录下来. C++读取mat文件的步骤如 ...
- 如何用matlab实现矩阵与mat格式、xlsx格式文件互转
目录 一.前言 二..mat格式 三..xlsx格式 四.出现load('file.mat') 数据变成struct结构体的问题 一.前言 当我们利用matlab去处理我们的实验数据时,常常需要读取m ...
- 分析比较图像RGB格式和YUV格式的存储概率分布
分析比较图像RGB格式和YUV格式的存储概率分布 实验思路 两个图片文件down.yuv和down.rgb均为二进制存储的图片文件,像素为256* 256.yuv为4:2:0格式,即1份y对应0.25 ...
- 独家|OpenCV 1.1 Mat - 基本图像容器(附链接)
翻译:陈之炎 校对:吴振东.林夕本文约3600字,建议阅读10分钟本文为大家系统地介绍了OpenCV官方教程. 写在前边 让读者朋友们较为系统地了解和学习OpenCV官方教程,数据派THU翻译组联合研 ...
- opencv 解析yuv_通过OpenCV读取并显示YUV视频文件
前言 Opencv中通常是读取 avi 格式的视频文件,下面程序是直接读取 YUV格式的视频文件并显示出来. 这里需要将YUV读取出来,使用Mat格式保存再使用 cv::cvtColor() 将每帧的 ...
最新文章
- 计算机网络——OSI与TCPIP体系架构、功能及协议
- 区块链基础知识系列第5课 Hyperledger fabric1.0网络中transaction产生以及流转过程
- shell脚本编程测试类型下
- oracle密码不能重复用_重复码
- 5g存储服务器是什么项目,5G时代对服务器有什么要求?
- 【Pytorch】 .item()==>得到元素张量里面的一个元素值,便可以循环、查看...操作
- 苹果maccmsv10和redis memcached缓存的若干问题解决!
- httos双向认证配置_APP爬虫双向认证抓包的两种方法
- 有关单元测试的 5 个建议
- [C4] 前馈神经网络(Feedforward Neural Network)
- java解释器是哪个命令_宽恕命令解释器的最佳Java库(IES)
- 输入法候选词排列的两种新方式
- cuda和cudnn各版本下载地址
- 微信飞机小游戏java_Shoot Plane 仿微信打飞机游戏的java实现
- 【前端】三种方法将文字垂直居中
- 如何解决3G模块和USB转串口冲突问题
- arthas profiler诊断服务性能
- 内存管理(15)——UI(20)——DeleteObject
- 从NCE loss到InfoNCE loss
- 虚拟主机cPanel面板查看服务器的访问日志
热门文章
- 用神经网络二分类吸引子与排斥子
- linux ip addr peer,Linux网络IP设置
- ie8不兼容java项目_[Java教程]ie8以下不兼容document.getElementsByName解决方法
- mysql -u -p -d_mysqld_exporter监控mysql
- 【CoppeliaSim】使用 Lua 语言控制四旋翼无人机运行
- 【数理知识】《数值分析》李庆扬老师-第9章-常微分方程初值问题数值解法
- 在隧道内放置多个地感线圈,车辆通过时、对通过的相邻两个线圈的脉冲信号数据进行实时采集,首先利用云模型算法,计算得到车速的估计值
- 10 在Spring Cloud中使用Hystrix
- CrazyWing:Python自动化运维开发实战 九、Python数据类型之列表
- Servlet3.1规范翻译 - 应用生命周期事件