计算机绘图一般用RGB颜色模型,也称RGB色系,但要表达渐变色则比较困难。本篇介绍HSV颜色模型,用HSV颜色模型可以方便地表示从某种颜色过渡到别一种颜色。
一、颜色模型
最为常用的颜色模型,分别是RGB颜色模型和HSV颜色模型,这两种模型之间是可以通过数学公式进行相互转换的。
RGB颜色模型(也叫红、绿、蓝三原光模型或者加色混色模型):将红、绿、蓝3种不同颜色,根据亮度配比的不同进行混合(3种颜色的定量配比),从而表现出不同的颜色。通过3种最基本颜色的混合叠加来表现出任意的一种颜色的方法,特别适用于显示器等主动发光的显示设备。
图1 RGB颜色模型的空间结构
图1展示了RGB颜色模型的空间结构,这是一个立方体结构,在该几何空间中,3个坐标轴分别代表了红(red)绿(green)蓝(blue)3种颜色。从理论上讲,任何一种颜色都包含在该立方体结构中。
我们平时用得最多的RGB颜色展示模式也就是24比特展示的。有种方法分别将红、绿、蓝3种颜色使用8比特无符号整数来表示,如#FFFFFF代表纯白色,#FF0000代表正红色-十六进制对24比特展示模式的一种表示方法。也可以使用(255,0,0)这样一个元组表示正红色。因为红色和绿色两种颜色叠加产生黄色,所以黄色为(255,255,0)。
HSV颜色模型:这是一种采用色调(H)、饱和度(S)、明度(V)3个参数来表示颜色的一种方式。
色调(Hue):以角度的形式进行度量,其取值角度范围是[0°,360°]。红色、绿色、蓝色3种颜色以逆时针方向进行排列。例如红色的位置为0°,绿色为120°,蓝色的位置为240°。
饱和度(Saturation):以百分比0~100%来表示,该数值越高,饱和度越高,光谱颜色的成分越多。饱和度反映了某种颜色纯度。饱和度为0则为黑白(灰度)。
明度(Value):以百分比0~100%来表示某种颜色的明度,明度值越高越明亮。明度表现了某种颜色的明亮程度,可以认为是一种由光线强弱产生的视觉体验。明度为0则为纯黑色,明度为100%、饱和度为0则为纯白色。
图2 HSV颜色模型的空间结构
图3 HSV颜色模型和RGB颜色模型关系
二、colorsys 模块
Python中的colorsys模块定义了RGB(红绿蓝)颜色与其他三坐标YIQ(亮度(Y)同相正交)、HLS(色相亮度饱和度)和HSV(色相饱和度值)之间的双向转换)。
colorsys 模块定义了如表1所示的方法(函数)。
表1 colorsys 模块定义的方法(函数)
方法(函数) | 描述 |
colorsys.rgb_to_yiq(r, g, b) | 将颜色从RGB坐标转换为YIQ坐标。 |
colorsys.yiq_to_rgb(y, i, q) | 将颜色从 YIQ 坐标转换为 RGB 坐标。 |
colorsys.rgb_to_hls(r, g, b) | 将颜色从RGB坐标转换为HLS坐标。 |
colorsys.hls_to_rgb(h, l, s) | 将颜色从HLS坐标转换为RGB坐标。 |
colorsys.rgb_to_hsv(r, g, b) | 将颜色从RGB坐标转换为HSV坐标。 |
colorsys.hsv_to_rgb(h, s, v) | 将颜色从HSV坐标转换为RGB坐标。 |
除colorsys.yiq_to_rgb()之外的所有上述方法(函数)的参数都是0到1之间的浮点值。在方法(函数)colorsys.yiq_to_rgb(y, i, q)中,参数y是0到1之间的浮点值,参数i和q为-1到1之间的浮点值。
对colorsys.hsv_to_rgb(h, s, v),可以固定s、v,s=1、v=1,h从0~1,颜色由红→黄→绿→青→蓝→洋红→红。
三、科赫(Koch)雪花
科赫雪花由3条科赫曲线组成,科赫曲线的构造过程主要分为三个步骤:(1)给定一个初始图形——一条线段;(2)将这条线段中间的 1/3长度用此长度的无底等边三角形替换(见图4(b));(3)按照第二步的方法不断的把各段线段中间的 1/3长度用此长度的无底等边三角形替换。这样无限地进行下去,最终即可构造出科赫曲线(如图4所示)。直线段称0阶科赫曲线,经一次替换称1阶科赫曲线,1阶科赫曲线每段直线段再经一次替换,则称为2阶科赫曲线,每多1阶替换,阶数加1,图4中(a)是直线(0阶)、(b)是1阶曲线、(c)是2阶曲线、(d)是3阶曲线、(e)是4阶曲线、(f)是5阶曲线。明显这是个递归过程。详见“Python海龟绘图——分形、递归与递归算法(上)”。
图4 科赫(Koch)曲线
四、用Python绘制科赫雪花
由图4(b)可知,设图4(a)直线长度为l,则左转0°(等于没有转向)向前画l/3长直线,左转60°向前画l/3长直线,右转120°(即左转-120°)向前画l/3长直线,左转60°用向前画l/3长直线。由图4(c)可知,设图4(b)直线长度为l,则可重复上述绘图规则绘图。这是个递归问题,每一段直线用4个向左转+向前画指定长度直线的动作完成,每一次用前一次长度的1/3画,直到0阶为止。
而三条相夹60°的科赫曲线可以组成科赫雪花。
Python用turtle绘制渐变色科赫雪花程序代码如下:
import turtle as t
import colorsys
t.speed(0) # 设置速度为最快
t.tracer(False) # 关闭绘图动画(不显示过程)
t.ht()
a = 400
N = 5 # 阶数
h=0 # 从红色开始,h=0~1
t.pu()
t.goto(-0.433 * a, -0.25 * a) # 使绘制的图形居中
t.pd()
def gw_fd(n, a): # 递归绘制科赫曲线
global h
h += 1 # h计数,除以总边数为0~1
pen_color = colorsys.hsv_to_rgb(h/4**(N+1), 1, 1) # 总边数为4^(N+1)
t.color(pen_color) # 设置渐变色,递归绘制科赫曲线
if n == 0:
t.forward(a)
else:
for angle in [0, 60, -120, 60]:
t.right(angle)
gw_fd(n-1, a/3)
for i in range(3): # 科赫雪花为相夹60°的3条科赫曲线
gw_fd(N, a) # 3条边数组成三角形
t.left(120)
t.update() # 绘图完成后更新缓存内容到显示器(防止显示不全)
t.done()
执行效果:
图5 渐变科赫雪花效果图