在 javascript / p5.js 中查找与当前颜色最接近的索引颜色值
Finding the closest indexed color value to the current color in javascript / p5.js
我有一个 "indexed" RGBA 颜色值数组,对于我加载的任何给定图像,我希望能够 运行 通过加载像素的所有颜色值,并且将它们与我的索引颜色值中最接近的匹配。因此,如果图像中的像素具有 RGBA(0,0,10,1) 颜色,并且颜色 RGBA(0,0,0,1) 是我最接近的索引值,它将调整加载的像素到 RGBA(0,0,0,1).
我知道PHP有一个函数imagecolorclosest
int imagecolorclosest( $image, $red, $green, $blue )
javascript/p5.js/processing有没有类似的东西?将一种颜色与另一种颜色进行比较的最简单方法是什么?目前我可以用这段代码读取图像的像素(使用P5.js):
let img;
function preload() {
img = loadImage('assets/00.jpg');
}
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 curR = pixels[i];
let curG = pixels[i]+1;
let curB = pixels[i+2];
let curA = pixels[i+3];
}
updatePixels();
}
如果我对您的理解正确,您希望将图像的颜色保持在某个有限的调色板内。如果是这样,您应该将此函数应用于图像的每个像素。它将为您提供一组有限颜色 (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 "distance" 的颜色。此 3d 距离使用距离公式计算:
每种颜色包含3个颜色通道。将颜色想象成 3 维 space 中的一个点,其中每个颜色通道(红色、绿色、蓝色)都与一个维度相关联。您必须通过 Euclidean distance 找到最接近的颜色(点)。距离最短的颜色是 "closest" 颜色。
在 p5.js 中您可以使用 p5.Vector
for vector arithmetic. The Euclidean distance between to points can be calculated by .dist()
。所以分别"colors"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();
}
我有一个 "indexed" RGBA 颜色值数组,对于我加载的任何给定图像,我希望能够 运行 通过加载像素的所有颜色值,并且将它们与我的索引颜色值中最接近的匹配。因此,如果图像中的像素具有 RGBA(0,0,10,1) 颜色,并且颜色 RGBA(0,0,0,1) 是我最接近的索引值,它将调整加载的像素到 RGBA(0,0,0,1).
我知道PHP有一个函数imagecolorclosest
int imagecolorclosest( $image, $red, $green, $blue )
javascript/p5.js/processing有没有类似的东西?将一种颜色与另一种颜色进行比较的最简单方法是什么?目前我可以用这段代码读取图像的像素(使用P5.js):
let img;
function preload() {
img = loadImage('assets/00.jpg');
}
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 curR = pixels[i];
let curG = pixels[i]+1;
let curB = pixels[i+2];
let curA = pixels[i+3];
}
updatePixels();
}
如果我对您的理解正确,您希望将图像的颜色保持在某个有限的调色板内。如果是这样,您应该将此函数应用于图像的每个像素。它将为您提供一组有限颜色 (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 "distance" 的颜色。此 3d 距离使用距离公式计算:
每种颜色包含3个颜色通道。将颜色想象成 3 维 space 中的一个点,其中每个颜色通道(红色、绿色、蓝色)都与一个维度相关联。您必须通过 Euclidean distance 找到最接近的颜色(点)。距离最短的颜色是 "closest" 颜色。
在 p5.js 中您可以使用 p5.Vector
for vector arithmetic. The Euclidean distance between to points can be calculated by .dist()
。所以分别"colors"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();
}