2008年9月24日星期三

视频YUV格式详解

概述
  YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。其中的Y,U,V几个字母不是英文单词的组合词,Y代表亮度,uv代表色差,u和v是构成彩色的两个分量。在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y(即U)、B-Y(即V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有 Y信号分量而没有U、V信号分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的相容问题,使黑白电视机也能接收彩色电视信号。
优点作用
  YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和CB来表示。其中,Cr反映了GB输入信号红色部分与RGB信号亮度值之间的差异。而CB反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。
  采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
  YUV与RGB相互转换的公式如下(RGB取值范围均为0-255):
  Y = 0.299R + 0.587G + 0.114B
  U = -0.147R - 0.289G + 0.436B
  V = 0.615R - 0.515G - 0.100B
  R = Y + 1.14V
  G = Y - 0.39U - 0.58V
  B = Y + 2.03U
  在DirectShow中,常见的RGB格式有RGB1、RGB4、RGB8、RGB565、RGB555、RGB24、RGB32、ARGB32等;常见的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等。
YUV主要的采样格式
  主要的采样格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 8bit 的亮度值(也就是Y值),每 2x2 个点保存一个 Cr 和Cb 值, 图像在肉眼中的感觉不会起太大的变化。所以, 原来用 RGB(R,G,B 都是 8bit unsigned) 模型, 1个点需要 8x3=24 bites(如下图第一个图),(全采样后,YUV仍各占8bit)。按4:1:1采样后,而现在平均仅需要 8+(8/4)+(8/4)=12bites(4个点,8*4(Y)+8(U)+8(V)=48bit), 平均每个点占12bites(如下图第二个图)。这样就把图像的数据压缩了一半。
  上边仅给出了理论上的示例,在实际数据存储中是有可能是不同的,下面给出几种具体的存储形式:
  (1) YUV 4:4:4
  YUV三个信道的抽样率相同,因此在生成的图像里,每个象素的三个分量信息完整(每个分量通常8比特),经过8比特量化之后,未经压缩的每个像素占用3个字节。
  下面的四个像素为: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
  存放的码流为: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
  (2) YUV 4:2:2
  每个色差信道的抽样率是亮度信道的一半,所以水平方向的色度抽样率只是4:4:4的一半。对非压缩的8比特量化的图像来说,每个由两个水平方向相邻的像素组成的宏像素需要占用4字节内存。
  下面的四个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
  存放的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3
  映射出像素点为:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]
  (3) YUV 4:1:1
  4:1:1的色度抽样,是在水平方向上对色度进行4:1抽样。对于低端用户和消费类产品这仍然是可以接受的。对非压缩的8比特量化的视频来说,每个由4个水平方向相邻的像素组成的宏像素需要占用6字节内存。
  下面的四个像素为: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
  存放的码流为: Y0 U0 Y1 Y2 V2 Y3
  映射出像素点为:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]
  (4)YUV4:2:0
  4:2:0并不意味着只有Y,Cb而没有Cr分量。它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。相邻的扫描行存储不同的色度分量,也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0...以此类推。对每个色度分量来说,水平方向和竖直方向的抽样率都是2:1,所以可以说色度的抽样率是4:1。对非压缩的8比特量化的视频来说,每个由2x2个2行2列相邻的像素组成的宏像素需要占用6字节内存。
  下面八个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
  [Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
  存放的码流为:Y0 U0 Y1 Y2 U2 Y3
  Y5 V5 Y6 Y7 V7 Y8
  映射出的像素点为:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]
  [Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]
各种YUV格式(图)
  YUV格式通常有两大类:打包(packed)格式和平面(planar)格式。前者将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开存放YUV三个分量,就像是一个三维平面一样。表2.3中的YUY2到Y211都是打包格式,而IF09到YVU9都是平面格式。(注意:在介绍各种具体格式时,YUV各分量都会带有下标,如Y0、U0、V0表示第一个像素的YUV分量,Y1、U1、V1表示第二个像素的YUV分量,以此类推。)
  ¨ YUY2(和YUYV)格式为每个像素保留Y分量,而UV分量在水平方向上每两个像素采样一次。一个宏像素为4个字节,实际表示2个像素。(4:2:2的意思为一个宏像素中有4个Y分量、2个U分量和2个V分量。)图像数据中YUV分量排列顺序如下:
  Y0 U0 Y1 V0 Y2 U2 Y3 V2 …
  ¨ YVYU格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
  Y0 V0 Y1 U0 Y2 V2 Y3 U2 …
  ¨ UYVY格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
  U0 Y0 V0 Y1 U2 Y2 V2 Y3 …
  ¨ AYUV格式带有一个Alpha通道,并且为每个像素都提取YUV分量,图像数据格式如下:
  A0 Y0 U0 V0 A1 Y1 U1 V1 …
  ¨ Y41P(和Y411)格式为每个像素保留Y分量,而UV分量在水平方向上每4个像素采样一次。一个宏像素为12个字节,实际表示8个像素。图像数据中YUV分量排列顺序如下:
  U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y8 …
  ¨ Y211格式在水平方向上Y分量每2个像素采样一次,而UV分量每4个像素采样一次。一个宏像素为4个字节,实际表示4个像素。图像数据中YUV分量排列顺序如下:
  Y0 U0 Y2 V0 Y4 U4 Y6 V4 …
  ¨ YVU9格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个4 x 4的宏块,然后每个宏块提取一个U分量和一个V分量。图像数据存储时,首先是整幅图像的Y分量数组,然后就跟着U分量数组,以及V分量数组。IF09格式与YVU9类似。
  ¨ IYUV格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个2 x 2的宏块,然后每个宏块提取一个U分量和一个V分量。YV12格式与IYUV类似。
  ¨ YUV411、YUV420格式多见于DV数据中,前者用于NTSC制,后者用于PAL制。YUV411为每个像素都提取Y分量,而UV分量在水平方向上每4个像素采样一次。YUV420并非V分量采样为0,而是跟YUV411相比,在水平方向上提高一倍色差采样频率,在垂直方向上以U/V间隔的方式减小一半色差采样,如下图所示。


