就在昨天,几乎所有网站都从彩色页面变成黑白页面,虽然一行 CSS 就可以解决这个问题,但是彩色页面(彩色图)变黑白页面(黑白图)有很多方法,主要有三种:最大值法、平均值法、加权平均值法,下面我就主要讲解这三种算法的具体逻辑。
图片数据的格式
在进行图像变换之前,先来简单介绍一下图片在计算机中的数据格式,图像在计算机中的数据格式有很多,详见下表:
格式 | 说明 |
---|---|
1 | 位图,像素 1 位 |
L | 灰度图,像素 8 位 |
I | 像素 int32 |
F | 像素 float32 |
P | 8 位,映射为其他模式 |
RGB | 真色彩,3 通道 |
RGBA | 4 通道,加透明 |
CMYK | 印刷,4 通道 |
YCbCr | 亮色分离,3 通道 |
一般情况下,彩色图在计算机中是通过 RGB 格式来进行存储的,所以今天彩色图变黑白图这个问题就转化为 RGB 格式的图片转 L 格式的图片,在转化之前先来详细说一下这两个格式。
RGB 格式
RGB 格式的 R 表示 Red,G 表示 Green,B 表示 Blue,也就是光的三原色红绿蓝,这三个元素的数据范围都是 0 到 255 的整数,也就是 8 位无符号整数的表示范围,占用一个字节。上面说的只是一个像素点的数据格式,并不是整个 RGB 格式的图片的数据格式,考虑到一张图片有长度有宽度有很多个像素,那么直接把很多像素构成一个二维数组就完事了,又因为一个像素对应着三个元素,这三个元素也可以放在一个数组,所以 RGB 格式的图片在计算机中的存储格式是一个三维数组,其形状为(长, 宽, 3)。
L 格式
L 格式就是灰度格式,每个像素对应一个灰度值,灰度值取值范围依旧是 0 到 255,所以灰度格式的图片在计算机中的存储格式是一个二维数组,其形状为(长, 宽)。
RGB 格式 转 L 格式
RGB 格式转 L 格式在开头就说了有三种方法,分别是:最大值法、平均值法、加权平均值法。在讲解和实现这三个算法之前先给大家看一下我所使用的图片。
最大值法
先来看一下最大值法,最大值法顾名思义就是取 RGB 格式的三个元素当中的最大值作为灰度值,代码如下:
from PIL import Image
import numpy as np
image_array = np.array(Image.open('row_image.jpg'))
# max,average,weighted_average
image_array = np.array(image_array.max(axis=2), dtype='uint8')
image = Image.fromarray(image_array)
image.save('converted_image.jpg')
下面看一下转换之后的图片,如图所示。
平均值法
平均值法就是把 RGB 三个元素的值取平均值作为对应像素的灰度值,代码如下:
from PIL import Image
import numpy as np
image_array = np.array(Image.open('row_image.jpg'))
# max,average,weighted_average
image_array = np.array(image_array.sum(axis=2)//3, dtype='uint8')
image = Image.fromarray(image_array)
image.save('converted_image.jpg')
下面看一下转换之后的图片,如图所示。
加权平均值法
加权平均值法就是给 RGB 三个元素给三个对应的权重,这三个权重暂且记作 WR、WG 和 WB,相乘相加得到灰度图的像素对应取值。在这里考虑到人眼对绿色敏感度最高,红色次之,蓝色最低,所以只要让 WG > WR > WB,即使如此还是有很多取值,目前效果最好的权重参数的值如下表所示。
权重 | 值 |
---|---|
WR | 0.299 |
WG | 0.587 |
WB | 0.114 |
其对应的代码如下:
from PIL import Image
import numpy as np
image_array = np.array(Image.open('row_image.jpg'))
# max,average,weighted_average
a = np.zeros((image_array.shape[0], image_array.shape[1]))
for i in range(image_array.shape[0]):
for j in range(image_array.shape[1]):
a[i, j] = image_array[i, j]@np.array([0.299, 0.587, 0.114])
a = np.array(a, dtype='uint8')
image = Image.fromarray(a)
image.save('converted_image.jpg')
转换后的图片如图所示。
其实加权平均值法在 PIL 中有封装好的,对应逻辑和我自己实现的一模一样,权重都是一样的,调用过程如下:
from PIL import Image
image = Image.open('row_image.jpg')
image = image.convert('L')
image.save('converted_image.jpg')
结果和上面的一样,我就不给大家看了。
本文分享自 Python机器学习算法说书人 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!