色空間

Color Spaces

色空間とは

色空間(Color Space)は、色を数値で表現するための座標系である。目的に応じて様々な色空間が使い分けられる。

RGB 加法混色 ディスプレイ表示 HSV/HSL 直感的に扱いやすい 色相・彩度・明度 YUV/YCbCr 輝度と色差 動画圧縮・放送 Y U V Lab (CIELAB) 知覚均等 色差計算に向く L: 明度, a: 緑-赤, b: 青-黄 グレースケール 明るさの 1 チャネル エッジ検出等
図1. 主要な色空間の特徴と用途

RGB色空間

RGB色空間は、赤(Red)、緑(Green)、青(Blue)の3原色の加法混色で色を表現する。具体的な色空間として扱うには、原色・白色点・ガンマを定めた sRGB などの規格を指定する(同じ RGB の値でも、規格が違えば別の色を表す)。

RGB立方体

RGB色空間の立方体モデル(回転アニメーション)

加法混色

R G B

R, G, B ∈ [0, 255] (8bit)  総色数: 256³ ≈ 1677万色

図2. RGB色空間の立方体モデル(回転)と加法混色

光の三原色と色の三原色

色の混合には2つの方式がある。

特性 加法混色(光の三原色) 減法混色(色の三原色)
原色 R(赤)、G(緑)、B(青) C(シアン)、M(マゼンタ)、Y(イエロー)
混ぜると 明るくなる(全部混ぜると白) 暗くなる(全部混ぜると理論上黒)
原理 光を足す(発光) 光を吸収する(反射光から引く)
用途 ディスプレイ、照明、カメラ 印刷(CMYK)、絵の具
関係 C = G+B(赤を引く)、M = R+B(緑を引く)、Y = R+G(青を引く)
0〜1 に正規化した値では C = 1−R, M = 1−G, Y = 1−B
加法と減法の原色は補色の関係にある

印刷では CMY だけでは完全な黒が出ないため、黒インク(K: Key)を追加した CMYK が使われる。 コンピュータビジョンでは主に加法混色の RGB を扱う。

注意: OpenCV の cv2.imread は画像をBGRの順で返す。RGB の順を前提にする処理(matplotlib での表示など)に渡す前に COLOR_BGR2RGB で変換する。

HSV/HSL色空間

HSV(Hue, Saturation, Value)は色を色相・彩度・明度に分けて表すので直感的に扱いやすく、色の選択や単純なしきい値による抽出に適している。ただし知覚均等な色空間ではない(純粋な青も白も $V = 1$)。見出しの HSL は、明度 $V$ の代わりに最大値と最小値の平均 $L = (M + m)/2$($M, m$ は R, G, B の最大値・最小値。下の明度法と同じ量)を使う変種で、彩度の定義も変わる。

HSVの各成分

  • H(Hue)色相: 色の種類。0° 以上 360° 未満の角度で表現(赤=0°, 緑=120°, 青=240°。無彩色では定まらない)
  • S(Saturation)彩度: 色の鮮やかさ。0〜1(0=灰色、1=純色)
  • V(Value)明度: 明るさ。0〜1(0=黒、1=最大輝度)
HSV色空間の円錐モデル
図3. HSV円錐モデル — 上面(V=1): 色相環(H=角度, S=半径方向)、頂点(V=0): 黒。V が小さくなるほど取りうる色域が狭まる。

RGB → HSV 変換(以下では R, G, B を 0〜1 に正規化する。8 ビットなら 255 で割る)

$$M = \max(R, G, B), \quad m = \min(R, G, B), \quad C = M - m$$ $$V = M, \quad S = \begin{cases} C/M & (M \neq 0) \\ 0 & (M = 0) \end{cases}$$ $$H = 60° \times \begin{cases} (G-B)/C \bmod 6 & \text{if } M=R \\ (B-R)/C + 2 & \text{if } M=G \\ (R-G)/C + 4 & \text{if } M=B \end{cases}$$

$C = 0$(無彩色)では $H$ は定まらない(実装では 0 とすることが多い)。

用途: 色によるオブジェクト検出、肌色検出、背景除去など。 例えば単純な赤色検出では、H を 0°〜10° または 350°〜360° の範囲に限り、S と V にも下限を設ける(範囲は照明やカメラに合わせて調整する)。