本文转载自
http://baike.baidu.com/view/189685.htm

2008年9月23日星期二

hello, world!

在这个网站上开始贴文章,是想把平时所看、所想、所得,做书面的整理和记录,供自己日后翻阅。

习惯性的采用以上的标题,作为我在这个网站上张贴的第一篇网志。如果你有着十多年软件开发的经历,如果你知道Turbo C、Borland C++,你一定会明白为什么采用这个标题。

"hello, world!",这是个测试程序在屏幕上输出的内容。Hello, World! 程序是一个在计算器屏幕上,只印出 "Hello, World!"(意为「世界,你好!」)这一行字符串的程序。像这样简单的程序,通常是计算器程序语言的初学者,在学习编写时的第一个程序。它还可以用来确定该语言的编译器、程序开发环境,以及执行环境是否已经安装妥当。

把打印出 "Hello World" 作为第一个测试程序,现在已经成为程序语言学习的传统。该程序由 Brian Kernighan 和丹尼斯•里奇写的计算器程序设计教程《C语言程序设计》(The C Programming Language)而广泛流传;但这本书并不是 "hello, world" 的发源处,虽然这是一个普遍存在的错误认知。

这范例程序最早出现于 1972 年,由贝尔实验室成员 Brian Kernighan 撰写的内部技术文件《Introduction to the Language B》之中。不久同作者于 1974 年所撰写的《Programming in C: A Tutorial》,也延用这个范例;而以本文件扩编改写的《C语言程序设计》也保留了这个范例程序。

Turbo C 是美国Borland 公司的产品,Borland公司是一家专门从事软件开发、 研制的大公司。该公司相继推出了一套 Turbo系列软件,如Turbo BASIC, Turbo Pascal, Turbo Prolog, 这些软件很受用户欢迎。

该公司在1987年首次推出Turbo C 1.0 产品,其中使用了全然一新的集成开发环境,即使用了一系列下拉式菜单,将文本编辑、程序编译、连接以及程序运行一体化,大大方便了程序的开发。

1988 年, Borland 公司又推出Turbo C1.5版本, 增加了图形库和文本窗口函数库等, 而Turbo C 2.0 则是该公司1989年出版的。Turbo C2.0在原来集成开发环境的基础上增加了查错功能, 并可以在Tiny模式下直接生成.COM (数据、代码、堆栈处在同一64K 内存中) 文件。还可对数学协处理器 (支持8087/80287/80387等)进行仿真。Borland 公司后来又推出了面向对象的程序软件包Turbo C++,它继承发展Turbo C 2.0 的集成开发环境, 并包含了面向对象的基本思想和设计方法。1991年为了适用Microsoft 公司的Windows 3.0 版本, Borland 公司又将Turbo C++ 作了更新, 即Turbo C 的新一代产品Borlandc C++也已经问世了。

Turbo C 2.0是我当年学习编程的第一个开发环境。这所谓的当年,应该是十五六年前的事情了,那一年大概是1993年。从学习Turbo C, Fortran,Borland C/C++, Delphi, 一直到后来Visual Basic, Visual C++, Perl, Java, ASP, PHP。其实学习不同的编程语言是大同小异的事情,无非不过熟练掌握这种语言的数据类型、关键字、条件分支、循环、程序体,以及开发调试的环境。每次写第一个测试程序,都习惯性的写到 "hello, world!"

在GNU上有一个关于"hello, world!"的笑话,非常有趣。不过看懂这个笑话,需要一点编程方面的知识。如果你看不懂这个笑话,哦,对不起,你一定不是做这行的。

http://www.gnu.org/fun/jokes/helloworld.html