从HSV模型中提取“主导”颜色? (不是来自RGB模型)

时间:2018-03-16 01:33:57

标签: javascript rgb hsv

我正在寻找一张来自图片的彩色托盘。

我可以从图像中获取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-thiefvibrant.js从RGB模型获得主色,但我想 从转换的HSV模型中获得主色。 (我听说hsv的提取颜色更适合人眼。是不是?)

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

2 个答案:

答案 0 :(得分:2)

我们需要做的第一件事就是获得图像的平均颜色。我们可以通过单独添加每个颜色通道然后除以画布的高度和宽度来实现。

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,我们可以使用此功能(您也链接到上面的那个)。

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

答案 1 :(得分:0)

有一个名为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返回各种颜色空间中的颜色

  • RGB
  • 十六进制
  • HSV
  • XYZ
  • 实验室
  • LCH

它还返回计数,即具有颜色的像素数