OpenCV固有の注意: OpenCVでは Hue の範囲は 0〜179(360°を半分にして8ビットに収める)、Saturation と Value は 0〜255 である。 数式の値から変換する際は H を半分にし(上の 0°〜10° は 0〜5、350°〜360° は 175〜179)、S と V は 0〜1 の値を 255 倍する。

YUV / YCbCr 色空間

明るさに対応する信号 Y(厳密には輝度ではなくルマ)と色差を分離した色空間である。人間の視覚が輝度に敏感で色差に鈍感であることを利用して、色差を間引くことでデータ量を削減できる。

YUV と YCbCr の違い

特性 YUV YCbCr
由来 アナログテレビ(PAL。NTSC は同系統の YIQ) デジタル映像規格
値の範囲 連続値(アナログ信号) 整数に量子化(8 ビットではフルレンジ 0〜255 や、映像規格のスタジオレンジ 16〜235 / 16〜240。10 ビット以上もある)
用途 アナログ放送、ビデオ信号 JPEG, H.264, MPEG, HDMI
変換係数 規格により異なる(BT.601: SD, BT.709: HD, BT.2020: 4K/8K)

多くの文献やライブラリで YUV と YCbCr は混同されているが、 OpenCV では COLOR_BGR2YUV と COLOR_BGR2YCrCb は異なる変換を行う。 現代のコンピュータビジョンでは主に YCbCr(デジタル版)を扱う。

RGB → YCbCr 変換(BT.601 の係数・0〜255 のフルレンジ。JPEG/JFIF と同じ)

$$\begin{pmatrix} Y \\ C_b \\ C_r \end{pmatrix} = \begin{pmatrix} 0.299 & 0.587 & 0.114 \\ -0.169 & -0.331 & 0.500 \\ 0.500 & -0.419 & -0.081 \end{pmatrix} \begin{pmatrix} R \\ G \\ B \end{pmatrix} + \begin{pmatrix} 0 \\ 128 \\ 128 \end{pmatrix}$$
Y(輝度) 人間の目に重要 Cb(青色差) B − Y に比例 Cr(赤色差) R − Y に比例 • 輝度(Y)と色差(Cb, Cr)を分離 → 色差をダウンサンプリングして圧縮 • 4:2:0サブサンプリング: 色差を1/4に削減(JPEG, H.264等) • 人間の視覚は輝度に敏感、色差に鈍感という特性を利用
図4. YUV/YCbCr色空間の輝度と色差成分

YCbCrの値域: ビデオ規格では通常、Y は 16〜235、Cb/Cr は 16〜240 の「スタジオスイング」範囲を使用する。 ただし、OpenCV の cvtColor は上の行列と同じフルレンジ(0〜255)で変換する。また COLOR_BGR2YCrCb はチャネルを $Y, C_r, C_b$ の順に返す(名前のとおり。上の行列とは $C_b$ と $C_r$ の順が逆)。

Lab色空間(CIELAB)

Lab は、色の差が知覚の差におおむね比例するよう設計された(近似的に知覚均等な)色空間である。ユークリッド距離が知覚的な色差とおおむね対応するため、色差評価やカラーマネジメントに広く使われる。ただし完全に均等ではなく、色の領域によってずれる。

Lab の各成分

  • L: 明度(0=黒、100=白)
  • a: 緑(−)〜 赤(+)軸
  • b: 青(−)〜 黄(+)軸

RGB → Lab 変換の流れ

RGB → XYZ(デバイス非依存の中間色空間)→ Lab。sRGB の値は、先にガンマ補正を外して線形の値に戻してから XYZ に変換する。白色点には通常 D65 を使う。

XYZ から Lab への変換には非線形関数を用いる:

$$L^* = 116\,f\!\left(\frac{Y}{Y_n}\right) - 16, \quad a^* = 500\left[f\!\left(\frac{X}{X_n}\right) - f\!\left(\frac{Y}{Y_n}\right)\right], \quad b^* = 200\left[f\!\left(\frac{Y}{Y_n}\right) - f\!\left(\frac{Z}{Z_n}\right)\right]$$

ここで $f(t) = t^{1/3}$($t > \delta^3$ のとき)、$f(t) = \dfrac{t}{3\delta^2} + \dfrac{4}{29}$($t \le \delta^3$ のとき)、$\delta = 6/29$。2 つの枝は $t = \delta^3$ で値と傾きがつながる。$X_n, Y_n, Z_n$ は白色点の三刺激値。

