传统图像算法

彩色空间以及优化思想

2018-10-12  本文已影响0人  雨幻逐光
  1. 彩色空间的介绍

其实本质上来说,彩色空间是坐标系系统和子空间的说明。其中,位于该坐标系统中的每种颜色都是由单个点来表示。

由此我们引入了很多种彩色模型。如 RGB 模型,以及由二次色组成的 CMY 和 CMYK 的彩色模型,以及 HSI 和 YUV 等颜色编码模式。

现在简单介绍下 RGB 模型。下图是 RGB 的坐标系统:


11.png

如图,其中x轴坐标代表红色(R)通道的灰度值,y轴坐标代表绿色(G)通道的灰度值,z轴坐标代表(B)通道的灰度值。一般我们都将这些坐标值归一化到[0, 1]区间内。所以上面的 rgb 立方体原点(0, 0, 0)表示黑色,(1, 1, 1)点代表白色。而我们计算机的全彩色位图的每个像素值就可以用 RGB 三通道各 256 种灰度值构成。

  1. 借彩色空间模型转换介绍两种常用的代码优化思想(以下优化思想仅限于 CPU。GPU 可以直接采用浮点数直接计算)

上面我们知道了彩色模型有很多。现在我们给出 RGB 模型和 YUV 模型之间的转换公式:

(1) RGB转YUV

Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

(2) YUV转RGB

R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U

首先,我们可以观察下上面的转换公式。我们会发现 RGB 转换成 YUV 时有大量的浮点乘法和加法的计算。因此,我们的出发点可以是用整型计算取代浮点型计算。通过移位方式代替乘法计算。当然这两种替换都将会造成结果精度的损失。所以我们可以通过额外的一些 trick 来保证我们的精度下降相对较少。

**【1】方案一: **

我们可以先在等式两边同乘以一个较大的数。以减少后面用整型数代替浮点数后带来的精度损失。

Y * 256 = 0.299 * 256R + 0.587 * 256G + 0.114 * 256B

U * 256 = -0.147 * 256R - 0.289 * 256G + 0.436 * 256B
V * 256 = 0.615 * 256R - 0.515 * 256G - 0.100 * 256B

R * 256 = Y * 256 + 1.14 * 256V
G * 256 = Y * 256 - 0.39 * 256U - 0.58 * 256V
B * 256 = Y * 256 + 2.03 * 256U

此处选择乘以 256 是方便之后的用移位操作来代替乘法。当然选择越大的数理论上损失的精度更小,但也要考虑到溢出问题。所以可以选择更大的 2 次方幂,如1024。

通过计算我们可以得到下面的式子:

256Y = 76.544R + 150.272G + 29.184B

256U = -37.632R - 73.984G + 111.616B

256V = 157.44R - 131.84G - 25.6B

256R = 256Y + 291.84V

256G = 256Y - 99.84U - 148.48V

256B = 256Y + 519.68U

接下来,我们把浮点数全部用整数代替:

256Y = 77R + 150G + 29B

256U = -38R - 74G + 112B

256V = 158R - 132G - 26B

256R = 256Y + 292V

256G = 256Y - 100U - 149V

256B = 256Y + 520U

之后,我们就可以用移位操作进一步优化乘法计算:

Y = (77R + 150G + 29B) >> 8

U = (-38R - 74G + 112B) >> 8

V = (158R - 132G - 26B) >> 8

R = (256Y + 292V) >> 8

G = (256Y - 100U - 149V) >> 8

B = (256Y + 520U) >> 8

当然,通过观察,我们仍然发现存在乘法计算。所以我们可以用移位操作进一步优化乘法计算。但是这个情况下又再次引入精度损失。这是因为我们的乘数不在是 2 的次方幂。当然我们可以用移位操作加上加法的办法进行精确优化,如我们可以用 Y=(Y<<3)+Y 来代替 Y=9*Y。经过优化变成下面形式:

RGB转YUV:

Y = ((R << 6) + (R << 3) + (R << 2) + R + (G << 7) + (G << 4) + (G << 2) + (G << 1) + (B << 4) + (B << 3) + (B << 2) + B) >> 8;
U = (-((R << 5) + (R << 2) + (R << 1)) - ((G << 6) + (G << 3) + (G << 1)) + ((B << 6) + (B << 5) + (B << 4))) >> 8;
V = ((R << 7) + (R << 4) + (R << 3) + (R << 2) + (R << 1) - ((G << 7) + (G << 2)) - ((B << 4) + (B << 3) + (B << 1))) >> 8;

YUV转RGB:

R = ((Y << 8) + ((V << 8) + (V << 5) + (V << 2))) >> 8;
G = ((Y << 8) - ((U << 6) + (U << 5) + (U << 2)) - ((V << 7) + (V << 4) + (V << 2) + V)) >> 8;
B = ((Y << 8) + (U << 9) + (U << 3)) >> 8;

【2】方案二:

可以通过查表法用空间换时间的方法提高时间效率:

由 RGB 转 YUV 为例:

Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

因为我们知道 R,G,B 三个通道的值为 0 到 255。所以我们可以计算出对应的每种可能值,并用 RGB 的值作为索引来读取每个值。例如第一个公式我们的 Y 是由 0.299 * R value 加上另外两个通道的权重和的结果。所以对于 Y 中 R 分量的权重和我们可以通过一个表格来得到值。这个表格如下:

map_list[256] = {0, 0.299, 0.598, 0.897, 1.196 …………………………}

即 0 * 0.299, 1 * 0.299, 2 * 0.299, 3 * 0.299, 4 * 0.299 以此类推…………

这样我们就能以O(1)时间来计算我们的乘法操作了。

上一篇 下一篇

猜你喜欢

热点阅读