前言
图片滤镜,大家日常生活中应该经常接触到,各种自拍,美颜,都会涉及到图片的处理,今天研究的内容,是图片的滤镜,用灰度图的方式,探究下如何进行图片展示的处理。
准备工作
我们随便找到一个头像
这是一张色彩比较丰富的图片,我们处理后对比比较明显,接下来我们就开始我们的处理
filter方法
如果只是需要对图片处理进行展示,我们可以采取css 或者 canvas 的 filter 方式进行直接处理
// 滤镜实现
.gray {
filter: grayscale(1);
}
// canvas 滤镜实现
const canvas = document.querySelector('.canvas')
const ctx = canvas.getContext('2d')
const img = document.querySelector('img')
const ratio = window.devicePixelRatio;
canvas.width = 200 * ratio;
canvas.height = 200 * ratio;
// 设置灰度滤镜
ctx.filter = 'grayscale(100%)';
ctx.drawImage(img, 0, 0, 200 * ratio, 200 * ratio)
图片真实像素处理
上面其实都是借助浏览器提供的 api 来进行实现模拟滤镜的功能,那如果我们想要自己去处理图片,我们应该怎么做呢
1. 我们需要先了解,灰度图的构成
在电子计算机领域中,灰阶(Gray scale)数位影像是每个像素只有一个采样颜色的影像。这类影像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以是任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度影像与黑白影像不同,在计算机影像领域中黑白影像只有黑白两种颜色,灰度影像在黑色与白色之间还有许多级的颜色深度。但是,在数字影像领域之外,“黑白影像”也表示“灰度影像”,例如灰度的照片通常叫做“黑白照片”。在一些关于数字影像的文章中**单色影像**等同于灰度影像,在另外一些文章中又等同于黑白影像。
灰度影像经常是在单个电磁波频谱如可见光内测量每个像素的亮度得到的。
用于显示的灰度影像通常用每个采样像素8 bits的非线性尺度来保存,这样可以有256种灰度(8bits就是2的8次方=256)。这种精度刚刚好能够避免可见的条带失真,并且非常易于编程。在医学影像与遥感影像这些技术应用中经常采用更多的级数以充分利用每个采样10或12 bits的传感器精度,并且避免计算时的近似误差。在这样的应用领域流行使用16 bits即65536个组合(或65536种颜色)。
通俗的来说,灰度图就是没有色彩,rgb 三原色全部相等的图,同时灰度图
再 matlab
中,我们可以简单的通过 Gray = 0.2989 * R + 0.5870 * G + 0.1140 * B
这个公式,来计算一个像素点的灰度值,那么我们只需要获取到图片的像素点,然后修改就可以了
2. 获取图片像素点并处理
在 canvas 中 我们可以通过 getImageData
这个方法,很方便的获取到图片的像素点,
然后一次处理所有所有像素点,统一为灰度像素点即可, 代码如下
const canvas2 = document.querySelector('.canvas2')
const ctx2 = canvas2.getContext('2d')
const len = 200 * ratio
canvas2.width = len
canvas2.height = len
ctx2.drawImage(img, 0, 0, len, len)
// 获取图片的像素点 rgba
let weiData = ctx2.getImageData(0, 0, len, len)
let gray = 0;
for (let i = 0; i < (len * len) * 4; i += 4) {
const r = weiData.data[i]
const g = weiData.data[i + 1]
const b = weiData.data[i + 2]
gray = ~~(0.2989 * r + 0.5870 * g + 0.1140 * b )
weiData.data[i] = gray
weiData.data[i + 1] = gray
weiData.data[i + 2 ] = gray
}
ctx2.putImageData(weiData, 0, 0);
这样我们拿到对应的像素点后,就很方便的直接完成处理, 如果想实现其他处理方式,我们只需要获取到对应像素点,处理后然后处理,就可以很方便的完成了。