用途: 色差計算($\Delta E$)、カラーキャリブレーション、画像セグメンテーション。 $\Delta E = \sqrt{(\Delta L^*)^2 + (\Delta a^*)^2 + (\Delta b^*)^2}$ が知覚的な色の違いの簡便な指標となる(CIE76 の色差)。より知覚に合う指標として CIE94 や CIEDE2000($\Delta E_{00}$)も使われる。

グレースケール変換

カラー画像をグレースケール(明るさに相当する 1 チャネル)に変換する方法はいくつかある。値の意味は方法によって違うので、輝度法の結果を $Y$、ほかの方法の結果を $I$ と書く:

輝度法(Luminosity Method) - 最も一般的

$$Y = 0.299R + 0.587G + 0.114B$$

人間の目の感度(緑に最も敏感で青に鈍感)に基づく BT.601 の重み。ガンマ補正のかかった値にそのまま当てる式で、厳密には物理的な輝度ではなく「ルマ」と呼ばれる量である。HD・sRGB の BT.709 では線形の値に 0.2126, 0.7152, 0.0722 を使う。OpenCV の COLOR_BGR2GRAY はこの BT.601 の重みを使う。

平均法(Average Method)

$$I = \frac{R + G + B}{3}$$

明度法(Lightness Method)

$$I = \frac{\max(R,G,B) + \min(R,G,B)}{2}$$

コード例(Python)

import cv2
import numpy as np

# 画像読み込み(BGR)
img_bgr = cv2.imread('image.jpg')

# 色空間変換
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
img_ycrcb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YCrCb)  # チャネル順は Y, Cr, Cb
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)  # 8 ビットでは L*×255/100、a*・b* は +128 して格納

# HSVで特定の色を抽出(例:赤色。OpenCV の H は 0〜179 なので 0°〜10° → 0〜5、350°〜360° → 175〜179)
mask1 = cv2.inRange(img_hsv, np.array([0, 100, 100]), np.array([5, 255, 255]))
mask2 = cv2.inRange(img_hsv, np.array([175, 100, 100]), np.array([179, 255, 255]))
mask = cv2.bitwise_or(mask1, mask2)
result = cv2.bitwise_and(img_bgr, img_bgr, mask=mask)

# グレースケール手動計算(輝度法・BT.601 の重み。四捨五入して cv2 と揃える)
b, g, r = cv2.split(img_bgr)
gray_manual = np.round(0.299 * r + 0.587 * g + 0.114 * b).astype(np.uint8)

よくある質問

Q1. RGB色空間とHSV色空間の違いは?

RGB は赤・緑・青の光の三原色を足し合わせる加法混色で色を表し、ディスプレイ表示に使われる。HSV は色を色相(H)・彩度(S)・明度(V)に分けて表すので直感的に扱いやすく、色抽出やオブジェクト検出の単純なしきい値処理に向く。ただし HSV は知覚均等な色空間ではない。

Q2. YUVとYCbCrの違いは?

YUV は本来アナログテレビ(PAL)の色差信号を指し(NTSC は同系統の YIQ)、YCbCr は JPEG や H.264 などのデジタル映像・画像で使われる、整数に量子化した色差表現である。ライブラリでは YUV の語が YCbCr を含めて曖昧に使われることがあるが、OpenCV の COLOR_BGR2YUV と COLOR_BGR2YCrCb は別の変換である。現代のコンピュータビジョンでは主に YCbCr を扱う。

Q3. グレースケール変換で最も一般的な方法は?

輝度法 $Y = 0.299R + 0.587G + 0.114B$ が最も一般的である。人間の目が緑に最も敏感で青に鈍感であることを反映した BT.601 の重みで、OpenCV の COLOR_BGR2GRAY もこれを使う。ガンマ補正のかかった値に当てる式なので、厳密には物理的な輝度ではなくルマである。

まとめ

  • RGB: ディスプレイ表示の標準、加法混色
  • HSV/HSL: 色相・彩度・明度に分けて直感的に扱える、色抽出に適する
  • YUV/YCbCr: 輝度と色差の分離、動画圧縮に使用
  • Lab: 近似的に知覚均等、色差計算やカラーマネジメントに向く
  • グレースケール: 明るさに相当する 1 チャネル(値の意味は変換方法による)、多くの画像処理の前処理として使用