クイックノート

ちょっとした発見・アイデアから知識の発掘を

補色のスペクトル的な意味

補色とは、
色相環の反対側にある色」、
「混ぜると無彩色になる色」
などの特徴で説明されることが多いのですが、
その物理的な性質はどのようなものでしょうか。

ここでは、補色の物理的な意味を、
光のスペクトルとの関係から紐解いていきましょう。

色と光

私たちの眼は光の刺激を受け取ることで、
目の前の風景をイメージとして認識します。

光は波の性質を持っていて、
様々な波長の光がありますが、
私たちは、その波長の違いを色として認識しています。

例えば、りんごが赤色に見えるのは、
様々な波長の光が含まれた光源の光が、
りんごの表面で吸収されて、
吸収されずに残った赤い光が反射されて目に届くことで、
私たちが赤色を認識しているからです。

f:id:u874072e:20191217154434p:plain
色が見える仕組み

重要なのは、ここで赤は吸収されずに反射された色で、
それ以外はりんごが吸収しているということです。

絵の具を混ぜる(減法混色)

補色の代表的な性質として、
「混ぜると無彩色になる」というものがあります。
言い換えると、色が消える、モノクロになるということです。

色を混ぜる時には何が起こっているのでしょうか。
赤の絵の具は先ほどのリンゴと同じように、
赤色以外の光を吸収してしまう物質です。
また、緑の絵の具は、緑色以外の光を吸収してしまう物質です。
これらを混ぜると、赤の絵の具は赤以外の光を、
緑の絵の具は緑以外の光を吸収し、
吸収されずに残った光が目に見えることいなります。

f:id:u874072e:20191217161723p:plain
補色の混色

実は、赤と緑は補色の関係にあり、
ほぼ全ての波長が赤か緑の絵の具に吸収されて
目に見えるのは黒っぽい色になります。

このように、絵の具の色を混ぜるという操作は、
それぞれの絵の具が色を吸収しあって、
吸収されなかった色の光が目に届くようになることを表します。

絵の具を混ぜるほど、吸収される光の波長が増えていき、
反射される光が減るので、どんどん暗い色になります。
このように混ぜると色が引き算されていくので、
減法混色とも呼ばれます。

補色のスペクトル

それでは、
この補色はスペクトル的にはどういう色だと言えるでしょうか。

2つの色を混ぜた時に、色がなくなるには、
他の色が吸収しきれなかった光を、
別の色が吸収すれば良いことに気がつきます。

すると、混ぜて無彩色になる色、つまり補色は、
反射される色と吸収される色を丁度反対にした色と言えます。

下の図では、それぞれの色について、
波長に分解した時の波長の強さをグラフで表現したイメージ図です。

f:id:u874072e:20191217155704p:plain:w400
補色のスペクトルのイメージ

赤の補色である緑は、
赤で反射される波長の光が吸収されるので、
丁度、グラフを上下逆さまにしたようになります。
これが補色のスペクトルです。

ここで、次のような疑問を持たれるかもしれません。
「緑色は、緑色の波長にピークがくる山のようなグラフで表せるのに、
 上の図では赤色以外の青や紫など、
 緑とは違う色も沢山含んだ色になっている。
 これって本当に緑色なの?」

実は人間の目には、違うスペクトルでも同じ色に見えるという
条件等色と呼ばれる現象が生じます。
このため、緑にピークのあるスペクトルも、
上の図のようなスペクトルも緑なのです。
特に、空の青には紫色の光も多く含まれていますが、
この条件等色によって青色に見えています。

clean-copy-of-onenote.hatenablog.com

補色の生成

補色はスペクトルを上下反転したものであると説明しました。
そこで、実際にスペクトルを反転して補色を作ってみましょう。

コードはRで記述しています。

波長と色の対応

補色を作るためには、
波長と色がどのように対応しているかを与える必要があります。

ここでは、波長に応じた色を求める関数lambda2colorをお借りしました。

スペクトルの分解粒度

