我們這次要做的是亮度值方圖,在相機或者是編輯軟體上都會呈現亮度直方圖方便查看呈現的是暗部到亮部的像素分佈圖,也就是說整體越偏向左邊,代表畫面中暗部像素較多,可能為夜景或者是整體過暗,反之亦然。對於攝影師或者是創作者來說,可以依照直方圖來調整照片的呈現方式,而在有些處理中也會參考此數據而做不同的處理。所以接下來我們就來做個顯示亮度的直方圖吧。
首先第一步我們要先將 R、G、B 轉換成亮度。 參考 維基百科 算法,將三個通道給予不同的權重即可算出。最後回傳算出來的值。然後其實這也是灰階算法的其中一種,有興趣的讀者可以試試看,把三個通道的值都改成算出來的值,應該會發現用這種算法出來的圖會比昨天介紹的更真實。
export const calculateBrightness = pixelData => {
const result = []
for (let i = 0; i < pixelData.length; i += 4) {
const red = pixelData[i]
const green = pixelData[i + 1]
const blue = pixelData[i + 2]
const brightness = 0.299 * red + 0.587 * green + 0.114 * blue
result.push(Math.round(brightness))
// 可嘗試替代之前灰階算法
// pixelData[i] = brightness
// pixelData[i + 1] = brightness
// pixelData[i + 2] = brightness
}
return result
}
接下來我們做一個簡單的圖表顯示,這邊是使用 Echart
<div ref="echart" style="width: 200px;height:80px;"></div>
接著發送事件在圖片更新之後
editImageData(pixelData) {
const canvas = this.$refs.drawCanvas
const context = canvas.getContext('2d')
context.putImageData(pixelData, 0, 0)
this.$root.$emit('imgChange', pixelData)
}
設定好一些參數 ( 詳請就請看 Echart 官網了 )
methods: {
calcuateHistogram(pixelData) {
const result = filter.calculateBrightness(pixelData.data)
this.echart.setOption({
xAxis: {
min: 0,
max: 255,
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
}
},
yAxis: {
show: false
},
grid: {
left: 0,
top: 0,
right: 0,
bottom: 10
},
series: [{
type: 'bar',
data: result,
large: true
}]
}, true, true)
}
},
mounted() {
this.echart = echarts.init(this.$refs.echart, {})
this.$root.$on('imgChange', this.calcuateHistogram)
}
配上昨天實做的曝光度後應該會蠻有感覺,當曝光度提高時會發現整體曲線往右偏移,反之亦然。直方圖可以提供一個客觀的數據來描述圖片的曝光程度,方便創作者使用。
今天實做了曝光直方圖,其實用相對應的原理,也可以分別創造出各種顏色的直光圖,在影像編輯軟體上,除了曝光直方圖之外,在不同場合也會有更細部的直光圖出現喔!明天見~