颜色矩阵

色彩矩阵分析

在Android中,系统使用一个颜色矩阵— —ColorMatrix,来处理图像的色彩效果。对于图像的每个像素点,都有一个颜色分量矩阵用来保存颜色的RGBA值(下图矩阵C),Android中的颜色矩阵是一个4x5的数字矩阵,它用来对图片的色彩进行处理(下图矩阵M)。如下:
M = [ a b c d e f g h i j k l m n o p q r s t ] C = [ R G B A 1 ] M= \left[ \begin {matrix} a&b&c&d&e \\ f&g&h&i&j \\ k&l&m&n&o \\ p&q&r&s&t \end {matrix} \right] C= \left[ \begin {matrix} R \\ G \\ B \\ \Alpha \\ 1 \end {matrix} \right]
如果我们想要改变一张图像的色彩显示效果,在Android系统中,我们会用矩阵的乘法运算来修改颜色分量矩阵的值。上面矩阵M就是一个4x5的颜色矩阵。在Android中,它会以一维数组的形式来存储[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t],而C则是一个颜色矩阵分量。在处理图像时,使用矩阵乘法运算MC来处理颜色分量矩阵,如下:
N = M C = [ a b c d e f g h i j k l m n o p q r s t ] [ R G B A 1 ] = [ a R b G c B d A e f R g G h B i A j k R l G m B n A o p R q G r B s A t ] = [ R G B A ] N=MC= \left[ \begin {matrix} a&b&c&d&e \\ f&g&h&i&j \\ k&l&m&n&o \\ p&q&r&s&t \end {matrix} \right] \left[ \begin {matrix} R \\ G \\ B \\ \Alpha \\ 1 \end {matrix} \right] = \left[ \begin {matrix} aR&bG&cB&d\Alpha&e \\ fR&gG&hB&i\Alpha&j \\ kR&lG&mB&n\Alpha&o \\ pR&qG&rB&s\Alpha&t \end {matrix} \right] = \left[ \begin {matrix} R' \\ G' \\ B' \\ \Alpha' \end {matrix} \right]
利用线性代数知识可知:

R' = aR + bG + cB + dA + e
G' = fR + gG + hB + iA + j 
B' = kR + lG + mB + nA + o
A' = pR + qG + rB + sA + t

从这个公式可以发现,矩阵M中:

  • 第一行的 abcde 用来决定新的颜色值中的R— —红色
  • 第二行的 fghij 用来决定新的颜色值中的G— —绿色
  • 第三行的 klmno 用来决定新的颜色值中的B— —蓝色
  • 第四行的 pqrst 用来决定新的颜色值中的 A \Alpha — —透明度
  • 矩阵M中第五列 ejot 值分别用来决定每个分量中的 offset ,即偏移量

这样划分好后,这些值的作用就比较明确了。

初始颜色矩阵

接下来,我们重新看一下矩阵变换的计算公式,以红色分量为例:

R' = aR + bG + cB + dA + e

如果令 a=1,b、c、d、e都等于0,则有R’=R。同理对二、三、四行进行操作,可以构造出一个矩阵,如下:
M = [ 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 ] M= \left[ \begin {matrix} 1&0&0&0&0 \\ 0&1&0&0&0 \\ 0&0&1&0&0 \\ 0&0&0&1&0 \end {matrix} \right]
把这个矩阵代入公式 N=MC,根据矩阵乘法运算法则,可得 R’=R,G’=G,B’=B,A’=A。即不会对原有颜色进行任何修改,所以这个矩阵通常被用来作为初始颜色矩阵。

改变颜色值

那么,当我们想要改变颜色值的时候,通常有两种方法:

  • 改变颜色的offset(偏移量)的值
  • 改变对应 RGBA 值的系数
  1. 改变偏移量

    从前面的分析中可知,改变颜色的偏移量就是改变颜色矩阵的第五列的值,其他保持初始矩阵的值即可。如下示例:
    M = [ 1 0 0 0 100 0 1 0 0 100 0 0 1 0 0 0 0 0 1 0 ] M= \left[ \begin {matrix} 1&0&0&0&100 \\ 0&1&0&0&100 \\ 0&0&1&0&0 \\ 0&0&0&1&0 \end {matrix} \right]
    上面的操作中改变了R、G对应的颜色偏移量,那么结果就是图像的红色和绿色分量增加了100,即整体色调偏黄显示。

  2. 改变颜色系数

    如下操作:
    M = [ 1 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 1 0 ] M= \left[ \begin {matrix} 1&0&0&0&0 \\ 0&2&0&0&0 \\ 0&0&1&0&0 \\ 0&0&0&1&0 \end {matrix} \right]
    改变G分量对应的系数g的值,增加到2倍,这样在矩阵运算后,图像会整体色调偏绿显示。

色调

Android系统提供了 setRotate(int axis, float degrees) 方法来修改颜色的色调。第一个参数 axis,用0、1、2分别代表红、绿、蓝三个颜色通道;第二个参数 degrees 就是要修改的值。如下:

ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0, hue0);
hueMatrix.setRotate(1, hue1);
hueMatrix.setRotate(2, hue2);

Android系统的 setRotate(int axis, float degrees) 方法其实就是对色彩的旋转运算。RGB色是如何旋转的呢,首先用R、G、B三色建立三维坐标系,如下:

matrix1

RGB坐标

这里我们可以把一个色彩值看成三维空间里的一个点,色彩值的三个分量可以看成该点对应的坐标(三维坐标)。我们先不考虑,在三个维度综合情况下是怎么旋转的,我们先看看,在某个轴作为Z轴,在另两个轴形成的平面上旋转的情况。假如,我们现在需要围绕蓝色轴进行旋转,我们对着蓝色箭头观察由红色和绿色构造的平面。然后顺时针旋转 α \alpha 度。如下图所示:

matrix2
围绕蓝色轴进行旋转 α \alpha

在图中,我们可以看到,在旋转后,原R在R轴的分量变为:Rcos α \alpha ,且G分量在旋转后在R轴上也有了分量,所以我们要加上这部分分量,因此最终的结果为 R’ = Rcos α \alpha + Gsin α \alpha ,同理,在计算G’时,因为R的分量落在了负轴上,所以我们要减去这部分,故 G’ = Gcos α \alpha - Rsin α \alpha

饱和度

Android系统提供了 setSaturation(float sat) 方法来修改颜色的饱和度。参数 sat:表示把当前色彩饱和度放大的倍数。取值为0表示完全无色彩,即灰度图像(黑白图像);取值为1时,表示色彩不变动;当取值大于1时,显示色彩过度饱和。如下:

ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);

亮度

当三原色以相同比例进行混合时,就会显示出白色。Android正是利用这个原理对图像进行亮度的改变。如下:

ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
发布了19 篇原创文章 · 获赞 0 · 访问量 859

猜你喜欢

转载自blog.csdn.net/qq_32036981/article/details/103866659