improc

画像のカラーパレットの分析

画像内の色情報を分析(クラスタリング)して、カラーパレット(カテゴリ化された色リスト)を計算します。

いくつかの画像についてカラーパレットを計算した例を以下に示します。画像の下にある帯がカラーパレットで、それぞれの帯の長さがその色の出現比率に対応します。


元画像


元画像


元画像

R パッケージのインストール

この分析をRで行えるようにしました。pictplot パッケージの中の関数のひとつとして実装しています。

pictplot パッケージをインストールするには、いくつかの前準備が必要です。

まず、devtools パッケージをインストールする必要があります。devtools パッケージがまだインストールされていないなら、コンソールに

install.packages("devtools")

と打って devtools パッケージをインストールしてください。

次に、Windows 環境の人は RTools をインストールする必要があります。自分の R バージョンに合ったバージョンをインストールしてください。自分の R バージョンは、コンソールに

R.version
と打つとわかります(version.string のところを見てください)。

Mac 環境の人は、XCode を App Store からインストールしてください(そこそこデータ量が大きいです)。

上記のインストールができたら、次の内容をコンソールに打って pictplot パッケージをインストールします。

devtools::install_github("tsuda16k/pictplot")
パッケージが使える状態になっているかチェックします。
library(pictplot)
plot(regatta)
plot 関数によって水辺のボートの絵が表示されれば OK です。

分析の実施

まず、分析したい画像を読み込みます。im_load() 関数を使って画像を読み込みます。

im = im_load("https://htsuda.net/wp-content/uploads/2023/02/hokusai.png")

引数には画像のアドレスを指定します。Web上の画像でもいいし、自分のパソコン内にある画像でも読み込めます。上記の例では Web 上の画像を読み込んでいます。png や jpg など、画像の拡張子も含めて指定する必要があります。
自分のパソコン内の画像を読み込む場合、たとえば Mac なら "/Users/tsuda/hokusai.png" などと指定します。

次にカラーパレットの計算を行います。

palette = palette_extract(im, bandwidth = 0.03)

im は先ほど読み込んだ画像です。bandwidth は色のクラスタリングに関連するパラメータです(後述)。

上では計算されたカラーパレット情報を palette と名付けた変数に記録しました。中身を確認してみましょう。

palette
       R      G      B    n percent
1 0.9665 0.9421 0.8321 1292    53.8
2 0.7475 0.7890 0.7842  517    21.6
3 0.2285 0.2842 0.3832  305    12.7
4 0.3944 0.4341 0.4972  138     5.8
5 0.5172 0.5521 0.5877   73     3.0
6 0.5699 0.5980 0.6216   72     3.0
7 0.8035 0.8366 0.8155    3     0.1

7 つの行があり、すなわち 7 色の色が抽出されています。1 つめの色(1 行目)は R(赤)が 0.9665, G(緑)が 0.9421、B(青)が 0.8321 の色であり、ピクセル数(n)が1292、存在比率が 53.8% であることがわかります。

ピクセル数がかなり少ないことに気づいた人もいるかもしれません。この理由は、palette_extract 関数は色の抽出(クラスタリング)を行う前に、処理を効率化するために入力された画像を小さいサイズに縮小しているからです。どのくらい縮小するかは bound というパラメータで指定可能です。詳しくは関数のヘルプ(?palette_extract)から確認してください。

数値情報だけではどのような色か分かりにくいので、結果を画像にして表示しましょう。
palette_visualize() 関数を使って結果の可視化を行います。
引数は画像とカラーパレットです。threshold パラメータで、表示する色の選別をしています(後述)。
plot() 関数を使って画像を表示します。

out = palette_visualize(im, palette, threshold = 1)
plot(out)

ほぼ半数がクリーム色のような色で、残りは様々な濃さの青色のようです。

上の画像をよく見ると、パレットの色が 6 色しかないことに気づきます。これは threshold パラメータの影響です。threshold を 1 に設定していたので、1% 以上の存在比率の色のみが表示されています。7 番目の色は 0.1% しか存在しない色なので、可視化の際には表示されなくなっています。全ての色を表示したい場合は threshold の値を 0 にすると良いでしょう。threshold のデフォルト値は 1 に設定されています。

この出力画像を保存するには、im_save() 関数を使います。

