购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.1 像素与图像

借我借我一双慧眼吧,让我把这纷扰看个清清楚楚,明明白白,真真切切。

——《雾里看花》

人类用双眼去感知这个五彩斑斓的世界。怎奈人生匆匆,如昙花一现,要是能永久铭记这白驹过隙般的时光该有多好。

本节将介绍图像在计算机中的表示与存储,让我们进一步看清色彩的世界。

2.1.1 视觉物理

颜色的分辨

刚出生的婴儿只能看到黑白色,随着生长发育,三四个月后,就能分辨出颜色了。

之所以能区分颜色,得益于视网膜中的 视锥细胞 (Cones),每只眼球都有600~700万个视锥细胞,它们能将光刺激转换为神经冲动。

在恐龙时代,哺乳动物为了躲避恐龙,都躲在黑洞里。这使得原先的4种视锥细胞退化成了两种(蓝色和绿色)。为了生存,又进化出一种 视杆细胞 (Rods),每只眼球约有1.2亿个视杆细胞,能在弱光下看清事物。

在恐龙灭绝后,灵长类为了区别成熟果实的颜色,从绿色视锥细胞逐步变异进化出红色视锥细胞。因此,人类眼中共有3种类型的视锥细胞(蓝色、绿色和红色),而其他哺乳动物则仍是红绿不分的色盲。

1801年,英国物理学家托马斯·杨(Thomas Young,1773—1829)发表了他的色彩研究:人眼可以有红光、绿光、紫光3种视觉神经的色感。

现代的实验数据也证明了这个结论。这3类视锥细胞,对不同波长的光谱有着不同的灵敏波峰,分别为420nm(蓝)S-cones、531nm(绿)M-cones、558nm(红)L-cones,其中红、绿光谱的灵敏波峰只相差不到30 nm,如图2-1所示。

图2-1 3种视锥细胞对不同光谱的感应

每种细胞都可以分清约100种色级,因此3种细胞大约可以分辨100×100×100=100万种颜色。

视觉精度

波长是光在一个振动周期内移动的距离。可见光的波长范围是380~780nm。

米制是我们比较熟悉的长度测量单位制。1米(m)等于100厘米(cm)。2.54厘米约为1英寸(inch)。1英寸在打印机上约等于72.27个点(point),点的单位记作pt

1个点又可以分解为65 536个小点(scaled point),小点的单位记作sp。

可见光的波长大约是100 sp,在这个级别上四舍五入对人眼是没有区别的。著名的排版系统TEX使用sp的整数倍来处理所有微小长度单位的运算。

因此,我们认为,在sp级别上的整数运算,完全可以达到人的视觉精度。

视觉暂留

1878年,摄影家迈布里奇(E.Muybridge,英国,1830—1904)为了证明马在奔跑时,四脚会同时腾空,设计了一台连续拍照的机器。他准备了24台相机,每台间隔69 cm,快门速度为1/2 000 s。这样可以完整地捕捉到马在一秒内的24张清晰画面。

结果表明,有极短的时间,马确实是四脚腾空的,如图2-2所示。

图2-2 奔跑中的马

人们同时发现,当把这24张图片连续交替展示时,可以看到类似动画的效果。这一现象被称为 视觉暂留

实际上,早在1824年,视觉暂留现象就由伦敦大学的彼得·马克·罗杰特教授(Peter Mark Roget,英国,1779—1869)在他的 Explanation of an optical deception in the appearance of the spokes of a wheel when seen through vertical apertures (《移动物体的视觉暂留现象》)中最先提出。

实验表明,视觉暂留时间为0.1~0.4 s。我们将一秒钟播放的图像数叫作 帧率 (frame rate),单位是fps(frame per second)。电影一般使用24 fps,游戏或视频则采用30 fps,小于该值则会感觉卡顿。流畅画面的体验为60 fps,相当于一秒钟60帧,这要求能在16.67 ms内完成一帧图像的计算与显示。现代显示器的刷新率也多为60 Hz。

当帧率大于100 fps时,人们对于画面流畅性的感觉并不明显。120 fps的电影能提供更真实的观影感受。

在下一节,我们将研究像素与颜色在计算机中的表示。

2.1.2 像素与颜色空间

RGB

对应上一节介绍的物理模型,在计算机中,我们将颜色拆分成红(Red,R)、绿(Green,G)、蓝(Blue,B)3个分量进行表示。任何一个颜色都是一个RGB三元组。

每个分量通常都使用8 bit二进制数表示,即最小值为0,最大值为255。例如红色为RGB(255,0,0),黑色为RGB(0,0,0),白色为RGB(255,255,255)。一共有2 24 种组合。

RGB的存储是有字节序的,在小端法机器上,R值通常在最低字节,如图2-3所示。

