在javascript / p5.js中找到与当前颜色最接近的索引颜色值

时间:2019-09-09 22:50:49

标签: javascript processing p5.js

我有一个“已索引” RGBA颜色值的数组,对于我加载的任何给定图像,我希望能够遍历已加载像素的所有颜色值,并使它们与我所索引的最接近的颜色匹配颜色值。因此,如果图像中的像素的颜色为RGBA(0,0,10,1),而颜色RGBA(0,0,0,1)是我最接近的索引值,则它将调整加载的像素到RGBA(0,0,0,1)。

我知道PHP具有功能imagecolorclosest

SELECT SUM(amount)  
FROM aggregated_requests  
WHERE user_id = ?  
AND request_date <= ?  
AND request_date >= ?

javascript / p5.js /处理是否有相似之处?将一种颜色与另一种颜色进行比较的最简单方法是什么。目前,我可以使用以下代码(使用P5.js)读取图像的像素:

int imagecolorclosest( $image, $red, $green, $blue )

2 个答案:

答案 0 :(得分:2)

如果我对您的理解正确,则希望将图像的颜色保留在一定的限制托盘内。如果是这样,则应将此功能应用于图像的每个像素。它将为您提供一组有限颜色(indexedColors)中最接近所提供像素的颜色值。

// example color pallet (no alpha)
indexedColors = [
  [0, 10, 0],
  [0, 50, 0]
];

// Takes pixel with no alpha value
function closestIndexedColor(color) {
  var closest = {};
  var dist;
  for (var i = 0; i < indexedColors.length; i++) {
    dist = Math.pow(indexedColors[i][0] - color[0], 2);
    dist += Math.pow(indexedColors[i][1] - color[1], 2);
    dist += Math.pow(indexedColors[i][2] - color[2], 2);
    dist = Math.sqrt(dist);

    if(!closest.dist || closest.dist > dist){
        closest.dist = dist;
      closest.color = indexedColors[i];
    }
  }
  // returns closest match as RGB array without alpha
  return closest.color;
}

// example usage
closestIndexedColor([0, 20, 0]); // returns [0, 10, 0]

它的工作方式与您提到的PHP函数相同。如果将颜色值视为3d坐标点,则壁橱颜色将是它们之间的3d“距离”最小的颜色。此3d距离是使用距离公式计算的:

3d distance formula

答案 1 :(得分:2)

每种颜色包含3个颜色通道。想象一下颜色是3维空间中的一个点,其中每个颜色通道(红色,绿色,蓝色)都与一个维相关联。您必须通过Euclidean distance找到最接近的颜色(点)。距离最小的颜色是“最近”的颜色。

在p5.js中,您可以使用p5.Vector进行矢量算法。到点之间的欧式距离可以通过.dist()计算。因此,点“ a”和“ b”之间的距离可以表示为:

let a = createVector(r1, g1, b1);
let b = createVector(r2, g2, b2);
let distance = a.dist(b);

以某种方式使用表达式:

colorTable = [[r0, g0, b0], [r1, g1, b1] ... ];

int closesetColor(r, g, b) {
    let a = createVector(r, g, b);
    let minDistance;
    let minI;
    for (let i=0; i < colorTable; ++i) {
        let b = createVector(...colorTable[i]);
        let distance = a.dist(b);
        if (!minDistance || distance < minDistance) {
            minI = i; minDistance = distance;
        }
    }
    return minI;
}

function setup() {
    image(img, 0, 0, width, height);
    let d = pixelDensity();
    let fullImage = 4 * (width * d) * (height * d);
    loadPixels();

    for (let i = 0; i < fullImage; i+=4) {
        let closestI = closesetColor(pixels[i], pixels[i+1], pixels[i+2])
        pixels[i]   = colorTable[closestI][0];
        pixels[i+1] = colorTable[closestI][1];
        pixels[i+2] = colorTable[closestI][2];
    }
    updatePixels();
}