web-dev-qa-db-ja.com

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

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

104
bgreater

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

DEMO 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 を確認してください。

128
James

支配的な色を得るために最近出会ったプロジェクトを投稿すると思いました。

カラー泥棒

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

支配的な色に言及し、提案する他のソリューションは、適切なコンテキスト(「in javascript」)で質問に実際に答えることはありません。うまくいけば、このプロジェクトがまさにそれをしたい人に役立つことを願っています。

77
J. Chase

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

ユークリッド距離を示すために、ここにMathMLがあればいいのにと思います。 Google it。

ここでPHP/Gdを使用して、RGBカラースペースで上記の実行を完了しました: https://Gist.github.com/cf23f8bddb307ad4abd8

ただし、これは非常に計算コストがかかります。それは大きな画像でシステムをクラッシュさせ、クライアントで試してみると間違いなくブラウザをクラッシュさせます。私は、実行を次のようにリファクタリングすることに取り組んでいます:-結果をルックアップテーブルに保存し、将来の各ピクセルの反復で使用します。 -大きな画像を20px 20pxのグリッドに分割して、局所的な優位性を確保します。 -x1y1とx1y2の間のユークリッド距離を使用して、x1y1とx1y3の間の距離を計算します。

この面で進展があったら教えてください。私はそれを見てうれしいです。私も同じことをします。

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

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

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

48
user304736

まず、HTML5 CanvasまたはSVGなしで実行できます。
実際には、誰かが JavaScriptを使用してクライアント側PNGファイルを生成withoutキャンバスまたはSVG、 データURIスキーム を使用します。

2番目:実際にはCanvas、SVG、または上記のいずれもまったく必要ない場合があります。
クライアント側でprocessイメージのみが必要な場合、withoutそれらを変更します。これはすべて必要ありません。

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

15
Andras Vass

HTMLキャンバスタグ経由で言うでしょう。

here を見つけることができます@GeorgによるOpera devによる小さなコードの話:

// 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コードに変換し直すことができます。

9
rnaud

私は最近、元々望んでいたことを行うjQueryプラグインに出会いました https://github.com/briangonzalez/jquery.adaptive-backgrounds.js 画像からドミニエートカラーを取得することに関して。

6
bgreater

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

4
Joel Martinez

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

私は個人的に Color Thief と組み合わせます の修正版Color という名前を付けて、画像のドミナントカラー結果の十分な配列を取得します。

例:

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

enter image description here

次のコードを使用して、支配的な色に関連する画像データを抽出できます。

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
Grant Miller

これは、 MMCQ (修正メディアンカット量子化)またはOQ(Octree量子化)のようないくつかのアプローチを持つ「色量子化」についてです。別のアプローチでは K-Means を使用して色のクラスターを取得します。

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

XMLHttpRequestを使用してRGBイメージのドミナントカラーを生成

1
loretoparisi

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

0
dctalbot

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);
}
0
350D

オンラインツール pickimagecolor.com を使用すると、画像の平均色または主要な色を見つけることができます。コンピュータから画像をアップロードして、画像をクリックするだけです。 HEX、RGB、HSVの平均色を提供します。また、選択する色に一致する色合いも見つけます。私はそれを複数回使用しました。

0
shubham agrawal