[英]Analyse an image and match to the closest color palette
我有一定數量的調色板(8),每種都有5種顏色。 目的是使用畫布處理圖像並確定最接近的調色板。
當時,我正在從調色板獲取平均RGB值,然后在將其轉換為LAB並使用CIE1976計算色差之前,先對源圖像進行同樣的處理。 最接近的匹配是最小的距離。
這在一定程度上可行,但是我正在測試的許多圖像都匹配兩個特定的調色板。 有沒有更好的方法來計算與圖像最相關的調色板?
因此,我將其更改為可與直方圖一起使用。 我將一些代碼放在下面,但基本上我是:
我的調色板只有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);
}
這可行,但結果似乎不對。 例如,我將分析一個森林場景的圖像,期望它會導致綠色調色板,但是它將返回另一個。 我將不勝感激任何指導。
您需要在調色板顏色和樣本顏色之間使用最小二乘方差。
另外,您還需要為每個通道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?]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.