ここ最近ドミナントカラーを抽出するアルゴリズムを作っていました。この記事では実現したかったものやアルゴリズムについて、また出来上がるまでの過程を残します。
実現したかったもの
人間であれば直感的に画像から特徴的な色を識別することができますが、これをプログラムに置き換えられないか?と考えたのがきっかけです。例えばこんな感じです。
この記事でも触れていますが、Nintendo SwitchのeShopではソフトごとに背景色と文字・ボタンカラーが割り振られています。
これはパッケージ画像からアルゴリズムが色を抽出してセットされる仕組みで実現されています。この話は「Nintendo SwitchとWeb」という講演で任天堂によって触れられました。(出典:Nintendo Switchの中ではReactが動いてる!Nintendo eShop開発秘話を聞いてきた)
しかしながら、特徴色を画像から抽出するのは案外難しく、パッと思いつく下記のような方法ではうまく抽出できません。
- 画像の全ピクセルの色(RGB値など)を平均し特徴色とする
- 画像の各ピクセルで一番彩度が高く、輝度50%の色を特徴色とする
以降は実際に作ったアルゴリズムについて記載します。
開発したアルゴリズムの処理フロー
今回使ってみたのはk-means法によるクラスタリングアルゴリズムです。下記のような流れで処理をしています。
-
下記を定数として設定する。
- クラスタ数 :抽出する色の数
- 許容彩度 :彩度の低いピクセルを計算対象外とするための境界変数
- 最大ステップ数 :処理負荷が重くなりすぎないための最適化設定値
-
画像から各ピクセルのRGB値を抽出する。ここで、設定した
許容彩度
より低い彩度のピクセルは計算対象外として無視するものとする。 -
設定した
クラスタ数
だけランダムな初期値(RGB値など)を設定し、初期クラスタ値とする -
各ピクセルのRGB値と初期クラスタ値の距離を計算し、1番近いクラスタ値のクラスタとする
-
初期クラスタに所属する各ピクセルのRGB値の平均を計算し、新しいクラスタの値とする
-
4~5をクラスタの値が更新されなくなるまで、あるいは定数として設定した
最大ステップ数
まで繰り返す -
1番多くのクラスタが所属するクラスタの値を特徴色とする
定数の値をいじることで、彩度の高い色を特徴色として抽出させるようにしたり、クラスタリングの精度を上げたりできます。k-means法自体はクラスタリング手法の中でも基本的なもので、そのアルゴリズムも複雑でなく理解も簡単でした。(数学苦手な私でもなんとかできました。。)
より使いやすいアルゴリズムとするために
アルゴリズムを作っていて、まだまだ改善できるポイントがあると感じています。個人的に改良したいのは下記の項目です。
- サンプリング解像度 :処理速度と精度のどちらを優先するかを設定できるパラメータです。処理速度優先の場合はサンプリングしたピクセルのみで特徴色を計算し、精度優先の場合はサンプリングせずに多くのピクセルを計算対象とするようなイメージです。許容彩度のパラメータとケンカする恐れがあります。
- ピクセルの重みづけ :画像を見たとき、人は被写体や画像の中央など、特定のピクセルグループに視線がいくと考えられます。これを擬似的に再現する目的で、視線が行きやすいピクセルに対して重みづけをし、他のピクセルよりも計算結果に影響を与えやすくします。
開発中につまづいたところ
今回では許容彩度
というパラメータを用意し、彩度の低いピクセルを無視するアルゴリズムとしました。これを設ける前は思うような結果が出ず2ヶ月くらい悩みました(笑)
他にも画像サイズが大きい場合に、ドミナントカラー算出に時間がかかってしまうこともつまづきました。というかまだつまづきっぱなしですが、これはサンプリングする処理を噛ませることで解決できると考えています。
そのうちWebサイト化してより使いやすくしようと思っているのでお楽しみに!
参考文献
この記事の 最終更新:2023.9.7