🌈

HSV -> RGB 変換式を高校数学でガチ導出する

2022/10/25に公開

前提知識

RGB -> HSV 変換式

RGB -> HSV 変換式をベースに、その逆変換を考えていくのがこの記事です。

https://zenn.dev/tetracalibers/articles/78474ee3e8678e

上記の記事と同様に、次の定義を用いる。

const Imax = Math.max(r, g, b)
const Imin = Math.min(r, g, b)

床関数の性質

\lfloor x\rfloorは、xを超えない最大の整数なので、x - 1xの間の数になります。

x - 1 < \lfloor x \rfloor \leq x

各辺に1を加えると、

x < \lfloor x \rfloor + 1 \leq x + 1

\lfloor x \rfloor \leq xと組み合わせて、

\lfloor x \rfloor \leq x < \lfloor x \rfloor + 1 \leq x + 1

この式から、次の性質を抜き出せます。

\lfloor x\rfloor \leq x<\lfloor x\rfloor +1

事前準備 - 色相を60で割った値の重要性

前記事を見ていただけるとわかるのだが、色相Hの計算式は、いずれも次のような形になっている。

H = 60y + 60X

X前記事でいう区間内回転率であり、yには0~6の整数が入る。

ゆえに、本記事での計算の過程では、60を括り出す、

H = 60 \cdot (y + X)

のような変形を毎度行うことになり、その流れで\cfrac{H}{60}という形がよく現れることになるので、\cfrac{H}{60}を変数化しておくと式が綺麗にまとまるのだ。

ところで、色相Hは0~360の間の整数ならなんでもありなので、\cfrac{H}{60}は整数になるとは限らない。
\cfrac{H}{60}が整数になるのは、Hが、前記事で規則性が発見された60°ずつの区間の開始角である時のみだ。
つまり、

  • \cfrac{H}{60}の整数部分は、何番目の区間であるかを表す
  • \cfrac{H}{60}の小数部分は、その区間の開始地点からの誤差(その区間内で何%進んでいるか)を表す

ことになる。

これらの重要な値を、まずは変数としてまとめておきたい。

\cfrac{H}{60}の整数部分は、色相の区間を指すindex、みたいな意味合いでH_iとしておく。

H_i = \left\lfloor \cfrac{H}{60} \right\rfloor

\cfrac{H}{60}の小数部分は、小数だからfloatのFにでもしておこうか。

F = \cfrac{H}{60} - H_i

整数部分と小数部分を加えれば元の数値になるので、\cfrac{H}{60} = H_i + Fが成り立つ。

H_i = 0のとき

このとき、色相Hは0°~60°

H_iは何番目の区間かを表す数ということで、H_i = 0は一番最初の区間を表すのだから、Hが0°~60°の範囲であることは至極当然のことである。

と言ってももやもやする人もいるかもしれないので、数学的な証明を書いておく。

H_i = \left\lfloor \cfrac{H}{60} \right\rfloor = 0

床関数の性質より、

0 \leq \cfrac{H}{60} < 0 +1
0 \leq \cfrac{H}{60} < 1
0 \leq H < 60

RGB値の関係性

詳しくは前記事の解説を参照してほしいのだが、以下のような関係にある。

  • R = Imax
  • G = Imin -> Imax
  • B = Imin

明度VからRを求める

明度の定義V = \cfrac{I_{max}}{255}より、

R = I_{max} = 255 \times V

彩度SからBを求める

彩度の定義S = \cfrac{I_{max} - I_{min}}{I_{max}}より、

\begin{align*} S &= \cfrac{255V - I_{min}}{255V} \\\\ &= \cfrac{255V}{255V} - \cfrac{I_{min}}{255V} \\\\ &= 1 - \cfrac{I_{min}}{255V} \\\\ S + \cfrac{I_{min}}{255V} &= 1 \\\\ \cfrac{I_{min}}{255V} &= 1 - S \\\\ I_{min} &= 255V \times (1 - S) \end{align*}

BがIminであるから、

B = I_{min} = 255 \times V \cdot (1 - S)

色相HからGを求める

H = 60 \times \cfrac{G - B}{I_{max} - I_{min}}より、

\begin{align*} H &= 60 \times \cfrac{G - 255V \cdot (1 - S)}{255V - 255V \cdot (1 - S)} \\\\ &= 60 \times \cfrac{255V \cdot \left(\cfrac{G}{255V} - (1 - S)\right)}{255V \cdot (1 - (1 - S))} \\\\ &= 60 \times \cfrac{\cfrac{G}{255V} - (1 - S)}{S} \\\\ \cfrac{H}{60} &= \cfrac{\cfrac{G}{255V} - (1 - S)}{S} \\\\ \cfrac{H}{60} \cdot S &= \cfrac{G}{255V} - (1 - S) \\\\ \cfrac{G}{255V} &= \cfrac{H}{60} \cdot S + (1 - S) \\\\ G &= 255V \cdot \left(\cfrac{H}{60} \cdot S + (1 - S)\right) \\\\ &= 255V \cdot \left(1 + \cfrac{H}{60} \cdot S - S \right) \\\\ &= 255 \times V \cdot \left(1 - S \cdot \left(1 - \cfrac{H}{60} \right)\right) \end{align*}

ところで、今はH_i = 0なので、

\begin{align*} \cfrac{H}{60} &= H_i + F \\\\ &= F \end{align*}

というわけで、代入すると、

G = 255 \times V \cdot \left(1 - S \cdot \left(1 - F \right)\right)

つまり、Hが0°~60°の時のRGB値は、

\begin{cases} R &= 255 \times V \\ G &= 255 \times V \cdot \left(1 - S \cdot \left(1 - F \right)\right) \\ B &= 255 \times V \cdot (1 - S) \end{cases}

Unfinished Tasks

近々続き書くよ。KaTeX疲れたにゃん

参考にしたサイト

床関数、整数部分・小数部分

https://www.clearnotebooks.com/ja/notebooks/1196929

https://ja.wikipedia.org/wiki/床関数と天井関数

色の変換原理

https://www.rapidtables.org/ja/convert/color/hsv-to-rgb.html

https://hooktail.org/computer/index.php?RGB����HSV�ؤ��Ѵ�������

Discussion