web-dev-qa-db-ja.com

アルゴリズムの課題:画像から配色を生成する

バックグラウンド

そのため、私はWebアプリの新しいイテレーションに取り組んでいます。そして、私たちのユーザーは怠惰であることに夢中になっていることがわかりました。本当に怠け者。実際、私たちが彼らのために行う仕事が多ければ多いほど、彼らはサービスを愛するようになります。既存のアプリの一部では、ユーザーが使用する配色を選択する必要があります。しかし、私たちは画像(ユーザーのウェブサイトのスクリーンショット)を持っているので、なぜ私たちは彼らの怠惰を満足させて彼らのためにそれをすることができないのですか?回答:できます。楽しいプログラミング演習になります。 :)

挑戦

画像が与えられた場合、対応する配色をどのように作成しますか?つまり、画像内の主要なX色をどのように選択しますか(XはWebアプリによって定義されます)。特定の状況で使用される画像は、フル解像度(1280x1024など)で撮影されたユーザーのWebサイトのスクリーンショットです。 (注:アルゴリズムを簡単に説明してください。実際の擬似コードを投稿する必要はありません。)

ボーナスポイント(実際のSOポイント)ではなく、ストリートクレジットポイント):

  • シンプルでありながら効果的なアルゴリズムの説明。コードは私たちが作成する方法です-それをシンプルで美しく保ちます。
  • ユーザーが「カラフル」、「明るい」、「ミュート」、「深い」などのさまざまな「ムード」に従って配色を微調整できるようにします(a la Kuler
  • ウェブサイトのスクリーンショットで使用されているメインテキストの色を確実に決定する方法を説明します(独自の個別のアルゴが必要になる可能性があります)。

インスピレーション

同様の機能を実行する既存のサイトがいくつかあります。それらをチェックして、「これをどのように複製しますか?どうすれば改善できますか?」と自問してください。

53
rinogo
  1. プライマリXカラーを見つけるには、アプリをスクリーンショットします。画像に対してカラーヒストグラムを実行します。ヒストグラムの上位X色がテーマです。編集:グラデーションを使用する場合は、色の明確な「ピーク」を選択する必要があります。つまり、オレンジがグラデーションで使用される主要な色の1つである場合、「オレンジ」の周りにたくさんの色がある可能性があります。効果的には、ヒストグラムから選択した色の間に一定の距離を強制するだけです。

  2. 配色の調整は、HSV空間で行うのが最適です。色をHSV空間に変換し、ユーザーが「より明るく」したい場合は値を増やし、より「カラフル」にしたい場合は彩度を上げます。

  3. テキストの色の決定は、変動性の高い領域(フーリエ空間での高周波数)を特徴づけることによって最もよく行うことができます。これらの領域内には、テキストと背景の2つの色が必要です。この場合、テキストはあまり使用されない色です。または、いくつかの色、テキスト、背景画像の色があります。この場合、テキストの色が最も一般的な色です。

26
Paul Sonier

あなたは見ることができます:

https://github.com/dcollien/Dreamcoat

これはCoffeeScriptでこれを行います(読み書きのできるコーヒーなので、十分に文書化されています)

ここでのデモ: http://dcollien.github.io/Dreamcoat/test.html

これには、色の量子化アプローチとKMeansアプローチの両方が組み合わされています。

8
Molange

これは、(アートワークの)画像に使用されるパレットを見つけるために行います。

  1. Imagemagickから始めて、大きな画像を実行可能なサイズ(つまり、最大サイズで400 px)にサイズ変更します。これは、実際には、微妙な局所的な色の違いを、それらの色の平均でより少ないピクセルに変換するのに役立ちます。

  2. サイズ変更された画像に存在する各ピクセルをループし、各ピクセルのRGB値を読み取り、RGBをHSBに変換し、HSB値を配列に格納します。

  3. 次に、見つかったピクセルカラーごとに、色相範囲(0,255)を16で除算し、彩度範囲(0,100)を10で除算し、明るさ範囲(0,100)を10で除算します。結果を整数に切り上げます。これは、ピクセルを類似した色のカテゴリにグループ化するのに役立ちます。

    したがって、HSBが223,64,76のピクセルは、カテゴリ14,6,8になります。

    各カテゴリ内では、各ピクセルの正確な色を見つけることができますが、ほとんどの場合、カテゴリ自体はソース画像と色が一致しています。

    カテゴリからより良い色の複製が必要な場合は、HSBをより細かい分割に分割することを選択します。すなわち。各H、S、Bを16,10,10ではなく8,5,5で割ります。

  4. 最も普及している色のカテゴリを数え、並べ替えて表示します。ピクセル数が非常に少ないカラーカテゴリを破棄します。

注:これは、実際には、同じ色の値を持つピクセルが非常に少ないアートワーク用に設計されています(つまり、影とグラデーションのある絵画)。

ほとんどの場合、HTMLページには、特定の色の値に正確に一致するピクセルが多く含まれている可能性があります(つまり、背景色、テキストの色などは、表示される場所に関係なくすべて同じ色になります)。

7
Gemini420

色の量子化 は、低色GIFのパレットを選択するために使用されるのと同じプロセスです。写真画像からカラーパレットを取得するために、LeptonicaのMMCQ(修正されたメディアンカット量子化)に基づくNick Rabinowitzの quantize.js を使用しました。

meemoo screen shotライブWebアプリ

6
forresto
  1. 画面イメージを、幅(全幅/ n)と高さ(全高/ m)を持つn xmの「グリッド」内のr個の長方形のグリッドに分割します。

    1a。中央から離れた領域など、画面の目立つ領域に重みを割り当てます。

    1b。長方形ごとに、ピクセルを(colorfrequency)のスペースに割り当てます。

  2. 各長方形R、度数分布f_R、および重みW_Rについて:

    2a。 「トップ周波数」、「セカンド周波数」(ief_R [i、:をスキャンして、i番目のスキームカラー(例:i = 1 <->背景色)を決定します。 ])各ブロック。

    2b。各iについて、スコアテーブルに入れます(color_iscore)ここで、score = f_R [i、 "frequency"] * W_R

    2c。各iの最高得点者は、i番目のスキームカラーになります。

理論的には、「白地に青」または「黒地に赤」が多い場合は、たとえば、白一次、青二次、または黒一次、赤二次を取得する必要があります。

テキストの色については、背景色に基づいて計算するか、二次色を選択します。HSVのV差が小さすぎる場合は、計算されたスキームの色に基づいて色を調整しますが、V値を増やします。

擬似コード:

float[][] weights = 
    { { 1.0, 3.0, 5.0, 5.0, 3.0, 1.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 3.0, 6.0, 6.0, 3.0 },
      { 2.0, 8.0, 9.0, 9.0, 7.0, 2.0, 3.0, 3.0, 2.0 },
      { 2.0, 7.0, 9.0, 9.0, 7.0, 2.0, 1.0, 1.0, 1.0 },
      { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 1.0 },
      { 1.0, 3.0, 5.0, 5.0, 3.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 6.0, 6.0, 2.0 },
      { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0 } };

// Leave the following implementations to the imagination:
void DivideImageIntoRegions( Image originalImage, out Image[][] regions );
void GetNthMostCommonColorInRegion( Image region, int n, out Color color );
TKey FindMaximum<TKey, TValue>( Map<TKey, TValue> map );

// The method:
Color[] GetPrimaryScheme( Image image, int ncolors, int M = 9, int N = 9 )
{
    Color[] scheme = new Color[ncolors];
    Image[][] regions = new Image[M][N];

    DivideImageIntoRegions( image, regions );

    for( int i = 0; i < ncolors; i++ )
    {
        Map<Color, float> colorScores = new Map<Color, float>();

        for( int m = 0; m < M; m++ )
        for( int n = 0; n < N; n++ )
        {
            Color theColor;
            GetNthMostCommonColorInRegion( region, i, theColor );

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }

        scheme[i] = FindMaximum( colorScores );
    }

    return scheme;
}

上記を見ると、変動の少ない領域がある場合、最も一般的な色と同じ2番目に一般的な色になることは明らかです。調整するために、そのような場合に2番目に一般的な色はnullである可能性があり、これを防ぐことができます。

            if( theColor != null )
                continue;

            if( colorScores[theColor] == null )
            { colorScores[theColor] = 0; }

            colorScores[theColor] += weights[m][n];
        }
