30

クライアントサイドスクリプトを使用して画像(HTMLを含む)の暗さ/明るさを検出するために利用できるスクリプトがあるかどうか誰かが知っていますか?

基本的に、背景で使用されている画像の明るさ(暗い/明るい)を検出し、CSS / HTML / jQuery / JSに暗いまたは明るい(trueまたはfalse)の変数に基づいてページを適応させたいと考えています。

サーバーサイドスクリプトが利用できることは知っていますが、この特定の開発プロジェクトには使用できません。

4

6 に答える 6

62

この関数は、各色をグレースケールに変換し、すべてのピクセルの平均を返すため、最終的な値は0(最も暗い)から255(最も明るい)の間になります。

function getImageLightness(imageSrc,callback) {
    var img = document.createElement("img");
    img.src = imageSrc;
    img.style.display = "none";
    document.body.appendChild(img);

    var colorSum = 0;

    img.onload = function() {
        // create canvas
        var canvas = document.createElement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this,0,0);

        var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
        var data = imageData.data;
        var r,g,b,avg;

        for(var x = 0, len = data.length; x < len; x+=4) {
            r = data[x];
            g = data[x+1];
            b = data[x+2];

            avg = Math.floor((r+g+b)/3);
            colorSum += avg;
        }

        var brightness = Math.floor(colorSum / (this.width*this.height));
        callback(brightness);
    }
}

使用法:

getImageLightness("image.jpg",function(brightness){
    console.log(brightness);
});

JSFiddle:

http://jsfiddle.net/s7Wx2/

于 2012-12-07T12:25:23.030 に答える
34

私の回答は@lostsourceの回答のコードのほとんどを再利用していますが、暗い画像と明るい画像を区別するために別の方法を使用しています。

まず、RGBチャネルの合計の平均値の結果を(簡単に)分析する必要があります。人間にとって、それは無意味です。ピンクは緑より明るいですか?つまり、なぜ(0、255、0)が(255、0、255)よりも低い輝度値を与えるようにしたいのですか?また、ミッドグレー(128、128、128)は、ミッドグリーン(128、255、0)と同じように明るいですか?これを考慮に入れるために、HSV色空間で行われるようにチャネルの色の明るさのみを扱います。これは、単に特定のRGBトリプレットの最大値です。

残りはヒューリスティックです。max_rgb = max(RGB_i)いくつかのポイントをしましょうi。が128未満の場合max_rgb(8bppの画像を想定)、i暗い新しいポイントが見つかりました。それ以外の場合は明るいポイントです。すべてのポイントに対してこれを行うと、明るいポイントと暗いポイントがi得られます。その場合、画像は明るいと言えます。すべてのポイントが暗い場合は-1の値を取得し、逆にすべてのポイントが明るい場合は+1を取得することに注意してください。前の式は微調整できるので、かろうじて暗い画像を受け入れることができます。コードでは、変数に。という名前を付けましたが、画像処理のフィールドを正当化するものではありません。したがって、画像が明るいと言います。AB(A - B)/(A + B) >= 0fuzzyfuzzy(A - B)/(A + B) + fuzzy >= 0

コードはhttp://jsfiddle.net/s7Wx2/328/にあります、それは非常に簡単です、私の表記があなたを怖がらせないでください。

于 2012-12-07T15:56:53.213 に答える
8

バックグラウンドチェックと呼ばれるスクリプトは、画像の暗さ/明るさを検出できます。JavaScriptを使用してこれを行います。

これへのリンクは次のとおりです。

http://www.kennethcachia.com/background-check/

このタイプの検出機能を備えたスライダーを作成したい人に役立つことを願っています。

于 2013-10-01T12:15:31.197 に答える
2

MarvinJは、特定の画像の平均色を取得するためのメソッドaverageColor(image)を提供しています。平均的な色を使用して、画像上のラベルの色を定義するルールを作成できます。

画像の読み込み:

var image = new MarvinImage();
image.load("https://i.imgur.com/oOZmCas.jpg", imageLoaded);

平均色の取得:

var averageColor = Marvin.averageColor(image2); // [R,G,B]

この投稿のスニペットの出力:

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

var canvas = document.getElementById("canvas");
var image1 = new MarvinImage();
image1.load("https://i.imgur.com/oOZmCas.jpg", imageLoaded);
var image2 = new MarvinImage();
image2.load("https://i.imgur.com/1bZlwv9.jpg", imageLoaded);
var loaded=0;

function imageLoaded(){
  if(++loaded == 2){
    var averageColor;
    averageColor = Marvin.averageColor(image1);
    setText("LION", averageColor, "text1");
    averageColor = Marvin.averageColor(image2);
    setText("LION", averageColor, "text2");
  }
}

function setText(text, averageColor, id){
  if(averageColor[0] <= 80 && averageColor[1] <= 80 && averageColor[2] <= 80){
     document.getElementById(id).innerHTML = "<font color='#ffffff'>"+text+"</font>";
  }
  else if(averageColor[0] >= 150 && averageColor[1] >= 150 && averageColor[2] >= 150){
     document.getElementById(id).innerHTML = "<font color='#000000'>"+text+"</font>";
  }
  
}
.divImage{
  width:400px; 
  height:268px;
  display:grid;
}

