从 HSV 模型中提取 'dominant' 颜色? (不是来自 RGB 模型)

Extract 'dominant' colors from HSV model? (not from RGB model)

我正在寻找从图像中获取颜色的调色板。

我可以从图像中获取 RGB 数据

getRgbData() {
    this.canvas = window.document.createElement('canvas')
    this.context = this.canvas.getContext('2d')
    this.width = this.canvas.width = image.width || image.naturalWidth
    this.height = this.canvas.height = image.height || image.naturalHeight
    this.context.drawImage(image, 0, 0, this.width, this.height)
    return this.context.getImageData(0, 0, this.width, this.height)
}

并将RGB值转换为HSV模型(rgbToHsv方法写自https://gist.github.com/mjackson/5311256#file-color-conversion-algorithms-js-L1

getHsvData() {
    const { data, width, height } = this.getRgbData()
    const pixcel = width * height
    const q = 1
    const array = []
    for (var i = 0, r, g, b, offset; i < pixcel; i = i + q) {
        offset = i * 4
        r = data[offset + 0]
        g = data[offset + 1]
        b = data[offset + 2]
        array.push({ r, g, b })
    }

    return array.map(l => this.rgbToHsv(l.r, l.g, l.b))
} 

结果是这样的(RGB 24bit转换后的数据)

[
   {h: 0.6862745098039215, s: 0.7727272727272727, v: 0.17254901960784313},
   {h: 0.676470588235294, s: 0.723404255319149, v: 0.1843137254901961},
   .....
]

color-thief and vibrant.js 是从 RGB 模型中获取主色,但我想 从转换后的 HSV 模型中获取主色。 (听说从hsv中提取颜色更符合人眼,对吗?)

如何从 HSV 模型中提取颜色..?

我们需要做的第一件事是获取图像的平均颜色。我们可以通过单独添加每个颜色通道然后除以 canvas.

的高度和宽度来做到这一点
function channelAverages(data, width, height) {
  let r = 0, g = 0, b = 0
  let totalPixels = width * height
  for (let i = 0, l = data.data.length; i < l; i += 4) {
    r += data.data[i]
    g += data.data[i + 1]
    b += data.data[i + 2]
  }
  return {
    r: Math.floor(r / totalPixels),
    g: Math.floor(g / totalPixels),
    b: Math.floor(b / totalPixels)
  }
}

接下来我们要将返回的颜色的平均值转换为 HSL,我们可以用这个函数来完成(你也 link 到上面)。

function rgbToHsl(r, g, b) {
  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if (max == min) {
    h = s = 0; // achromatic
  } else {
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }
  return [h, s, l];
}

所以,为了得到我们的输出,我们可以这样做:

let data = ctx.getImageData(0, 0, canvas.width, canvas.height)
let avg = channelAverages(data, width, height)
console.log(rgbToHsl(avg.r, avg.g, avg.b))

如果我们想要可以在编辑器(例如 PhotoShop 或 Gimp)中使用的数字来验证我们的结果,我们只需要将每个相乘即可:

h = h * 360 
    Example: 0.08 * 360 = 28.8

s = s * 100 
    Example: 0.85 * 100 = 85

l = l * 100 
    Example: 0.32 * 100 = 32

有一个名为 Kleur.js 的库,您可以使用它来获取图像,但请记住,它每次都会提供随机调色板。但主色在每个调色板中都将保持不变

// Create the Kleur Object
Kleur = new Kleur();

// Set the image link to get the palette from
imageObj = Kleur.init(imgLink);

// Wait for the image to load
imageObj.onload = function(e) {

    // get the color array from the image
    let colorArr = Kleur.getPixelArray(imageObj);

    // pass the array to generate the color array
    let array_of_pixels = Kleur.generateColorArray(colorArr);

    // you can get the dominant color from the image
    const dominant = Kleur.getDominant(array_of_pixels);

    // log the light colors and the dominant color
    console.log(light, dominant)
}

如果您想查看使用此代码的示例,请访问 codepen

如果你想要所有主色,我认为是像素最多的颜色,你可以访问 array_of_pixels,所以你可以

// for first five dominant color
for(let x = 0; x < 5; x++){
    console.log(array_of_pixels[x].hsv);
}

// for the dominant colors hsv value
console.log(dominant.hsv)

这将记录图像中五个最主要颜色的 hsv 值(通常主要颜色非常相似,因此请注意这一点)

Kleur js returns 各种颜色的颜色 space

  • RGB
  • 十六进制
  • 单纯疱疹病毒
  • XYZ
  • 实验室
  • LCH

它还 returns 计算具有颜色的像素数