yuv422,yuv420,yuv444的区别
一、yuvplanar和packed的区别。YUV格式有两大类:planar和packed。PIXEL_FORMAT_YVU_SEMIPLANAR_422,PIXEL_FORMAT_YVU_SEMIPLANAR_420,PIXEL_FORMAT_YVU_SEMIPLANAR_444,PIXEL_FORMAT_YUV_SEMIPLANAR_422,PIXEL_FORMAT_YUV_SEMIPLANA
声明:下面的图部分是摘自博主的,感谢博主 https://www.cnblogs.com/tid-think/p/10616789.html,如果涉及侵权,感谢告知,
学习了博主的图,彻底搞懂了yuv格式的知识,yuv格式很多种类,乱七八糟的感觉,学了他的图,加上自己的知识,彻底搞明白了,
一、yuv planar和packed的区别。
YUV格式有两大类:planar和packed。
PIXEL_FORMAT_YVU_SEMIPLANAR_422,
PIXEL_FORMAT_YVU_SEMIPLANAR_420,
PIXEL_FORMAT_YVU_SEMIPLANAR_444,
PIXEL_FORMAT_YUV_SEMIPLANAR_422,
PIXEL_FORMAT_YUV_SEMIPLANAR_420,
PIXEL_FORMAT_YUV_SEMIPLANAR_444,
PIXEL_FORMAT_YUYV_PACKAGE_422,
PIXEL_FORMAT_YVYU_PACKAGE_422,
PIXEL_FORMAT_UYVY_PACKAGE_422,
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。 对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。
二、yuv422,yuv420,yuv444的区别。
YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。
YUV 4:2:0采样,每四个Y共用一组UV分量。
什么意思额,看下面的图,第二张图,实心黑圈代表u和v的值,每两个y共用一个uv,第三张图,空心白圈代表u和v的值,第一第二行,列共用一个u和v,
假如图像视720※576的
(1)、yuv444,图片的大小是720x576x3个字节,是总像素大小的3倍
y的字节是720x576
u的字节是720x576
v的字节是720x576
下面的图是摘自博主的,感谢博主 https://www.cnblogs.com/tid-think/p/10616789.html,如果涉及侵权,感谢告知,
博主原话
首先要介绍的是YUV444,这种格式占用空间最大,每个像素点有一个Y分量+一个U分量+一个V分量所以和rgb一样每个像素点占用3个字节!但是根据UV存储顺序不一样,又有两种不同的格式。
(2)、yuv422,图片的大小是720x576x2个字节,是总像素大小的2倍
y的字节是720x576
u的字节是720x576 /2
v的字节是720x576 /2
下面的图是摘自博主的,感谢博主 https://www.cnblogs.com/tid-think/p/10616789.html,如果涉及侵权,感谢告知,
博主原话
接下来是YUV422 每两个Y分量公用一个UV分量,所以一个像素占用两个字节,根据存储顺序不同又分为四种不同的格式。
还有一种变态的V210格式,好像是苹果搞出来的。
(3)、yuv420,图片的大小是720x576x3/2个字节,是总像素大小的1.5倍
y的字节是720x576 w*h
u的字节是720x576 /4 (w/2) * (h/2)
v的字节是720x576 /4 (w/2) * (h/2)
下面的图是摘自博主的,感谢博主 https://www.cnblogs.com/tid-think/p/10616789.html,如果涉及侵权,感谢告知,
博主原话
接下来是YUV420 每四个y分量共用一个UV分量,所以每个像素点占用1.5个字节空间,根据存储顺序不一样又分为四个不同的类型。
如果要将4 :2: 2 和4:2:0 转换:上图很清晰,只需把uv的值在垂直方向隔行取,就额可以了。
三、采集到的yuv420转rgb
下面的程序能帮助更能理解,yuv420的储存格式
yuv2rgb的转换公式:参数可以调,颜色将不一样。
r= y + 402 *(v - 128);
g = y - 0.34413 *(u - 128) - 0.71414 *(v - 128);
b = y + 1.772 *(u -128);
datas[0]对应装的是y,这里是指针,指向了一段存y的内存,
datas[1]对应装的是u,这里是指针,指向了一段存u的内存,
datas[2]对应装的是v,这里是指针,指向了一段存v的内存,
看下图,我的数据是这样存储的,别搞错了,下面的代码清楚的知道y是如何和u,v组合提取的。
如果要参考公式是可以的,如果你的yuv和我不一样,别傻傻的直接用,修改看你自己。
转换后,存在了数组里,调用的是opcv里的imwrite函数,保存为bmp格式的图片,自动填充bmp数据头,如果有需要自己
保存为bmp的,问度娘,如何填充54字节的数据头。
int w = 800;
int h = 600;
char rgbBuf[800*600*3] = { 0 };
{
int i = 0,j = 0;
double y = 0, u = 0, v = 0;
double r = 0, g = 0, b = 0;
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
rgbBuf[(w *j + i) * 3] = 0;
rgbBuf[(w*j + i) * 3 + 1] = 0;
rgbBuf[(w*j + i) * 3 + 2] = 0;
y = *(datas[0] + w*j + i);
v = *(datas[1] +(w/2)* (j /2) + (i /2));//这里w/2,j/2,i/2,是u,v只有y的一半宽和高
u = *(datas[2] +(w/2)* (j /2) + (i /2));
r= y + 402 *(v - 128);
g = y - 0.34413 *(u - 128) - 0.71414 *(v - 128);
b = y + 1.772 *(u -128);
if (r>255)
r=255;
if (r<0)
r=0;
if (g>255)
g=255;
if (g<0)
g=0;
if (b>255)
b=255;
if (b<0)
b=0;
rgbBuf[(w*j + i) * 3] = (char)(r);
rgbBuf[(w*j + i) * 3 + 1] = (char)(g);
rgbBuf[(w *j + i) * 3 + 2] = (char)(b);
}
}
cv::Mat resultMat(cv::Size(width, height), CV_8UC3, &rgbBuf);
ret = imwrite(url, resultMat);
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)