?
?
4.4.4 色相矩阵hue的算法原理
?
我们尝试将hue设置为60,效果如图 4.41所示。
?

图 4.41 hue设置为60后的效果
?
可以看到,每种颜色都绕着色相环的圆心旋转了60度,红偏移60度变成了黄,黄偏移60度变成了绿……(图 4.42)白色和黑色由于不受色相值影响,所以色值不变。
?

图 4.42 色相偏移60度
?
如果色相设置为负数,则颜色会往相反的方向旋转。从-180度到180度,每个点都可以绕着色相环转足一圈,换而言之,每种颜色都可以被AdjustColor调整为任意的色相,只是任意两种颜色的色相差始终保持不变。
?
色相是一个角度值,它的大小既不像饱和度那样跟RGB差值有着明显的相关性,也没有0饱和度矩阵和1饱和度矩阵那样的极端矩阵供我们参考,但是我们同样有一些特征性的矩阵可供参考。
?
首先,在色相转换的过程中,明度基本上保持不变,所以灰度矩阵仍然可以套用进来:
?

?
不过色相转换中,灰度心理学公式的系数与以上的矩阵不完全相同:
?
两个矩阵主要体现电子屏幕色彩与图纸色彩对肉眼刺激程度的差异,电子屏幕由于具有发光的特性,因此对于人眼来说,色彩的对比度会相对强烈一些,绿色会显得更加刺眼,所以此处绿色的系数要比传统心理学系数稍大。
?
为了方便后续的讨论,我们把红绿蓝三个通道的系数分别表示为lumR,lumG和lumB
?
然后,单位矩阵也可以给我们提供一定的指导作用,因为当hue=0时,图像的颜色不发生任何改变,所以hue=0时的色相矩阵应与单位矩阵相等。
?
如果用饱和度矩阵的思想实现灰度与单位矩阵的转换,那么这个矩阵可以表示为:
?

其中s仍代表饱和度,s=1时矩阵等于单位矩阵。我们要把它换成与色相相关的变量,并且当hue=0或360时,s都等于1(色相360度一个轮回,所以360度与0度等价)。
?
可以让hue在360度和0度处都等于1,并且本身具有旋转特性的函数恐怕非余弦函数莫属了,不过使用Math.cos函数之前,我们需要将角度转换为弧度:
?
angle=hue*Math.PI/180
?
然后我们就可以把s全部替换为cos(angle):
?

?
又是一个超长的式子,不仅我们看着眼疼,而且对计算机也不太友好,所以我们把上式整理一下,将灰度矩阵和变换的部分分离出来:
?

?
然后根据矩阵加法的运算法则,我们可以把它拆分成两个独立矩阵相加的形式:
?

?
最后根据矩阵数乘法则,把cos(angle)从矩阵中提取出来:
?

?
经过这样的一番整理以后,整个矩阵的结构就清晰很多了。
?
很显然,如果直接用这样的矩阵进行色相变换,其结果一定会令人哭笑不得。当色相值=90度,即value=Math.PI/2时,cos(value)=0。也就是说,hue在0~90度范围内变化时,图像的饱和度将会随着色相值的增加而下降,最终变成一张黑白照片。
?
所以在
不断下降的同时,我们需要再附加一个矩阵,它不仅要像余弦函数那样具有旋转的特性,而且要求在[0, Math.PI/2]区间内递增,从而抵消余弦函数矩阵的递减变化——众望所归,正弦函数是最合适不过的了:
?

?
上式中,与正弦函数相乘的3*3矩阵包含了9个未知变量,需要把它们逐一求出来。
?
为了更直观地展示hue值对RGB三通道的影响机制,我把S和B都锁定为满值,并绘制出RGB和hue的关系曲线(图 4.49)。
?

图 4.43 RGB-hue关系曲线
?
可以看到,在S和B都等于100%时,RGB三个通道呈现出此消彼长的关系,它们三者不会同时达到满值。
?
关系曲线看起来比较像是锯齿状的正弦曲线,我们不妨让它们平滑一下,得到如图 4.50的结果,虽然有部分像素在y轴方向越界了,但没关系,因为最终结果都会限制在[0,255]的范围内,平滑处理只是为了方便我们观察其变化趋势。
?

图 4.44 平滑后的RGB-hue关系曲线
?
下面我们开始尝试借助图 4.44的曲线对正弦矩阵
内的元素进行推导。
?
rr:源像素的R通道与rr值相乘后附加到目标像素的R通道值,所以它反映的是R通道自身的变化,在0~90度的区间内,R通道值呈现出递减的趋势,但sin(angle)在该区间内单调上升。所以rr值是一个负数,与心理学系数相乘,得到结果-lumR。
?
gr:源像素的G通道与gr值相乘后附加到目标像素的R通道值,所以它反映的是G通道向R通道的转移,在0~90度区间内,R递减,G递增,即R通道正在向G通道转移,与sin(angle)的变化趋势恰好相反,所以gr值也是个负数,与心理学系数相乘得-lumG。
?
br:源像素的B通道与br值相乘后附加到目标像素的R通道值,所以它反映的是B通道向R通道的转移,在0~60度区间内,B和R同时递减,而到了60~90度这一区间,又出现R递减R递增的变化趋势,所以我们试着用255-的方式对蓝通道进行反相(图 4.45)。
?

图 4.45 对蓝通道进行反相
?
此时变化趋势整齐了好多,尽管此时红蓝通道在0~60度区间内的变化方向不一致,但由于数值均已向上越界,所以认为蓝通道在此处递减也无伤大雅。
?
蓝通道反相后,红蓝的曲线的变化趋势接近一致,所以br值应等于反相后的lumB值:1-lumB。
?
用类似的方法,我们可以算出该矩阵其它元素的值,得到的最终结果如下:
?

?
把灰度矩阵,余弦矩阵和正弦矩阵进行合并,得到的色相矩阵为:
?

?
用这样的矩阵测试色相60度时的色彩变化,效果如图 4.52所示。发现部分颜色变得明亮了。经统计发现,亮度变大的颜色主要集中在绿通道值较大的色彩中(白色除外),也就是说,矩阵中与绿色相关的元素,即第2列的元素rg,gg,bg需要做一下修正(从理论上也能说得通,因为绿通道的心理学系数较大,是1/3的两倍多)。
?

图 4.46 hue=60时的效果
?
下面我们尝试用更精确的方法计算rg,gg和bg的值。
?
为便于考察,我把RGB-hue曲线向下平移128像素,使正弦波的中轴线与hue轴重合(图 4.53)。
?

图 4.47 平滑后的RGB-hue关系曲线
?
这时候,因为hue=270度时,r的值等于0,且曲线位于上升的区间,所以270度处为正弦曲线的起点,于是r通道与色相的关系式就可以表示为r =sin(hue-270°)(忽略振幅系数128)。
?
同理得g=sin(hue-30°),b=sin(hue-150°)。
?
从r转移到g,其过程可以表示为r-g=sin(hue-270°)-sin(hue-30°)=-cos(hue)-sin(hue)cos(-30°)+cos(hue) sin(-30°)=1.5*cos(hue)-0.866*sin(hue)。
?
而在我们的矩阵中,红到绿的转移公式为
?
lumR + cos(hue)*(-lumR) + sin(hue)*rg=0.213-0.213cos(hue)+rgsin(hue)
?
要保证矩阵的红到绿转移公式与上面推导的式子具有相同的变化趋势,我们应该保证cos(hue)和sin(hue)的系数比相等,既1.5/(-0.866)=-0.213/rg,解得rg=0.123。
?
而gg则代表绿通道自身的