Imagemagickを使った減色処理

こんにちわ。今週のテックブログ、担当のURAです。
最近めっきりと寒くなりましたね。私は毎朝子供を保育園に連れて行くのですが、なぜか保育園は暑いのです。外は肌寒いのに、保育園の中で子供を教室に連れて行ったり荷物をセットしているだけで、ちょっと汗をかくくらい暑いのです。これ保育園あるあるだと思うのですが、世のお父さん方どうでしょうか?

ですよね?保育園、暑いですよね?
はい、全力で共感してもらえて満足したので、今回のテーマ「減色」の話に移ります。

Why 減色?

最近、とあるプロジェクトで「減色」の実装をしていました。
弊社は様々なアイテムにオンデマンドでプリントする会社です。
プリント方法にも色々あり、インクジェットプリントであれば写真のようなフルカラーの画像をプリントできますが、プリントする色数が1色のみであったり、2色のみであったりと限られているプリント方法もあります。
そして、注文時に指定された加工方法の色数と、お客様がアップロードしたデザインデータの色数は必ずしも一致しません。
そこで、デザインデータを決まった色数に減らす処理、つまり「減色」が自動的にできると、デザインデータを補正できるというわけです。

Imagemagickで減色してみる

減色処理にはいくつかアルゴリズムがあります。
今回は、Imagemagickを使って減色する方法をご紹介します。
説明のため、とある画像を8色に減色することを考えていきます。

色のビット深度を指定して減色する

「ビット深度」とは、画像の各チャネルを何ビットで表現しているかという数値です。
例えば、ビット深度が8ビットのRGB画像とは、Red / Green / Blueチャネルのそれぞれが8ビット(256色)で表現されている画像であり、1ピクセルはRed / Green / Blueを組み合わせた情報ですので、
256 * 256 * 256 ≒ 1678万
約1678万パターンの色表現が可能な画像という意味です。

Imagemagickの「depth」コマンドを使うと、ビット深度を指定して減らすことができます。
お題は8色に減色することですので、ビット深度を1ビット(Red:2 * Green:2 * Blue:2 = 8色)に減色します。
convert dance.png -depth 1 dance-depth1.png
単純に画像のビット数を減らすと、肌色が消えてしまいました。

パレットを指定して減色する

Imagemagickの「remap」コマンドを使うと、指定したパレットに使われている色のみになるよう、画像を再構成することができます。
今回は、パレットの色は元画像を見ながら大まかに決定し、以下のようなコマンドでパレットを作成しました。
convert -size 60x60 xc:"rgb(0,0,0)" xc:"rgb(255,255,255)" xc:"rgb(255,0,0)" xc:"rgb(0,255,0)" xc:"rgb(0,255,255)" xc:"rgb(0,0,255)" xc:"rgb(255,0,255)" xc:"rgb(254,220,189)" +append palette8.png
remapコマンドは以下です。
convert dance.png +dither -remap palette8.png dance-remap.png
上記のコマンドに「+dither」とありますが、これは色を組み合わせて中間色を表現する「ディザ」処理を入れないという意味です。
減色する8色以外の中間色が表現されてしまうと見づらいので、今回はディザ処理を省いています。

パレットを自身で作成したため肌色は出ていますが、細かくパレットを調整したわけではないので、例えば洋服の水色は色に差が出ています。
また、パレットの8色にしか減色できないため、様々な画像を自動的に減色する用途には向かなそうです。

画像の色分布から似た色を減色する

Imagemagickの「colors」コマンドを使うと、画像の色分布を元に似た色を減らすことができます。
アルゴリズムについて知りたい方は以下をご覧ください。
https://imagemagick.org/script/quantize.php
convert dance.png +dither -colors 8 dance-colors8.png
元画像の主要な色が再現できていそうです。

k-means法を使って減色する

k-means法とは、k個のクラスタに平均を使ってクラスタリングするアルゴリズムです。
機械学習界隈でも登場するアルゴリズムの一つですので、興味のある方は知らべてみてください。
https://ja.wikipedia.org/wiki/K%E5%B9%B3%E5%9D%87%E6%B3%95

Imagemagickでのコマンドは「kmeans」を使います。
magick dance.png -kmeans 8 dance-kmeans8.png
これも元画像の主要な色が再現できていそうです。
「colors」コマンドと比較すると、顔色が良くなった(頬の色がより再現できている)ような…?

まとめ

Imagemagickを使った減色処理について紹介しました。
紹介しておいてなんなのですが、とあるプロジェクトでは減色処理にImagemagickは採用せず、独自実装する道を選びました。
Imagemagickは誰でも使えますし、独自実装することでより直感的な減色の結果が得られるなら、ユーザビリティーの面で差別化できますしね。
カテゴリー: URA