5
maxwellb

必要なアルゴリズムのタイプの名前は 色の量子化 です。

残念ながら、利用できるソースコードはありませんが、 google search で何かが見つかると確信しています。

特に、このテーマに関する Dr。Dobb's Journalの記事 は有望なようです。

原色を見つける方法についてはすでに多くの良い提案があり、私は同様のアプローチを試してみます。テキストの色を見つけるために、私は別の提案があります。

画像の各線のヒストグラムを上から下に計算します。線のベースラインに到達するたびに、テキストの色の頻度が大幅に低下するはずです。次の行の大文字に到達するまで頻度は低くなり、その後、小文字に到達すると2番目のステップが続きます。

ベースラインに到達したときにさらに大きくなる別の強いピークがある場合は、背景色を見つけています。グラデーションの背景はこのピークを滑らかにし、ピークの変化(新しいラインに出入りするとき)はアンチエイリアスによって滑らかになります。

2

McWafflestixのソリューションと同様に、詳細を微調整する必要がありますが、私の一般的なアプローチは...

(私はHSVが適切なスペースであることに同意します)

  1. 画像のヒストグラムを取得し、それをフィルタリングしてノイズを平滑化し、VとSが「対象」の可能性のある色の(おそらく動的な)色域にある最高スコアを見つけます。青い空に赤い鳥がいると、計画を青ではなく赤に基づいて行うのに十分な賢さが必要になります。これには、「フレームの中央」や「三分割法」の分析など、写真の構図に関する推測が必要になる場合があります。これにより、色が関連する可能性が得られます。とにかく、これが私たちのベースカラーです。

  2. Kulerの線に沿って、カラーホイールの周りを移動して、ベースを補完する色を計算します。ステップ1のヒストグラムにも目立つように表示された場合、計算された褒め言葉の追加ポイント。

  3. ベースカラーと計算された賛辞を使用して、それぞれの明るいバージョンと暗いバージョン、多かれ少なかれ飽和しているなど、心地よい補助色を導き出します。

