このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
イメージ内の色数の削減
24 ビット カラー表示のシステムで、トゥルーカラー イメージは最大 16,777,216 色 (すなわち 224) まで表示可能です。しかし、より低いスクリーン ビット深度をもつシステム上で、トゥルーカラー イメージは、非常にうまく表示できます。これは、必要に応じて、MATLAB® が自動的に色近似とディザリングを行うからです。色近似は、正確に一致する色が見つからない場合に、ソフトウェアが代わりの色を選択する処理です。
しかし、インデックス付きイメージは、多くの色数をもっている場合に問題が起こる可能性があります。一般に、次の理由で、インデックス付きイメージを 256 色までに制限すべきです。
8 ビット表示をもつシステムで、256 色を超えるカラーのインデックス付きイメージは、ディザリングまたはマッピングしなければなりません。そのため、うまく表示できません。
一部のプラットフォームでは、カラーマップに 256 個を超えるエントリを登録できません。
インデックス付きイメージが 256 色を超える場合、MATLAB は
uint8
配列にイメージ データを保存することはできません。一般的には、代わりにデータ型double
の配列を使用し、イメージのストレージ サイズをより大きくします (各ピクセルは 64 ビットを使用します)。多くのイメージ ファイル形式は、インデックス付きイメージを 256 色に制限しています。256 色を超える色数を使用するインデックス付きイメージを (
imwrite
を使用して) 256 色までしかサポートしない形式に書き込むと、エラーが発生します。
このトピックでは、イメージの色数を削減する方法について説明します。
色近似を使用したトゥルーカラー イメージの色数の削減
イメージの色数を削減するには、関数 rgb2ind
を使用します。この関数は、トゥルーカラー イメージをインデックス付きイメージに変換し、この処理で色数を削減します。rgb2ind
では、元のイメージでの色を近似するために次の方法が提供されます。
量子化 (量子化を参照)
一様量子化
最小分散量子化
カラーマップ マッピング (カラーマップ マッピングを参照)
結果のイメージの画質は、使用する近似法、入力イメージの色の範囲、およびディザリングの使用の有無に依存します。どの方法がより有効に機能するかはイメージによって異なります。ディザリングとそれを有効または無効にする方法の詳細については、ディザリングを使用した色数の削減を参照してください。
量子化
イメージ内の色数を削減するには、"量子化" を行います。関数 rgb2ind
は、色数低減アルゴリズムの一部として量子化を使用します。rgb2ind
は、一様量子化と最小分散量子化の 2 つの量子化法をサポートします。
イメージの量子化の説明で重要な用語は、"RGB カラー キューブ" です。RGB カラー キューブは、特別なデータ型に対して、定義されるカラー全体を表す 3 次元配列です。MATLAB の中で RGB イメージは、uint8
、uint16
、double
のいずれかのタイプで、これらに対して 3 種類の異なるタイプのカラー キューブの定義があります。たとえば、RGB イメージのデータ型が uint8
の場合、256 個の値は各色平面 (赤、緑、青) に対して定義され、全体として 224 (16,777,216) 色がカラー キューブで定義されます。このカラーチューブは、実際に使用する色にかかわらず、uint8
RGB イメージ全体に対して、同じものになります。
uint8
、uint16
、double
の 3 つのカラー キューブは、同じ色範囲をもっています。言い換えれば、uint8
RGB イメージの中の明るい赤は、double
RGB イメージの中の明るい赤と同じように表示されます。違いは、double
RGB カラー キューブは、より多くの赤の階調 (すべての色で多くの階調) をもっていることです。次の図は、uint8
イメージ用のRGB カラー キューブを示しています。
uint8 イメージ用の RGB カラー キューブ
量子化は、RGB カラー キューブをより小さな数のボックスに分け、その後、すべてのカラーを、対応するボックスの中心のカラー値にマッピングする処理です。
一様量子化と最小分散量子化は、RGB カラー キューブを分けるために使用する手法に違いがあります。一様量子化では、カラー キューブは、同じサイズのボックス(より小さいキューブ)に切り取られます。最小分散量子化では、種々の異なるサイズのボックス(必ずしも、キューブではない)に切り取られます。ボックスのサイズは、イメージの中に分布する色数に依存します。
一様量子化. 一様量子化を実行するには、関数 rgb2ind
を呼び出し、許容誤差を指定します。許容誤差は、RGB カラー キューブを分配する立方体のサイズを決定します。許容誤差の設定値は、[0,1] の範囲の値です。たとえば、許容誤差を 0.1
とすると、ボックスのエッジは、RGB カラー キューブの長さの 1/10 になり、ボックスの最大数は、次のようになります。
n = (floor(1/tol)+1)^3
次のコマンドは、許容誤差 0.1 を設定した一様量子化を行います。
RGB = imread('peppers.png');
[x,map] = rgb2ind(RGB, 0.1);
次の図は、uint8
イメージの一様量子化を示します。この図は、わかりやすくするためにカラー キューブの 2 次元スライス (または、色平面) を示しており、red=0、green と blue が 0 から 255 までの範囲に相当します。実際のピクセル値は x マーカーの中心で示されています。
RGBカラー キューブのスライス上での一様量子化
カラー キューブを分割した後、すべての空のボックスを切り捨てます。そのため、いずれか 1 つのボックスのみを使用して、カラーマップ用の色が 1 つ作成されます。前に示したように、一様量子化で作成されるカラーマップの最大長は予測できますが、rgb2ind
が入力イメージの中に現れない色を除去するので、カラーマップは予測したものより短くなります。
最小分散量子化. 最小分散量子化を実行するには、rgb2ind
を呼び出し、出力イメージのカラーマップの中にある色の最大数を指定します。指定した値によって、RGB カラー キューブが分割されるボックスの数が決定します。次のコマンドは、185 カラーをもつインデックス付きイメージを最小分散量子化を使用して作成します。
RGB = imread('peppers.png');
[X,map] = rgb2ind(RGB,185);
最小分散量子化は、ピクセル値間の分散に基づいてピクセルをグループに関連付けることによって行われます。たとえば、青のピクセルの集合は、グループの中心ピクセルからわずかしかズレていないので、すべて同じグループになります。
最小分散量子化で、カラー キューブを分配するボックスのサイズは異なり、カラー キューブを必ずしも満たすものではありません。カラー キューブのある部分で、ピクセルが存在しない場合、これらの部分にはボックスは存在しません。
rgb2ind
を使用するときに、ボックス数 n
を設定すると、配置はイメージのカラー データを解析するときのアルゴリズムにより決定されます。イメージが、最適に配置された n
個のボックスに分割されると、各ボックスの中のピクセルは、一様量子化と同様にボックスの中心のピクセル値にマッピングされます。
結果として得られるカラーマップには、通常、ユーザーが指定した数のエントリが含まれています。これは、各領域は、入力イメージの中で少なくとも 1 つの色を含むようにカラー キューブが分割されるためです。入力イメージで使用される色が指定した数より少ない場合、出力カラーマップの色数は n
より少なくなり、出力イメージには入力イメージの色がすべて含まれます。
次の図は、前の図 (一様量子化) で使用されているカラー キューブと同じ 2 次元スライスを示しています。11 個のボックスが、最小分散量子化を使用して作成されます。
RGB カラー キューブのスライス上での最小分散量子化
色数を与えると、最小分散量子化は、実際のデータを考慮するので一様量子化よりも良い結果を出力します。最小分散量子化では、入力イメージで頻繁に現れる色に対してより多くのカラーマップ エントリが割り当てられます。あまり頻繁に現れないものは、カラーマップ要素の割り当てが少なくなります。結果として、色の精度は一様量子化よりも高くなります。たとえば、入力イメージにおいて、緑の階調が多く、赤の階調が少ない場合、出力のカラーマップでは赤よりも緑が多くなります。最小分散量子化に必要な計算時間は一様量子化の場合よりも増えます。
カラーマップ マッピング
使用する実際のカラーマップを指定する場合、rgb2ind
は、(量子化の代わりに) "カラーマップ マッピング" を使用して、指定したカラーマップの中で RGB イメージ内の色と最も一致する色を探します。この方法は、固定したカラーマップを使用してイメージを作成する場合に役立ちます。たとえば、8 ビット表示上で複数のインデックス付きイメージを表示する場合、同じカラーマップにこれらすべてをマッピングすることにより、色に関する問題を避けることができます。カラーマップ マッピングでは、指定したカラーマップに RGB イメージ内の色と類似する色が含まれている場合、良好な近似結果が得られます。カラーマップに RGB イメージ内の色と類似する色が含まれていない場合、この方法を使用しても良好な結果は得られません。
この例は、2 つのイメージを同じカラーマップにマッピングしたものを示しています。2 つのイメージに対して使用されるカラーマップは、指定した色数を含む RGB カラーマップを作成する MATLAB 関数 colorcube
を使用して、実行中に作成されます (colorcube
は、与えられた色数に対して常に同じカラーマップを作成します)。このカラーマップは RGB カラー キューブに含まれるすべての色を含んでいるため、出力イメージは入力イメージにかなり近くなります。
RGB1 = imread('autumn.tif'); RGB2 = imread('peppers.png'); X1 = rgb2ind(RGB1,colorcube(128)); X2 = rgb2ind(RGB2,colorcube(128));
メモ:
関数 imshow
は、複数のインデックス付きイメージを表現するために有効なものです。詳細については、同じ Figure ウィンドウ内に個別にイメージを表示または関数 imshow
のリファレンス ページを参照してください。
imapprox を使用したインデックス付きイメージの色数の削減
インデックス付きイメージで色数を削減しなければならない場合は、imapprox
を使用します。imapprox
は rgb2ind
に基づいて処理され、同じ近似法を使用します。本質的に、imapprox
は、最初に ind2rgb
を呼び出して、イメージを RGB 形式に変換し、次に rgb2ind
を呼び出して、色数を減らした新しいインデックス付きイメージを戻します。
たとえば、元のイメージは 128 色ですが、次のコマンドを使用して、64 色の trees
イメージを作成します。
load trees
[Y,newcmap] = imapprox(X,map,64);
imshow(Y,newcmap)
結果のイメージの画質は、使用する近似法、入力イメージの色の範囲、およびディザリングの使用の有無に依存します。どの方法がより有効に機能するかはイメージによって異なります。ディザリングとそれを有効または無効にする方法の詳細については、ディザリングを使用した色数の削減を参照してください。
ディザリングを使用した色数の削減
イメージの色数を減らすために rgb2ind
または imapprox
を使うと、一部の色が失われるために、最終的なイメージは元のイメージより劣化して見える可能性があります。rgb2ind
と imapprox
はどちらも "ディザリング" を行って出力イメージの見かけの色の数を増やします。"ディザリング" は、ある近傍の中でピクセルの色数を変化させ、各ピクセルの周りの平均色が元の RGB カラーを近似するものです。
ディザリングがどのように機能するかの例として、カラーマップに厳密な意味で一致しない、暗いオレンジのピクセルを含むイメージを考えます。オレンジのこの階調を作成するために、ディザリングはカラーマップから色の組み合わせを選択し、6 個のピクセルをひとまとめにして、希望するオレンジの階調に近似します。遠目には、ピクセルは正しい階調で見えますが、近くでイメージを見ると、他の階調が混ざっているように見えます。ディザリングを説明するために、次の例では 24 ビットのトゥルーカラー イメージを読み取り、rgb2ind
を使用して わずか 8 色だけでインデックス付きイメージを作成します。最初の例はディザリングが使用されていません。2 番目の例はディザリングが使用されています。
イメージを読み取り、それを表示します。
rgb = imread('onion.png');
imshow(rgb)
インデックス付きイメージを 8 色で、ディザリングなしで作成します。
[X_no_dither,map] = rgb2ind(rgb,8,'nodither');
imshow(X_no_dither,map)
ディザリングで、8 色のインデックス付きイメージを作成します。ディザリングされたイメージは、見かけの色の数を非常に大きくしますが、若干あいまいに見えることに注意してください。ディザリングされていないイメージは、見かけの色数が少なく見えますが、ディザリングされたイメージと比べ、空間分解能が高くなっています。ディザリングなしで色数を減らすことによるリスクの 1 つに、新しいイメージに偽の等高線を生じる可能性があります。
[X_dither,map] = rgb2ind(rgb,8,'dither');
imshow(X_dither,map)