我有一組調色板(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);
}
這可行,但結果看起來不對。例如,我將分析一個森林場景的圖像,期望它導致綠色調色板,但它會返回另一個。我會很感激任何指導。
你可能會發現有工作直方圖更有效。 – Andy 2014-09-01 09:27:30