YCbCr
読み:ワイ-スィービー-スィーアー
外語:YCbCr

 カラー画像の色を表現する方式(色空間)の一つ。ITU-R BT.601(かつてのCCIR 601-1)という規格でも定義される。厳密には異なるがYUVとも呼ばれ、呼称が混在する傾向にある。
目次

概要

概念
 一般的には光の三原色である赤/緑/青の強さで表わすRGB方式が使われるが、YCbCr方式はRGBで表現された値を元に換算式で計算される数値で色を表わす。
 Yは輝度で、CrCbは、Cbが青系統、Crが赤系統のそれぞれの色の色相と彩度を表わす。

YUVとの違い
 YUV、YCbCr、YPbPrは、ほぼ同一視され、呼称も混在している。
 しかし厳密には、YUVはPAL信号用のコンポーネント信号をいい、そうでないものはYCbCr又はYPbPrと呼び分ける。
 NTSCではクロマ信号(色度信号)にIQ成分を使っていたが、PALでは代わりにUV成分を用いており、これが現在使われているCb,Cr(またはPb,Pr)成分に近いため、このように呼ばれるようになった。

YCbCr/YPbPr
 YCbCrとYPbPrの区別は明確ではないが、SD映像をYCbCr、HD映像をYPbPrで表わす傾向が強い。
 SD映像とHD映像ではカラーマトリクスが異なるため、このように呼び分けるようになったのではないかと見られるが、定かではない。

特徴

輝度
 Yは輝度信号と呼ばれ、人間の目が「明るさ」として感じる強さとほぼ比例した数値になる。
 このY信号のみを再生すれば、自然なモノクロ画像(グレイスケール)が得られる。

特性
 この方式の特徴は、「人間の目は明るさの変化には敏感だが、色の変化には鈍感である」という性質に基づいて、色度信号の情報量を減らすことができるという点にある。
 例えばJFIF(JPEG)ファイルでは、RGBからYCbCrに変換した後、Yはそのまま記録されるがCr/Cbは多くの場合縦横に1ピクセルずつ間引かれて記録される。しかしデコードされた画像を見ても色度信号が間引かれたことに起因する画像の劣化はほとんど目立たない。
 ビデオ信号処理でも、変換の式が若干異なるがCrCbと同様の仕組みの色表現が使われる。

RGBとの変換
 RGBとYCbCr/YPbPrの換算式は様々あり、用途によって使い分けられている。

ITU-R BT.601(SDTV向け)

RGB→YCbCr

YCbCr→RGB

ITU-R BT.709(HDTV向け)

RGB→YPbPr

YPbPr→RGB

輝度の変更

変更の手法
 画像処理において、輝度の変更(暗くする、明るくする)が必要になることは多い。
 BMPファイルなどでもそうだが、コンピューターが扱う色の情報はRGBだが、そのままでは輝度を変えることが難しいので、いったんYCbCr(またはYPbPr)に変換してYを変え、再びRGBに戻す処理とするのが一般的である。

輝度処理の例
 ある1画素に対して、引数kidoChange分だけ変更する処理の例を以下に示す。
 ここでは説明のために、マクロや他の関数等は一切使わず理論が分かるようにしてある。
 なお、次のような構造体があるものとする。
 typedef struct {
 unsigned char B;
 unsigned char R;
 unsigned char G;
 } RGB;
 あらかじめ、pixel構造体に1画素分のRGBを入れるものとする。
 RGB pixel;
 fread(&pixel, sizeof(RGB), 1, fp); /* BMPから1画素読む */
 実際の変換処理は、次のようになる。
 double Y, Cb, Cr;
 double R, G, B;
 R = pixel.R;
 G = pixel.G;
 B = pixel.B;
 
 /* Y/Cb/Crを求める */
 /* 飽和演算だが、ここでは敢えてマクロ等を使わず説明 */
 Y = 0.299*R + 0.587*G + 0.114*B;
 Cb = -0.169*R - 0.332*G + 0.5*B + 128.0;
 Cr = 0.5*R - 0.419*G - 0.081*B + 128.0;
 Y += kidoChange; /* kidoChangeは-255…0…+255の範囲内 */
 if (Y < 0.0) Y = 0.0;
 if (Y > 255.0) Y = 255.0;
 if (Cb < 0.0) Cb = 0.0;
 if (Cb > 255.0) Cb = 255.0;
 if (Cr < 0.0) Cr = 0.0;
 if (Cr > 255.0) Cr = 255.0;
 
 /* 計算されたY/Cb/Crから、新たなRGBを算出する */
 /* 飽和演算だが、ここでは敢えてマクロ等を使わず説明 */
 Cb -= 128.0;
 Cr -= 128.0;
 R = Y + (1.402 * Cr);
 if (R < 0.0) R = 0.0;
 if (R > 255.0) R = 255.0;
 G = Y - (0.344 * Cb) - (0.714 * Cr);
 if (G < 0.0) G = 0.0;
 if (G > 255.0) G = 255.0;
 B = Y + (1.772 * Cb);
 if (B < 0.0) B = 0.0;
 if (B > 255.0) B = 255.0;
 
 /* 足している 0.00001 は、整数変換時の誤差の解消用 */
 pixel.R = (unsigned char)(R + 0.00001);
 pixel.G = (unsigned char)(G + 0.00001);
 pixel.B = (unsigned char)(B + 0.00001);
 これを関数化するなどすると、RGBとYの変更分を与えるだけで目的のRGBを得る処理とすることができる。
 また、この例では計算をdouble型で普通に行なっているが、値を1000倍などにしてlong型で扱って高速化、など様々なアレンジは可能だろう。

再検索