图像旋转 错切算法原理_图像算法原理与实践——色彩表示模型

一、图像像素坐标系

当一张图片在显示设备上展现在用户面前的时候,显示设备是如何进行工作的呢?显示设备展现内容的时候,是使用一个个显示点组合来展现最终的显示内容,每个显示点可以显示一个颜色,我们把这些一个个显示颜色点的点称之为“像素”,每个像素点可以显示一个颜色,这样几个百万个像素点就构成了一个完整的显示屏幕。在现实环境下,不同的显示设备中每个像素点显示的颜色范围也不一样,最简单的LED显示屏,只能显示黑色或者白色一种颜色,中端一些的显示屏可以由黑色到白色不同深度的灰度图(类似八九十年代的黑白电视机显示方式),后来又出现采用索引方式的彩色图像显示(但是这一类彩色图像不能显示所有彩色空间的颜色值,所以通常称之为伪彩),直到后来能够完整显示 红、绿、蓝三原色构成的所有色域空间的显示设备,这种设备称之为真彩。随着硬件设备性能的提升和价格的降低,目前我们接触到的大部分显示设备全部都是真彩显示。

根据硬件设备的显示原理,在计算机中为了保存图像内容,也采用保存像素点颜色值的方式。一张图像又一个个独立的像素点沟通,每个像素点显示的颜色值使用不同数量的字节数据保存下来,从而完整的保存一张图像内容数据。

在计算机中,根据不同的应用场景,图像像素的的颜色值有不同的表示方式。对于灰度图像来说,通常每个像素点只需要一个字节来表示该像素点显示的 黑-白-灰 颜色深度;而对于真彩图像来说,每个像素至少需要三个字节来表示其颜色值,如果要考虑图像重叠显示的透明度等,还需要额外字节来表示。在图像表示中,我们通常使用 X-Y轴的二维屏幕坐标系来表示像素位置,与数学几何坐标系不同的是:屏幕坐标系中Y轴的正方向朝下。以320*240 像素大小的图像为例,其像素坐标如下图表示:坐标原点位于左上角,从左往右是X轴的正方向,从上往下是Y轴的正方向。

3cd3fa1735ffe892d0a1956e5193e2ac.png
像素点位置坐标

通常图像数据在整个内存中是连续布局的,在已知图像缓冲区起始地址的情况下,我们可以计算到任意像素位置的颜色值。

假设图像缓冲区起始地址为 pImgBuffer,每个像素使用 nPxlBytes 个字节来表示颜色值,那么对于 (nImgWidth * nImgHeight)大小的图像中,任意像素点 (x, y) 的颜色值数据地址就为: pBuffer + (y * nImgWidth * nPxlBytes) + (x*nPxlBytes)

二、灰度图像表示方式

在灰度图像中,每个像素使用1个字节来表示颜色值,由于计算机中1个字节可以表示的无符号数值范围是[0, 255],故灰度图像中每个像素可以表示256个灰度值。 其中 像素值=0,表示纯黑色;像素值=255表示纯白色;中间的像素值则是由纯黑到纯白色的线性插值。

6e54aaa7523a538a91833852b48fe0c8.png
绘图图像颜色值 (归一化)

对于灰度图像在内存中的数据布局,按照每个像素1个字节来线性存放,以320*240 像素图像为例,其内存布局如下:

48070bb24f2fd5f602fe0dbe825707e2.png
320*240灰度图像的内存布局

在实际内存保存时,我们直接根据图像宽高来创建对应的字节数即可。

// 内存占用字节数 = 图像宽度 * 图像高度 * 每个像素占用字节

颜色值的归一化表示

在进行图像算法处理的时候,为了计算方便,我们通常会将图像像素的颜色值归一化到0.0~1.0这个浮点值范围内,这样可以进行更加方便的数值计算。对于灰度图像来说,灰度字节0x00表示0.0这个浮点灰度值,而0xFF(255)则表示1.0灰度值,这样就可以把灰度值以连续值方式进行。两者之间的转换关键很简单:

整数值 = (int)(浮点值*255); 例如: 0.73 颜色值保存到字节中就是 0xBA(186)

浮点值 = (float)(整数值 / 255.0);

三、彩色图像RGB表示方式

彩色图像的表示方式稍微复杂一些,每个彩色颜色都可以使用红、绿、蓝三种基本光学三原色来构成。对此每个像素也使用3个字节来表示颜色值,分别表示 Red、Green、Blue三原色的各个分量的值,由这三原色来构成所有的真彩色效果。对于R、G、B这三个分量我们又通常称之为三个独立的色彩通道。 这里每个颜色通道值范围是在[0, 255]之间,故RGB通道的3个字节总计可以表示 256*256*256=16777216种颜色。