图2-3 RGB颜色的存储

使用宏DRGB(r,g,b),可以直接得到RGB的整数表示。

img

使用式(2.1),可以将彩色的RGB转换为0~255的灰度值,使用式(2.2)计算会更快一点。

img

FFmpeg是多媒体领域非常著名的一个开源项目,它提供一个命令行工具,也可以完成从彩色图到灰度图的转换。

img

颜色空间

将RGB的值归一化,所有RGB三元组的集合构成了RGB 颜色空间 ,如图2-4所示。

图2-4 RGB颜色空间

显示器使用RGB颜色空间。彩色打印机则使用CMYK颜色空间,它的每种颜色都是青色(Cyan)、洋红色(Magenta)、黄色(Yellow)、黑色(Black)成分的组合。

画家则喜欢用色调(Hue)、饱和度(Saturation)、亮度(Luminance)来描述颜色。

我们需要将颜色空间中的每个样本与现实世界中的一种真实颜色对应起来。即精确定义每一种计算机二进制对应的真实颜色,这就形成了颜色空间的标准。

常见的颜色空间标准有BT.601、BT.709、BT.2020。

·BT.601标准是1982年由CCIR提出的,2011年10月发布第7版,制定了数字电视信号编码,也定义了YUV格式的表示,涵盖了36%的可见光谱。

·BT.709标准是1990年开始制定的,2015年6月发布第6版,定义了高清电视的格式,支持8bit、10bit像素的表示。

·BT.2020标准是2015年10月发布的,定义了超高清电视系统的参数,支持10bit、12bit像素的表示,涵盖了76%的可见光谱。

YUV颜色空间

与RTC密切相关的颜色空间是YUV。Y表示亮度(Luminance或Luma),也就是前面的灰度值,U和V表示色度(Chrominance)和浓度(Chroma)。YUV也称作YCbCr,在BT.601中定义。

使用YUV进行图像编码表示,有两个好处。

·由于人眼对亮度Y特别敏感,对U和V不敏感,因此可以对U、V进行下采样,只保留原先的一半或四分之一的U、V。例如,YUV420中每4个点只保留一个U、V,原先需要4Y+4U+4V,如今只需要4Y+1U+1V,其大小压缩了一半。

·对Y和U、V的后续编码,可以采用不同的压缩策略,将在第6章详细介绍。

在BT.601标准下,要将RGB转换成YUV,可以使用式(2.3):

img

反之,如果要将YUV转换成RGB,可以用式(2.4):

img

上述 R G B Y 的取值范围都是[0,255], U V 的取值范围都是[1,255],我们也称之为Full-Range。

在传统的视频上,还存在一种Video-Range的YUV表示,也被称作Limited-Range。 Y 的取值范围是[16,235], U V 的取值范围是[16,240],其余部分保留,用来传递同步信号。

使用Video-Range转换YUV时,计算公式与Full-Range不同。如果Full-Range和Limited-Range混用,会导致视频有一种“蒙尘”效果,质量下滑,需要格外注意。

下一节,我们将介绍在常见文件中RGB和YUV的字节是如何排列的。

2.1.3 位图与视频帧

RGB颜色分量组合成了像素,像素的二维数组则构成了 位图 (Bitmap)。

BMP文件格式

最基本的位图是BMP格式的,它由14字节的文件头、40字节的信息头、可选的位屏蔽(Bit Mask)、颜色表(Color Table)及RGB像素数组构成,如图2-5所示。

图2-5 BMP文件格式

BMP文件头的14字节如表2-1所示。

表2-1 BMP文件头的14字节

BMP信息头的40字节如表2-2所示。

表2-2 BMP信息头的40字节

位屏蔽和颜色表可以参看MSDN。

像素阵列是实际存储RGB的地方。在BMP文件中,需要注意两点。

(1)行的顺序是从下到上的。这意味着第一个像素是图像最后一行的第一个像素。

(2)每行都会按32位的整数倍对齐。

以下代码可以用来计算一行的实际字节数。

img

对于24位的RGB图像,坐标为( x y )的像素点偏移为:

img

YUV像素格式

RGB24是众多像素格式中最基本的一种,使用命令ffmpeg-pix_fmts可以查看FFmpeg库所支持的全部像素格式,运行结果显示有200种以上。

对于 Y U V 分量表示的图像, U V 分量的采样数可能有3种情况。

·4:4:4采样,每一个 Y 对应一组 U V 分量。

·4:2:2采样,每两个 Y 共用一组 U V 分量。

·4:2:0采样,每四个 Y 共用一组 U V 分量。

本书着重介绍YUV420相关的部分,共有I420、YV12、NV21、NV12这4种格式。

