JavaScriptを介して画像の平均色を取得する


118

これが可能かどうかはわかりませんが、画像の平均値hexまたはrgb値を返すスクリプトを書くことを検討しています。ASで実行できることはわかっていますが、JavaScriptで実行することを検討しています。


19
私の友人のボアズは以前にこの道を進んでいます(うまくいけば彼はでチャイムを鳴らします)が、平均すると、通常、嘔吐のような色があなたに残ります。本当に欲しいのは「ドミナントカラー」。これを取得する方法はいくつかあります(色相ヒストグラムw /動的バケットなど)が、意図した結果にはおそらくより正確だと思います。
ポールアイリッシュ

回答:


149

私の知る限り、これを行う唯一の方法は<canvas/>...

デモV2http : //jsfiddle.net/xLF38/818/

これは、同じドメイン上の画像と、HTML5キャンバスをサポートするブラウザーでのみ機能します。

function getAverageRGB(imgEl) {

    var blockSize = 5, // only visit every 5 pixels
        defaultRGB = {r:0,g:0,b:0}, // for non-supporting envs
        canvas = document.createElement('canvas'),
        context = canvas.getContext && canvas.getContext('2d'),
        data, width, height,
        i = -4,
        length,
        rgb = {r:0,g:0,b:0},
        count = 0;

    if (!context) {
        return defaultRGB;
    }

    height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
    width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;

    context.drawImage(imgEl, 0, 0);

    try {
        data = context.getImageData(0, 0, width, height);
    } catch(e) {
        /* security error, img on diff domain */
        return defaultRGB;
    }

    length = data.data.length;

    while ( (i += blockSize * 4) < length ) {
        ++count;
        rgb.r += data.data[i];
        rgb.g += data.data[i+1];
        rgb.b += data.data[i+2];
    }

    // ~~ used to floor values
    rgb.r = ~~(rgb.r/count);
    rgb.g = ~~(rgb.g/count);
    rgb.b = ~~(rgb.b/count);

    return rgb;

}

IEについては、excanvasをチェックしてください


1
別のドメインにある画像のカラーヒストグラムを取得する方法はありますか?
Dan Loewenherz

1
Dan:別のドメインの画像の画像データにアクセスしようとすると、クロスオリジン制限にぶつかると思います。これは残念です。

8
私は青と緑の値に'rgb('+rgb.r+','+rgb.b+','+rgb.g+')'注意すべき配置があると思います、あなたは書いて、それはそうあるべきです'rgb('+rgb.r+','+rgb.g+','+rgb.b+')'。支配的な色が青であるのに奇妙ですが、結果は緑です:)。
Ariona Rian

7
クロスオリジン制限の優れた回避策が見つかりました。属性をimg.crossOrigin = '';設定する前に追加してくださいsrc。見つけた場所:coderwall.com/p/pa-2uw
mhu

カウントアップする必要はありませんcount === length / 4 / blockSize。;)
yckart

84

最近ドミナントカラーを取得するために出くわしたプロジェクトを投稿すると考えました。

色泥棒

画像からドミナントカラーまたは代表的なカラーパレットを取得するためのスクリプト。JavaScriptとキャンバスを使用します。

ドミナントカラーについて言及および示唆する他のソリューションは、適切なコンテキスト(「JavaScript」で)で質問に実際に回答することはありません。うまくいけば、このプロジェクトがまさにそれをしたい人を助けるでしょう。


55

「ドミナントカラー」はトリッキーです。あなたがしたいことは、色空間内の各ピクセルと他のすべてのピクセルとの間の距離(ユークリッド距離)を比較し、色が他のすべての色に最も近いピクセルを見つけることです。そのピクセルが支配的な色です。平均的な色は通常泥です。

ユークリッド距離を示すために、ここにMathMLがあればいいのに。グーグルそれ。

ここでPHP / GDを使用してRGB色空間で上記の実行を達成しました:https : //gist.github.com/cf23f8bddb307ad4abd8

ただし、これは非常に計算コストがかかります。大きな画像ではシステムがクラッシュし、クライアントで実行するとブラウザが確実にクラッシュします。私は自分の実行を次のようにリファクタリングすることに取り組んでいます。-ローカライズされた優位性のために、大きな画像を20px 20pxのグリッドに分割します。-x1y1とx1y2の間のユークリッド距離を使用して、x1y1とx1y3の間の距離を計算します。

この面で進歩を遂げたら教えてください。よろしくお願いします。私も同じことをします。

Canvasは、クライアントでこれを行うための最善の方法です。SVGはそうではなく、SVGはベクターベースです。実行を停止した後、次に実行したいのは、これをキャンバスで実行することです(おそらく、各ピクセルの全体的な距離の計算にWebワーカーを使用します)。

RGB空間での色間のユークリッド距離は視覚的な距離にあまり近いわけではないため、RGBはこれを行うのに適した色空間ではありません。これを行うためのより良い色空間はLUVかもしれませんが、これに適したライブラリ、またはRGBをLUVに変換するためのアルゴリズムは見つかりませんでした。

まったく異なるアプローチは、虹の中で色を並べ替え、色のさまざまな色合いを考慮するための許容範囲を備えたヒストグラムを作成することです。私はこれを試していません。虹で色を並べ替えるのは難しいので、色のヒストグラムもそうです。私はこれを次に試すかもしれません。繰り返しますが、ここで何か進歩があったらお知らせください。


6
これは私が+1よりももっと多くのことをしたいと思っている回答の1つです:-)
David Johnstone