ddf073d763df9e879a5c85cad775f575.png
光学三原色

在RGB色彩坐标系中,RGB(0, 0, 0)值表示纯黑色,RGB(255, 255, 255)值表示纯白色,其他不同的RGB色值组合构成各种不同的颜色。我们可以根据这三原色建立一个三维坐标系,三个坐标轴分别表示 Red、Green、Blue三个通道的值,每个真彩颜色值属于这个三维立方体空间中的任意一点。 从RGB色彩坐标系中可以看到,纯黑色就处于坐标原点,而纯白色处于原点的对角点,在纯黑色和纯白色之间的对角线上的颜色值也是灰度值,即:RGB彩色坐标系完全可以描述灰度图。在RGB色彩格式中,只要三个分量的颜色值一样,则就表示了灰度图,例如: RGB(80, 80, 80) 就表示了灰度值。其他空间的离散点直接表示对应的色彩。

afebac29e5fef10864648ed6e9b49513.png
RGB三原色色系坐标空间

彩色图像在内存中的数据布局稍微复杂一些,每个像素需要3个字节分别表示Red、Green、Blue三个分量值,在内存中各个分量是依次顺序存放的。以320*240像素大小的彩色图像为例,其内存布局如下:

d512c946c3a0fa5c2ed395fcb426b602.png

在实际内存操作时,我们可以使用如下代码进行操作

// 内存占用字节数 = 图像宽度 * 图像高度 * 每个像素占用字节
int nPxlBytes = 3;   // 每个像素占用3个字节
int nBufSize = nImgWidth * nImgHeight * nPxlBytes; 
uint8_t  *pRgbBuffer = (uint8_t*)malloc(nBufSize);

// 对于(x,y) 像素点的颜色值访问
uint8_t  *pPixelData = pRgbBuffer + (nImgWidth * y * nPxlBytes) + (x * nPxlBytes);
pPixelData[0] = 128;  // 将 (x,y)像素点的颜色值设置为 RGB(128, 255, 64)
pPixelData[1] = 255;
pPixelData[2] = 64;

1、色彩通道排布

需要注意的是在不同的设备上,考虑到图像数据不同的优先处理顺序,因此有些设备上有时会有其他的色彩通道排布方式。例如:BGR格式,在这种格式中将Red和Blue通道的字节顺序调换了一下,其内存布局也对应的如下,具体哪种排布方式看具体应用场景和存储方式。

8b684cbd1ecd1f948fe8df237f8c5d5d.png
BGR通道排列方式的内存

2、图像alpha通道的保存

在实际应用场景中,通常会有多张图像重叠显示的情况,最简单的一种显示方式是上层的图像直接遮挡住下层图像显示,这种显示方式称之为遮罩。不过更多的显示方式是带一定透明度的显示,即:上层图像带有一定的透明度,可以通过上层图像的还是可以隐约看到下层的图像。(如下图的效果)

3999c1f8a2a24862bb29694a6cb595ac.png

在这种显示方式下,重叠区域需要将两张图片做混合处理,基本混合算法公式: dest = srcUp * alpha + srcDn *(1.0-alpha) 这里alpha就是上层图像的透明度。在实际进行运算操作时,每个像素的三个色彩通道分别独立的按照上面这个公式进行计算,则可以计算出最终显示出来的像素颜色。

a0b60ed723282202c668aa868d81b1e3.png
透明度混合计算公式

这里表示透明度的alpha我们通常直接称之为"Alpha通道"(与R、G、B色彩通道保持一致叫法),从计算公式可以看出,当alpha通道值越大,上层图像显示越明显,下层图像越看不清。我们可以所有的像素点计算都使用一个alpha值计算透明度,也可以每个像素使用不同的透明度,这样可以做到上层图像仅显示部分的效果。为此,考虑到数据的更加通用性,很多处理软件在保存图像数据时,每个像素都额外增加一个字节,来保存像素的alpha通道,这样正常的一张图像,每个像素点需要4字节来保存 RGBA数据,这就是我们通常所说的 RGBA或者BGRA 像素格式。

109d6f948bd8d70c06c2fc2b8971cde1.png
RGBA像素格式的内存布局

3、归一化值的表示

同灰度图像一样,在进行图像算法计算的时候,我们通常会将RGBA各个通道的颜色值分别归一化到0.0~1.0这个浮点值范围内,这样可以进行更加方便的数值计算。例如:RGBA(255, 50, 78, 128) 这个颜色值归一化后表示值是 (1.0, 0.196, 0.306, 0.5)

