对于 YUV 所表示的图像,Y 和 UV 分量是分离的。如果只有 Y 分量而没有 UV 分离,那么图像表示的就是黑白图像。彩色电视机采用的就是 YUV 图像,解决与和黑白电视机的兼容问题,使黑白电视机也能接受彩色电视信号。
人眼对色度的敏感程度低于对亮度的敏感程度。主要原因是视网膜杆细胞多于视网膜锥细胞,其中视网膜杆细胞的作用就是识别亮度,视网膜锥细胞的作用就是识别色度。所以,眼睛对于亮度的分辨要比对颜色的分辨精细一些。
利用这个原理,可以把色度信息减少一点,人眼也无法查觉这一点。
所以,并不是每个像素点都需要包含了 Y、U、V 三个分量,根据不同的采样格式,可以每个 Y 分量都对应自己的 UV 分量,也可以几个 Y 分量共用 UV 分量。相比 RGB,能够节约不少存储空间。
YUV 4:4:4采样方式与 RGB 图像大小是一样的。
YUV 4:2:2相比 RGB, 节省了三分之一的存储空间。
YUV 4:2:0相比 RGB, 节省了一半的存储空间。
设实际宽高为
w*h
的图像,如果是
RGB
格式,那么他的数据量为
w*h*3
;
如果是
yuv420
格式,那么他的数据量为
w*h*1.5
因为
yuv4:4:4
的数据量等于RGB数据量,而
yuv4:4:4
是
yuv4:2:0
数据量的2倍,所以
yuv4:2:0
的数据量为
w*h*3/2
。
-
1.当我们拿到一帧图像的yuv原始数据后,首先需要明确拿到的是以下哪种yuv数据:
yuv4:4:4
、
yuv4:2:2
、
yuv4:2:0
。并且,我们都会知道给对应图像的宽和高,因为这都是驱动配置给出的。如果你是从yuv元素数据中截取出来的某roi区域的yuv数据,那么你也应该知道该roi的宽和高。注意,此时的宽和高是指图像的宽和高,不是指代图像数据码流排列的行数和列数。
-
2.把原始yuv数据通过构造
cv::Mat
格式封装起来,此时的
cv::Mat
的宽(
.cols
)和高(
.rows
)就需要变化了,因为yuv格式和RGB格式的数据量是不一样的,yuv格式如果不是
yuv4:4:4
(yuv数据量为
w*(h*3)
)的话,那么yuv格式的数据量是一定比RGB少的。所以,此时如果是
yuv420
格式,就根据
yuv420
格式的特点,把
cv::Mat
的宽高设置为
w*(h*1.5)
,且必须为单通道,注意这里宽度不变,是在高度上延伸。yuyv原始数据变成
cv::Mat
格式后,你如果直接
imshow
显示的话,图像会变高。转化成RGB格式后才会恢复为正常宽和高。
-
3.然后再通过
cv::cvtColor(yuyv_img, rgb_img, cv::COLOR_YUV420sp2RGB);
转化得到RGB图像。
注意构造yuyv的
cv::Mat
时通道类型是
CV_8UC1
,而构造RGB的
cv::Mat
时通道类型是
CV_8UC3
.
cv::Mat yuyv_img =
cv::Mat(box.height * 3 / 2, box.width, CV_8UC1,
const_cast<unsigned char *>(yuv_raw.data()));
if (!yuyv_img.data) {
std::cout << "empty yuyv_img"<< std::endl;
cv::Mat rgb_img = cv::Mat(box.height, box.width, CV_8UC3);
cv::cvtColor(yuyv_img, rgb_img, cv::COLOR_YUV420sp2RGB);
可参考下面两篇文章来理解YUV:
一文理解 YUV
YUV色彩格式总结
设实际宽高为w*h的图像,如果是RGB格式,那么他的数据量为w*h*3;如果是yuv420格式,那么他的数据量为w*h*1.5因为yuv4:4:4的数据量等于RGB数据量,而yuv4:4:4是yuv4:2:0数据量的2倍,所以yuv4:2:0的数据量为w*h*3/2。从yuv420sp转化得到rgb的步骤:1.当我们拿到一帧图像的yuv原始数据后,首先需要明确拿到的是以下哪种yuv数据:yuv4:4:4、yuv4:2:2、yuv4:2:0。并且,我们都会知道给对应图像的宽和高,因为这都是驱动配置给
0.1 灰度模式
也就是灰度图(黑白照片),每个像素只有明暗变化,用0~255共256个亮度级来表示,用8个bit来表示,所以每个像素信息用8bit储存.
0.2 位图模式(二值图像)
即只有纯黑和纯白两种亮度,没有渐变的亮度级,通常用0表示纯黑,1表示纯白,所以每个像素信息用1bit表示即可
0.3 RGB模式:基于发光体(电子产品)的色彩模式
static long int cgu_tab[256];
static long int cgv_tab[256];
static long int tab_76309[256];
static unsigned char clp[1024]; //for clip in CCIR601
void init_yuv420p_table()
通过FFMPEG 得到mov视频解码后的一个Frame,它是YUV420P的图像,我要把它转换成方便显示的JPEG图像。
代码片断如下所示
av_image_copy(_data, _linesize, (const uint8_t **)avframe->data, avframe->linesize, _pix_fmt, _width, _height);
cv::...
YUV格式哟很多种,本篇记录的格式为YUV420。
有关YUV420的详细介绍,可以参考资料:1、图文详解YUV420数据格式 http://blog.csdn.net/jefry_xdz/article/details/7931018
首先yuv420的存储大小为:width * he