3
明確な解決策が提示されなかったとしても、すばらしい答え。これは私が次のステップを決めるのに役立ちます...
10

これは素晴らしい答えです。LUVではなくL a b *色空間でユークリッド距離計算を行うためのノードモジュールをいくつか作成しました。github.com/zeke/color-namerおよびgithub.com/zeke/euclidean-distance
Zeke

1
@ユーザー:ただ疑問に思っていました。たとえば、大きな画像では1%のサンプルで計算を高速化するには十分ではないでしょうか。
jackthehipster 14

幾何学的な中央値のように聞こえます。多分これは助けることができますか? stackoverflow.com/questions/12934213/… そして、探しているポイントが元のセットに存在している必要がある場合: en.m.wikipedia.org/wiki/Medoid#Algorithms_to_compute_medoids
Lawrence Weru

16

まず、HTML5 CanvasやSVGがなくても実行できます。
実際、キャンバスやSVGを使用せずJavaScriptを使用して、データURIスキームを使用してクライアント側のPNGファイルを生成した人がいます

第二に、実際にはCanvas、SVG、または上記のいずれも必要ない場合があります。クライアント側で画像
処理するだけで、画像変更する必要がない場合、これはすべて必要ありません。

ページ上のimgタグからソースアドレスを取得し、そのXHRリクエストを行うことができます。これはおそらくブラウザーのキャッシュからのものであり、JavaScriptからのバイトストリームとして処理します。
画像形式をよく理解する必要があります。(上記のジェネレーターは部分的にlibpngソースに基づいており、良い出発点になるかもしれません。)


バイトストリームソリューションの場合は+1。これは、クライアントアプリケーションで作成する唯一の方法である場合に適しています。
loretoparisi 2015年

11

私はHTMLのcanvasタグを介して言うでしょう。

Operaの開発者による小さなコードについての@Georgの投稿はこちらです。

// Get the CanvasPixelArray from the given coordinates and dimensions.
var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

// Loop over each pixel and invert the color.
for (var i = 0, n = pix.length; i < n; i += 4) {
    pix[i  ] = 255 - pix[i  ]; // red
    pix[i+1] = 255 - pix[i+1]; // green
    pix[i+2] = 255 - pix[i+2]; // blue
    // i+3 is alpha (the fourth element)
}

// Draw the ImageData at the given (x,y) coordinates.
context.putImageData(imgd, x, y);

これは、各ピクセルのR、G、B値を使用して画像を反転します。RGB値を簡単に保存してから、赤、緑、青の配列を切り上げ、最後にそれらをHEXコードに変換することができます。


キャンバスソリューションに代わるIEがある可能性はありますか?
10

@ Ben4Himv:IE9プラットフォームのプレビューがあります;-)しかし、真剣に、私はそうではありません。
アンディE


4

JavaScriptは、画像の個々のピクセルカラーデータにアクセスできません。少なくとも、おそらくhtml5まではそうではありません...その時点で、キャンバスにイメージを描画し、キャンバスを検査できるようになるのは当然のことです(たぶん、私が自分で行ったことはないでしょう)。


2

オールインワンのソリューション

私は個人的に、Color Thiefをこの変更されたName that Colorのバージョンと組み合わせて、画像のドミナントカラー結果の配列を十分以上に取得します。

例:

次の画像を検討してください。

ここに画像の説明を入力してください

次のコードを使用して、ドミナントカラーに関連する画像データを抽出できます。

let color_thief = new ColorThief();
let sample_image = new Image();

sample_image.onload = () => {
  let result = ntc.name('#' + color_thief.getColor(sample_image).map(x => {
    const hex = x.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
    
  }).join(''));
  
  console.log(result[0]); // #f0c420     : Dominant HEX/RGB value of closest match
  console.log(result[1]); // Moon Yellow : Dominant specific color name of closest match
  console.log(result[2]); // #ffff00     : Dominant HEX/RGB value of shade of closest match
  console.log(result[3]); // Yellow      : Dominant color name of shade of closest match
  console.log(result[4]); // false       : True if exact color match
};

sample_image.crossOrigin = 'anonymous';
sample_image.src = document.getElementById('sample-image').src;

1

これは、MMCQ(Modified Median Cut Quantization)やOQ(Octree Quantization)のようないくつかのアプローチを持つ「カラー量子化」についてです。別のアプローチでは、K-Meansを使用して色のクラスターを取得します。

tvOSXHTMLのサブセットがあり、<canvas/>要素のない場所の解決策を見つけていたので、ここですべてまとめました。

XMLHttpRequestを使用してRGB画像の主要な色を生成する


1

精度は落ちますが、datauriサポートされている画像の平均色を取得する最速の方法:

function get_average_rgb(img) {
    var context = document.createElement('canvas').getContext('2d');
    if (typeof img == 'string') {
        var src = img;
        img = new Image;
        img.setAttribute('crossOrigin', ''); 
        img.src = src;
    }
    context.imageSmoothingEnabled = true;
    context.drawImage(img, 0, 0, 1, 1);
    return context.getImageData(1, 1, 1, 1).data.slice(0,3);
}

1

他の回答で指摘されているように、茶色になる傾向がある平均的な色とは対照的に、多くの場合、実際に支配的な色が必要です。最も一般的な色を取得するスクリプトを作成して、この要点に投稿しました


-2

画像の平均色または支配的な色を見つけるのに役立つオンラインツールpickimagecolor.comがあります。コンピューターから画像をアップロードし、画像をクリックするだけです。HEX、RGB、HSVの平均色を示します。また、選択する色に一致する色合いも検索します。何度も使ったことがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.