四、图像YUV色彩格式表示

根据人眼的生理特性,人眼对于亮度的敏感度远大于对于颜色细节的敏感度,因此在现代彩色电视系统中,通常不会直接采用RGB的表示方式,而是采用YUV或者YCrCb等表示方式。

0db3c2c12ddd14fb8d1773da6ebaa87c.png

在现代三管彩色摄像机或彩色CCD(点耦合器件)摄像机,它把摄得的彩色图像 信号,经分色、分别放大校正得到RGB,再经过矩阵变换电路得到亮度信号Y 和 两个色差信号 U(蓝基色分量与亮度的差值信号)和 V(红基色分量与亮度的差值信号), 最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这就是我们常用的YUV色彩空间。而采用YUV颜色空间的好处有:一是解决了彩色电视机和黑白电视机的兼容问题(因为黑白电视机只需要提取信号中的Y信号即可显示出来);二是可以减少数据码率,节省传输带宽。通常情况数字化后的 Y:U:V = 8:4:4或者Y:U:V = 8:2:2,即亮度信号Y需要8比特表示,UV需要4个或者2个比特表示,我们知道,RGB颜色空间下,需要24比特来表示一个颜色,而利用YUV则仅需要16比特或者12比特,达到压缩的目的。

根据实际硬件设备处理后的YUV数据值范围,Y~ [0,1] U,V~[-0.5,0.5] ,这样的浮点值不利于数据存储,因此在实际处理和保存时,会对YUV数据值进行量化处理,将其值范围扩大到:Y~[16,235] U ~[16-240] V~[16-240] ,这样YUV的数据值都限制在[0, 255]范围内,各个分量可以只使用一个字节就可以来表示和存储。(注: YCbCr中的Cb和Cr分量就相当于UV两个分量)

a5446dd1eb1872f0fe4990d51518622c.png
BT601 量化后的UV 的坐标图(横坐标为u,纵坐标为v,左下角为原点)

YUV色彩格式 与 RGB色彩格式 表示的颜色内容本质是一致的,他们之间存在固定的转换公式。不过有一点要注意:不同制式的YUV格式与RGB转换公式稍有差距

以BT601制式为例,YUV与RGB转换公式如下

b8255a9835be4a7289eaeee75a15f10b.png
RGB转YUV(RGB归一化的值,YUV未量化的值)

b97f59ef0b98591ef592780bdb1083f9.png
YUV转RGB(RGB归一化的值,YUV未量化的值)

考虑到YUV在实际保存时都是量化后的处理单个字节数据,因此YUV量化值 与 RGB字节值之间的转换公式如下 (该公式在实际开发中更加通用)

0155737be01fe0ed86eb0ae413a9712f.png
RGB转YUV, RGB范围[0, 255], YUV是量化后的值

b4ba820cc934414a1cd8a11cc0f2ec04.png
YUV转RGB, YUV是量化后的值,RGB范围[0, 255]

采用C语言代码描述

// 内存占用字节数 = 图像宽度 * 图像高度 * 每个像素占用字节
int nPxlBytes = 3;   // 每个像素占用3个字节
int nBufSize = nImgWidth * nImgHeight * nPxlBytes; 
uint8_t  *pRgbBuffer = (uint8_t*)malloc(nBufSize);

// 对于(x,y) 像素点的颜色值访问
uint8_t  *pPixelData = pRgbBuffer + (nImgWidth * y * nPxlBytes) + (x * nPxlBytes);
int16_t R = pPixelData[0];
int16_t G = pPixelData[0];
int16_t B = pPixelData[0];

// 将像素的RGB转换为YUV数据
int16_t Y = (int16_t)(0.2568f*R - 0.1479f*G + 0.4375f*B + 16);
int16_t U = (int16_t)(-0.1479f*R - 0.2896f*G - 0.4375f*B + 128);
int16_t V = (int16_t)(0.4375f*R - 0.3666f*G - 0.0709*B + 128);

// 值域限制处理
Y = (Y < 16) ? 16 : Y;
Y = (Y > 235) ? 235 : Y;
U = (U < 16) ? 16 : U;
U = (U > 240) ? 240 : U;
V = (V < 16) ? 16 : V;
V = (V > 240) ? 240 : V;

1、YUV数据的采样格式

在实际应用场景中,不同的应用场景对于YUV数据有不同的存储格式,YUV格式有两大类:planar和packed。planar模式中,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V;而packed模式,每个像素点的Y,U,V是连续交叉存储的。