スペクトルで分解する波長の数と、
波長の代表点を定めておきます。

ここでは、380nmから770nmまでの波長を
100分割して、スペクトルを作成します。

Ncol=100
lambdas = seq(from=380,to=770,length.out=Ncol)

単色スペクトルの生成

赤や青といった一つ一つの色の光を表現するためのスペクトルを、
以下の関数で生成します。

norm_col_weight = function(lambda){
  x = dnorm(lambdas,mean=lambda,sd = 60)
  return(x / max(x))
}

ただし、光の強度は複数の波長にまたがっているものとして、
中心の波長をピークとした正規分布でスペクトルを生成しています。

例えば、700nmをピークとした赤色に対しては、
下のようなスペクトルが生成されます。

f:id:u874072e:20191219115449p:plain:w300
赤のスペクトル

スペクトルの反転

補色はスペクトルを反転することで計算します。
下の関数は、波長毎の強度の強弱を反転する関数です。

compl_color = function(weights){
  mix_colors(lambda2color(lambdas),1 - weights)
}

混色(加法混色)

スペクトルの反転で、
補色をスペクトルに分解した時の、
各波長(色)の強度が計算されます。
あとは、それぞれの強度に従って色を混ぜる必要があります。

光の混色は、絵の具の混色とは違い、
混ぜれば混ぜるほど明るくなる加法混色と呼ばれます。

下の関数は、16進数で表現された色を、
weightsで指定した割合で加法混色する関数です。
normは重みの和を1になるようにリスケールするか否かを表します。

mix_colors = function(cols,weights,norm=T){
  to_rgb = function(x){
    x = substr(x,2,9)
    x = as.numeric(paste("0x",x,sep=""))
    
    r1 = as.numeric(paste("0x010000"))
    r = x %/% r1
    x = x %% r1
    
    g1 = as.numeric(paste("0x000100"))
    g = x %/% g1
    x = x %% g1
    
    b = x
    
    return(c(r=r,g=g,b=b))
  }
  
 if(norm){weights = weights / sum(weights)}
  
  rgb_cols = sapply(cols,to_rgb)
  mix_rgb = round(rgb_cols %*% cbind(weights))
  mix_rgb = sapply(mix_rgb,function(x){min(255,x)})
  print(mix_rgb)
  paste0("#", to_hex(mix_rgb[1]), to_hex(mix_rgb[2]), to_hex(mix_rgb[3]))
}

補色の計算例

上の関数を使って、補色を計算してみます。

weight1 = norm_col_weight(700)
col1 = mix_colors(lambda2color(lambdas),weight1)
col2 = compl_color(weight1)

plot(NULL, xlim=c(0,2), ylim=c(1,2),
     axes=FALSE, xlab="", ylab="")
rect(0:1, 1.1, 1:2, 2,
     col=c(col1,col2))

まず、norm_col_weight(700)'で700nmを中心とした、 単色のスペクトルを生成し、 スペクトルに沿って色を混ぜ合わせてcol1`を生成しています。

次に、compl_colorcol1と補色の関係にあるcol2を生成しています。

最後にそれぞれの色をプロットしています。

下の図は、もとの色の波長を変えながら補色を計算した結果です。

f:id:u874072e:20191219113345p:plain:w300
計算された補色

  • 赤-青緑
  • 黄緑-紫
  • 青-黄土色
  • 黄色-青紫

のように、補色が生成されていることがわかります。

まとめ

ここでは、色の補色について、
そのスペクトル的な意味を説明しました。

また、実際にプログラムで補色を生成してみました。

実は補色にも種類があり、
ここで紹介したのはRYB補色と呼ばれるものです。
この補色では、赤と緑が補色関係になります。
美術の教科書などではこの補色を学ぶことが多いように思います。

一方で、赤とシアン(水色)が補色関係になる
RGB補色と呼ばれるものもあり、
こちらの補色は、PCの色の表現的に簡単に計算できるので、
具体的な計算方法を紹介しているサイトは数多く見つかります。

プライバシーポリシー