.divText{
  font-family:Verdana;
  font-size:56px;
  font-weight:bold;
  margin:auto;
  display:table-cell;
}
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<div id="result"></div>
<div style="background-image:url(https://i.imgur.com/oOZmCas.jpg);" class="divImage">
   <div id="text1", class="divText"></div>
</div>
<div style="background-image:url(https://i.imgur.com/1bZlwv9.jpg);" class="divImage">
   <div id="text2", class="divText"></div>
</div>

于 2018-03-29T12:27:36.440 に答える
1

私のシナリオでは、背景が透明な画像を使用しているため、これらのピクセルを別の方法で処理する必要があります。

コードについては、このフィドルを参照してください。背景が透明な2つの画像があります。前景が明るい画像は、以前は@mmgpのコードで暗い画像と見なされていましたが、現在は明るい画像として正しく解釈されています。

私の答えは、mmgpからのこの答えのjsfiddleに基づいています。違いは、完全に透明なピクセルは明るいまたは暗いとしてカウントされないことです。また、暗い色と明るい色の比率では、どちらか一方のピクセルのみが考慮され、透明ではありません。

// Ignore transparent pixels
if (data[x+3] === 0) {
  continue;
}
// Calculate the dark to light ratio
var dl_diff = ((light - dark) / (light + dark));

うまくいけば、アルファチャネルについてもっと知っている誰かがそれを改善することができます。完全に透明なピクセル(0?)だけを透明と見なし、他の値(1〜255)を処理しないのは間違っていると思います。アルファ値を255で割ってから...?

于 2020-12-08T20:00:58.040 に答える
0

私のセットアップでは、画像が透明であるかどうか、透明である場合は、不透明なピクセルで主に暗いか明るいかを確認したいと思いました。また、base64でエンコードされたデータ画像ではなくリモート画像(URL)を使用したかったので、@ lostsourceの優れた回答を微調整して、いくつかの追加機能を追加しました。

  • transparencynonTransparentBrightness(および)をbrightness返します
  • crossOrigin="anonymous"src)を使用したCORSサポート
  • 0-を使用すると、結果は( -100ではなく) %になります0255
  • レンダリングされた画像サイズ(img.naturalWidthおよびimg.naturalHeight)ではなく、フル画像サイズを使用するようにしてください。画像が小さいほど、結果の信頼性が低くなります(ピクセル化が原因である可能性があります)。

私のセットアップでは、暗いBGに画像を表示しているので、nonTransparentBrightness <= 60 && transparency > 0少量のパディングと白いBGを追加するとします。

これはまだ徹底的にテストされていないため、いくつかの癖があるかもしれませんが、方向的に正しいようで、これまでのところ私のユースケースでは機能しました。

const getImageBrightness = (img) => {
  if (!img) return null;

  let alphaSum = 0;
  let colorSum = 0;

  var canvas = document.createElement("canvas");
  
  // make the canvas use the full size of the image, not the rendered size
  canvas.width = img.naturalWidth;
  canvas.height = img.naturalHeight;

  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);

  var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  var data = imageData.data;
  var r, g, b, a, avg;

  for (var x = 0, len = data.length; x < len; x += 4) {
    r = data[x];
    g = data[x + 1];
    b = data[x + 2];
    a = data[x + 3];

    avg = Math.floor((r + g + b) / 3);
    colorSum += avg;
    alphaSum += a;
  }

  const transparency = 100 - Math.floor((alphaSum / (img.naturalWidth * img.naturalHeight) / 255) * 100);
  const brightness = Math.floor((colorSum / (img.naturalWidth * img.naturalHeight) / 255) * 100);
  const nonTransparentBrightness = Math.floor((brightness / (100 - transparency)) * 100);

  return { brightness, transparency, nonTransparentBrightness };
};

var imgs = document.body.getElementsByTagName('img');

const handleImage = (imageSrc) => {
  const img = document.createElement("img");
  img.src = imageSrc;
  img.style.display = "none";
  img.crossOrigin = "anonymous";
  document.body.appendChild(img);

  img.onload = () => {
    const { brightness, nonTransparentBrightness, transparency } =
      getImageBrightness(img);

    document.getElementsByTagName('pre')[0].innerHTML = `brightness: ${brightness} | nonTransparentBrightness: ${nonTransparentBrightness} | transparency: ${transparency}`;
  };
}

for(var x = 0; x < imgs.length; x++) {
  imgs[x].onclick = function() {
    const imgEl = this;
    handleImage(imgEl.src);
  }
}
body {
  background-color: #999;
}

img {
  width: 100px;
}
<img src="https://static.files.bbci.co.uk/orbit/8161b75793cc3c38d814e1a4a19a2f6a/img/blq-orbit-blocks_grey.svg" />
<img src="https://static.aviva.io/assets/logo/aviva-logo.svg" />
<img src="https://www.moneyrates.com/wp-content/uploads/imagesrv_wp/2516/barclays_bank_logo_thumbnail.png" />

<pre>Click on image to get values</pre>

于 2022-01-17T16:19:33.767 に答える