研究的第一步是获得数据样本。借助FFmpeg强大的转换功能,我们可以得到各种格式的图像。在示例的Data/Image目录下有一张24bit.bmp,先看下它的像素格式。

img

注意,命令返回的是BGR24,这要跟RGB24区分开。518×292是该图像的大小。

下一步,我们将其转换为I420与其他像素格式。

img

YUV420的4种格式如图2-6所示。 Y 平面都是在最前面, U V 平面有所不同。

图2-6 YUV420的4种格式

YV12与I420交换了 U V 平面的位置,NV12与NV21的 U V 交错。

可以校验一下所得的结果。首先预览一下转换后的图像。

img

然后计算一下大小,原图共有518×292=151 256个像素。

因此RGB共需要151 256×3=453 768字节。

YUV420则需要453 768÷2=226 884字节。

在Windows上用dir,或者macOS上用wc-c看到的文件大小正是此值。

img

可按比例推算出, U 开始于文件2/3=151 256处, V 开始于文件5/6=189 070处。

ImageViewer

根据前面介绍的内容,我们可以动手开发一个位图显示工具ImageViewer。

该工具支持以下功能。

·Bitmap文件的加载与展示。

·Bitmap文件头与信息头的展示。

·RGB转成YUV420格式。

·YUV420格式的加载展示。

ImageViewer的总体界面如图2-7所示。

图2-7 ImageViewer的总体界面

在“Bitmap”菜单中,我们使用了两种加载与绘制方式。Win32 API的SetPixel可进行逐点的绘制,而StretchDIBits则可以绘制像素矩阵。实际体验后,会发现后者的绘制性能要高很多,前者主要可以帮我们看清每个像素的内存排布。

“File Header”和“Info Header”菜单会将Bitmap文件的头部结构进行字符串格式化输出,这种dump结构体的方法是一种非常好的软件调试手段。

最后的“Save as I420”,会将加载的位图转换为I420格式的YUV文件进行保存。

这里有一些实现的细节需要注意。

首先是下采样的方法。我们要每4个点计算一个 U V ,这里取的2×2的像素矩阵。在水平最右的边界上,如果有单独的一列,可简单忽略 。在垂直下方的边界上,如果有单独的一行,则只会计算横排两个像素值的平均值。

然后是计算平均值的方法。由于舍入问题,两个像素的平均值不能简单相加除以2。

img

我们分别得到4个像素对应的 R G B 分量的平均值,再通过式(2.5)来计算 Y U V

img

在“YUV”菜单下,可先加载刚生成的YUV文件,将其转回RGB显示,代码使用式(2.6):

img

再使用Clamp()函数将其输出限制在0~255。

具体的绘制显示细节,读者可以直接查看示例工程的代码。

总结

本节我们介绍了视觉的物理原理。对应3种视锥细胞,我们建立了RGB的颜色模型。RGB转换到YUV有着不同的颜色空间标准。

我们使用FFmpeg进行了像素格式转换,并实现了一个类似FFplay的图像浏览工具。

下一节,我们将关注视频的采集设备。

要点回顾

·视锥细胞,视觉暂留,RGB颜色空间。

·不同标准下的YUV转换公式。

·不同的YUV420存储格式。

参考阅读

1.FFmpeg官网提供的源码,是学习媒体格式很好的素材。

2.微软的 Recommended 8 -Bit YUV Formats for Video Rendering 是对YUV的细致介绍。

3.WebRTC提供的YuvConvertor.java是一个精确的YUV转换浮点实现。

4.Google开源库LibYUV的row_common.cc提供了各类像素格式转换到I420的方法。

5.颜色空间的相关介绍,可以参考BT.601、BT.709、BT.2020。

练习题

1.[30分钟](色盲)红绿色盲患者通常不能分辨红色和绿色,上网查询这种病症的第一发现者是谁。

2.[30分钟](四色视觉者)由于X染色体变异,部分人会多一种橙色视锥细胞,理论上他们可以识别出多少种不同的颜色?上网查询皮皮虾有多少种视锥细胞。

3.[2小时](Video-Range检测)写一个函数,检测输入的图像是否是Video-Range。

4.[1小时](RGB转换)写一个函数,完成BGR24到RGB24的转换。

5.[1人天](颜色抖动)RGB565使用16位来表示颜色,人眼最敏感的绿色用6位。从ARGB转换到RGB565时,需要做颜色抖动(dither)下采样,学习并实现该函数。

6.[1人天](YUY2)YUY2格式在Windows采集中比较常见,它属于YUV422,试上网了解其格式。 2tDnVUC+xSz0mF/OC4ZAXTgenbrzyba8lDgyV8+TrSdLTLWxQ40ecM0OqzJP9w9r

点击中间区域
呼出菜单
上一章
目录
下一章
×