对于每个像素点的YUV数据,也有不同的采样方式,不同的采样方式占用不同的存储空间

e5a45fa1bd27ee534afd1e7d37dbc7e0.png

YUV 4:4:4采样: 每一个Y对应一组UV分量。每1个像素对应1个Y、1个U、1个V。这样每个像素占用3个字节。

YUV 4:2:2采样:每两个Y共用一组UV分量。 每4个像素对应4个Y、公用2个U、公用2个V。这样每个像素平均占用2个字节。

YUV 4:2:0采样:每四个Y共用一组UV分量。每4个像素对应4个Y、公用1个U、公用1个V。这样每个像素平均占用1.5个字节。

2、YUV数据的内存排列格式

常见的排列格式有YUV420P、YUV420SP、I420、NV12、NV21等,不同系统平台上有多种不同的排列格式。

YUV420P,Y,U,V三个分量都是平面格式,分为I420和YV12。I420格式和YV12格式的不同处在U平面和V平面的位置不同。在I420格式中,U平面紧跟在Y平面之后,然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。

YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。

I420: YYYYYYYY UU VV =>YUV420P

YV12: YYYYYYYY VV UU =>YUV420P

NV12: YYYYYYYY UVUV =>YUV420SP

NV21: YYYYYYYY VUVU =>YUV420SP

3、YUV格式应用场景

YUV数据表示格式应用最多的场景是JPG图片和视频文件中。在JPG文件中,图像的像素格式通常是以YUV420P方式来存储,然后经过编码压缩算法进行压缩后保存。而在主流的.mp4等视频文件中,几乎所有的视频帧像素 数据也都是以YUV像素格式来进行处理的,所以掌握YUV数据格式还是比较重要的。

五、图像HSI色彩格式表示

最后讲解一种在图像处理算法中比较常用的HSI色彩格式。HSI格式在图像格式的存储中很少使用,但是在图像处理算法过程中确具有十分重要的地位。前面的RGB模型也好,或者YUV模型也好,可以很好的处理图像数据的存储格式,但是却不能对于色彩有很好的解释能力。例如:用户想对当前图像的某种颜色调得更加浓郁一些;或者将红色的图像调节得变得偏粉红色一些,针对这样一些的应用场景,上述的色彩格式都 无能为力了,因此,在图像处理算法中推出了很重要的适合人类视觉表示的HSI色彩格式。

在HSI色彩系统中,每个像素点的颜色使用:色调(Hue)、饱和度(Saturation) 和 亮度 (Intensity) 三个属性来描述。

色调(Hue): 表示颜色的相位角,是彩色最重要的属性,决定颜色的本质。红、绿、蓝分别相隔120度;互补色分别相差180度,即颜色的类别。简单来说表示是蓝色还是粉色或者绿色。

饱和度(Saturation):表示颜色的深浅程度,饱和度越高,颜色越深。与白色的比例有关,白色比例越多,饱和度越低。简单来说就是表示 深红、浅红、粉红 这种不同的深浅程度。

亮度(Intensity):表示色彩的明亮程度,人眼对亮度很敏感。简单来说就是颜色比较亮或者比较暗。

fa0908f5b505d82f6d3e564de67247de.png
HSI色彩坐标系

HSI 和R GB的色彩坐标系也是相互对应的,两者之间有专门的换算方式,不同的换算算法也有不同的换算公式。

4bf74b77e36a526eacb8c5d8321b7990.png
RGB转HSI公式

f0557612c3d67ae26d8aff48c35402c7.png
HSI转RGB公式

这里转换公式要注意一下,在这两个转换公式中 RGB值是归一化的值,在[0.0, 1.0]范围内,色调H可以用得到的值除以360归一化,其他饱和度和亮度两个分量也归一化在[0.0, 1.0]范围内。

// RGB转换为HSI的处理
// HSI转换成归一化的RGB值

HSI色彩模型在图像基础调节具有很重要的作用,在常见的美图软件中经常会有一个基础调节项,调节图像的 亮度、色调、饱和度、对比度、高低光等 其中前面三种就可以直接在HSI色彩模型中调节相应的分量即可。

总结

本章主要讲解了在不同的应用场景中,几种常见的色彩模型表示方式,主要针对 灰度图、RGB色彩模型、YUV色彩模型 和 HSI色彩模型进行详细的讲解,希望大家能够掌握模型中主要的原理和内存布局,以及不同色彩模型之间的转换。

文章系列目录

华叔-视觉魔术师:图像算法原理与实践——绪论​zhuanlan.zhihu.com
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值