色彩平衡公式添加了过多的白色

时间:2018-07-17 03:23:12

标签: javascript math colors html5-canvas

我试图写色彩平衡,但是数学上有些困难。我在Wikipedia

上找到了这个公式

Color Balance Formula

我要做的是以下事情:

  1. 获取所有红色,绿色和蓝色的总和
  2. 获取每个红色,绿色和蓝色通道的平均值
  3. 最后,我将公式应用于每个像素的每个通道,并将其设置回画布上的ImageData
    • (255 / col.red) * avgRed
    • (255 / col.green) * avgGreen
    • (255 / col.blue) * avgBlue

它看起来像这样:

function averageColor() {

  let sumRed = 0, sumGreen = 0, sumBlue = 0
  let pixels = 0

  // Get the sum of each color
  this.eachColor((col, idx) => {
    sumRed += col.red
    sumBlue += col.blue
    sumGreen += col.green
    pixels++
  })

  // Get the averages of each channel
  let avgRed = sumRed / pixels
  let avgGreen = sumGreen / pixels
  let avgBlue = sumBlue / pixels

  // Replace each color in the image
  this.eachColor((col, idx) => {
    this.setColorAtIndex(idx, color.rgb(
      (255 / col.red) * avgRed,
      (255 / col.green) * avgGreen,
      (255 / col.blue) * avgBlue
    ))
  })

}

以下是上面看到的两个函数(this._dtaUint8ClampedArray的{​​{1}}):

ImageData.data

当我应用滤镜时,这就是前后的样子,因为您会看到白色太多了。我的公式有什么问题?

之前的示例

Color Balance Before

之后的例子

Color Balance After

1 个答案:

答案 0 :(得分:3)

您不想乘以平均值。您希望缩放平均值,因此最大值为255。这实际上是在假装平均值应为灰色,然后进行缩放。因此,如果您的平均值是Short,那么白色可能是:

[133.54055621951161, 133.85785501369506, 95.50769969447687]

一旦有了您就可以使用它按公式进行缩放(在实践中,您应该使用伽玛校正此转换(srgb伽玛约为2.2,反之约为.45:

let avg = [133.54055621951161, 133.85785501369506, 95.50769969447687]
let max = Math.max(...avg)
let white = avg.map(c => 255 * c / max)
console.log(white)

您可以看到,所有这些操作都是按照 data[i] = (255/white[0]) ** .45 * data[i] ; // red data[i + 1] = (255/white[1]) ** .45 * data[i+1]; // green data[i + 2] = (255/white[2]) ** .45 * data[i+2] // blue 的比例缩放所有内容,这取决于平均值是接近灰色的。在这种情况下,它可以很好地消除黄变。

转换后,这是我的样子:

之前

enter image description here

之后

enter image description here