2
Trueblood

以下は、画像から配色を生成するためのさまざまなアプローチに関するいくつかの提案と議論です。

まず、ピクセルをある色空間に埋め込み/プロットします。これは、RGB、HSL、またはその他の色空間にすることができます。次に、次のいずれかを使用して配色を生成できます。

  1. 色空間のヒストグラムを作成する -これには、スペースをグリッドに分割し、各グリッドセルのピクセルをカウントすることが含まれます。ピクセル数が最も多い上位N個のセル(ヒストグラムバケット)を選択し、それぞれのピクセルを平均して、セルごとの色を生成します。これはあなたの配色にすることができます。

  2. メディアンカット または他のスペース分割手法-これは、データを確認することでスペースを分割するため、#1よりも優れた改善点です。

  3. ピクセルのクラスタリング -多くのクラスタリング手法(k-means、mean-shiftなど)の1つを使用して、ピクセルをグループにクラスター化します。次に、各グループのピクセルを平均して、配色を生成します。

上記の3つのアプローチについてより詳細な投稿を書きました ここ

また、上記の3つのアプローチのいずれかを使用して、画像をロードし、カラーパレットを生成できるようにする インタラクティブWebアプリ も作成しました。そのコードは github にあります。

1
mattnedrich

私はこれに少し遅れていますが、3D色空間でKohonenマップ(http://en.wikipedia.org/wiki/Self-organizing_map)を実装します。マップ上のポイントの数は、パレットに必要な個別の色の数になり、画像のすべてのピクセルを使用してマップをトレーニングします。私はこれを自分で試したことはありませんが、他の誰かがすでにそれを考えていると確信しています。

1
NickD

最小/最大値を維持しながら、色相、彩度、明るさを個別に平均します。

すべての色のターゲット色相を平均にロックし、境界間のxポイントの彩度と明るさを補間します。これにより、写真と同じ色かぶりで、単純なバリエーションのスキームが返されます。たぶん、あなたはAppleの外観を得るでしょう。

3色の犬の吐き気が出ないことを願っています。

0
Hans Malherbe