2014-09-01 35 views
0

我有一組調色板(8),每個調色板有5種顏色。目標是用畫布處理圖像,並確定哪個調色板最接近匹配。分析圖像並與最接近的調色板匹配

Atm我從調色板中獲得平均RGB值,然後在轉換爲LAB之前對源圖像執行相同操作,並使用CIE1976來計算色差。最接近的匹配是最小的距離。

這在一定程度上起作用,但我測試的許多圖像匹配兩個特定的調色板。有沒有更好的方法來計算圖像最相關的調色板?

所以我改變它與直方圖一起工作。我把下面的一些代碼,但基本上我:

  • 從所選圖像的3D RGB柱狀圖,分裂RGB值到8家的銀行之一,(8 * 8 * 8),512。
  • 展平直方圖以創建單個512陣列。
  • 通過除以圖像中的總像素來標準化值。
  • 我對顏色調色板也做同樣的事情,創建一個平坦的512直方圖。
  • 計算兩個直方圖之間的卡方距離以找到最接近的調色板。

我的調色板只有5種顏色,它們的直方圖非常空。將直方圖與卡方進行比較時會出現這個問題。

這是我如何爲要分析的圖像創建扁平直方圖。

  var canvas = document.createElement('canvas'), 
       ctx = canvas.getContext('2d'), 
       imgWidth = this.width, 
       imgHeight = this.height, 
       totalPixels = imgWidth * imgHeight; 

      ctx.drawImage(this, 0, 0, this.width, this.height); 

      var data = ctx.getImageData(0, 0, imgWidth, imgHeight).data; 
      var x, y, z, histogram = new Float64Array(512); 

      for(x=0; x<imgWidth; x++){ 
       for(y=0; y<imgHeight; y++){ 
        var index = imgWidth * y + x; 

        var rgb = [data[index], data[index+1], data[index+2] ]; 

        // put into relevant bank 
        var xbin = Math.floor((rgb[0]/255)*8) 
        var ybin = Math.floor((rgb[1]/255)*8) 
        var zbin = Math.floor((rgb[2]/255)*8) 

        histogram[ (ybin * 8 + xbin) * 8 + zbin ] ++; 
       } 
      } 

      // normalize values. 
      for(var i=0; i<512; i++) { 
       histogram[i] /= totalPixels; 
      } 

這就是我爲顏色調色板創建直方圖的方式。顏色只存儲在RGB值數組中,每個調色板有5種顏色。

 var pals = []; 

     palettes.forEach(function(palette){ 
      var paletteH = new Float64Array(512); 
      palette.forEach(function(color){ 
       var xbin = Math.floor((color[0]/255)*8); 
       var ybin = Math.floor((color[1]/255)*8); 
       var zbin = Math.floor((color[2]/255)*8); 
       paletteH[ (ybin * 8 + xbin) * 8 + zbin ] ++; 
      }); 
      for(var i=0; i<512; i++) { paletteH[i] /= 5; } 
      pals.push(paletteH); 
     }); 

要計算卡方距離我循環每個調色板獲取到圖像直方圖的距離。那麼最小的應該是最相似的。

  for(var p = 0; p<pals.length; p++){ 
       var result = 0; 
       for(var i=0; a = histogram[i], b = pals[p][i], i < 512; i++){ 
        result += 0.5 * (Math.pow(a-b,2)/(a + b + 1e-10)); 
       } 
       console.log(result); 
      } 

這可行,但結果看起來不對。例如,我將分析一個森林場景的圖像,期望它導致綠色調色板,但它會返回另一個。我會很感激任何指導。

+0

你可能會發現有工作直方圖更有效。 – Andy 2014-09-01 09:27:30

回答

0

您需要使用調色板顏色和樣本顏色之間的最小二乘差。

另外你需要爲每個通道RGB,可能A.爲此

它看起來是這樣的(僞代碼[...]):

var min = 999999; 
var paletteMatch; 

[loop sample colors] { 
    [loop palette colors] { 

    float lsd = (Math.pow(paletteR - sampleR, 2) + [greed] + [blue])/3; 

    if (lsd < min) { 
     min = lsd; 
     paletteMatch = currentPaletteInThisLoop; 
    } 
    } 
    [award a point for paletteMatch for this sample Color 
} 

[which palette has the most points?]