im_save(out, name = "myimage", path = getwd(), format = "png", quality = 0.95)

name 引数は出力画像のファイル名です。拡張子は指定しません。
path 引数は出力先のディレクトリです。この例ではカレントディレクトリに画像を保存しています。
format 引数は出力画像のフォーマットです。"png", "jpg", "tiff" から選べます。
quality 引数は画像の圧縮率です。高い値ほど高画質になります。

カレントディレクトリ(コンソールに getwd() と打って表示される場所)に myimage.png という名前で画像が保存されているはずです。

基本的なことは以上です。

可視化のパラメータ設定について

palette_visualize() 関数には様々なパラメータがあり、出力画像の見た目を変えることができます。

monospace 引数を TRUE にすると、色の幅がすべて同じになります。それぞれの色を見比べやすいです。

out = palette_visualize(im, palette, monospace = TRUE)
plot(out)

type 引数を "circle" にすると、パレットを円環にして表示します。

out = palette_visualize(im, palette, type = "circle")
plot(out)

その他のパラメータとして、以下のものがあります。
width パラメータは色の帯の太さを決めます。デフォルトは 0.15 です。0から1の範囲の値を指定します。
outline_width パラメータは色の帯の輪郭線の太さ(ピクセル数)です。デフォルトでは 0 に指定されており、輪郭線は描画されません。

次の例では、色の帯を太くして、帯の輪郭線も加えています。

out = palette_visualize(im, palette, type = "circle", width = 0.3, outline_width = 4)
plot(out)

輪郭線の機能は、カラーパレットの中に白色がある場合に特に便利です(白がある場合、輪郭線がないと色が抜けているように見えるので)。

色クラスタリングのパラメータについて

palette_extract() 関数には bandwidth というパラメータがあり、この値によって、抽出される色の数が変わります。このパラメータの挙動を理解するために、この画像のカラーパレットを見てみます。

im = im_load("https://htsuda.net/wp-content/uploads/2023/02/usa.jpg")
palette = palette_extract(im, bandwidth = 0.03)
out = palette_visualize(im, palette, threshold = 1)
plot(out)

アメリカ合衆国の国旗には赤・白・青の三色があるので、その3色が抽出されて欲しいところです。トップ3には予想通りの3色が出現していますが、それ以外の様々な色も多く抽出されています。3 色だけを抽出させるにはどうすればよいでしょうか?

ひとつのやり方は、可視化の段階で比率の小さな色を無視してしまうという方法です。palette_visualize の threshold の値を 10 などにすると、三色だけにして表示ができます。

より根本的な解決方法は、カラーパレットの抽出処理を変えることです。palette_extract 関数の bandwidth の値を、たとえば 0.15 にすると、3色だけが抽出されます。

palette = palette_extract(im, bandwidth = 0.15)
out = palette_visualize(im, palette, threshold = 1)
plot(out)

この bandwidth とは何なのかですが、palette_extract 関数はミーンシフト法を用いた色のクラスタリングを行なっており、その処理において用いられるガウスカーネルの幅を意味しています。ミーンシフト法による色クラスタリングについて詳しくはこのページなどを参照してください。直感的には、カーネルの幅(bandwidth)が大きいほど、幅広い色がひとつにまとまりやすくなり、したがってクラスターの数(カラーパレットの色数のこと)が少なくなります。

palette_extract 関数はミーンシフト法を行うために meanShiftR パッケージの meanShift 関数を使っています。bandwidth パラメータはこの meanShift 関数の引数になります。

bandwidth をどのような値にすべきかについての正解は特にありません。クラスタ数を少なくしたいのか、多めにしたいのかという、分析者自身の目的によるからです。

palette_extract 関数のデフォルトでは bandwidth は 0.03 に設定されています。経験的には、国旗のような、色数が少数に限定されている画像の場合には、0.1 あるいはそれ以上の値にすると、直感と一致する結果が得られやすいです。

絵画や写真の場合には bandwidth を0.05 未満の値にした時に直感と合う結果になりやすいです(それより大きい値だと、直感よりも色の数が少なくなりやすい)。上で使った北斎の絵の場合、bandwidth を 0.1 にすると、2 色しか色が抽出されません。分析の目的に合わせて bandwidth の値を適切に設定する必要があるでしょう。

コメント

Copied title and URL