关于Numpy处理图像和提取图像色位:照片加滤镜的Python方案

关于Numpy处理图像和提取图像色位,我首先是参考了如下的b站视频。
一个10分钟的numpy入门教程(bilibili)
视频中说图像是RGB三个色位,但是我按照Mac微信截图得到的png图像却是有4个色位。经探究,前三个色位分别代表红R、绿G、蓝B。第四个色位代表透明度,从0(完全透明)到255(完全不透明)。
如果缺少第四个色位,那么默认会将透明度设为255。
导入图像并将其转化为ndarray矩阵对象的代码为

from PIL import Image
import numpy as np
impho = Image.open('/Users/mac/Documents/photo.png')
im = np.array(impho)
print(type(impho))
print(type(im))
print(im.shape)

输出为

<class 'PIL.PngImagePlugin.PngImageFile'>
<class 'numpy.ndarray'>
(670, 1004, 4)

这说明imphoPngImageFile型的对象,而imndarray型的对象。
此外,im有3个维度,其中第3个维度有4个色位。
通过代码

Image.fromarray(im).show()

展示出原始图片如下,这是某大学食堂的照片。

原始图片

因为第四个色位,即透明度是我们基本不需要用的,所以通过

im = np.delete(im, -1, axis=2)

将第四个色位删除。
按道理,这时采用

im_r = im[:, :, [0, 1]]
Image.fromarray(im_r).show()

即可绘制出仅含红R、绿G的图像,但是绘制的结果为

在这里插入图片描述
并不是彩色的,而是黑白的图像。
我认为Python在绘制PngImageFile类型的图像时,如果色位小于2,他便不会绘制出彩色的图像。
为了得到彩色的仅含红R、绿G的图像,我们进行如下处理

im = np.insert(im, 3, values=0, axis=2)

首先,这一句的作用是增加了第四个色位,值全为0。但是我们不将其理解为透明度。虽然放在第四个色位就是透明度,但是这里我们仅仅是借用其作为一个工具。
接下来再运用代码

im_r = im[:, :, [0, 1, 3]]
Image.fromarray(im_r).show()

绘制出的图像为:

在这里插入图片描述

这就完美的提取出了红R、绿G的图像。在这里,我们仅仅把值全为0的第四个色位替代了第三个色位,即蓝B色位。这样PngImageFile类型的对象色位数已经达到了3,于是便能够绘制出彩色图像。
上述绘图处理完整的代码为

from PIL import Image
import numpy as np
impho = Image.open('/Users/mac/Documents/photo.png')
im = np.array(impho)
im = np.delete(im, -1, axis=2)
im = np.insert(im, 3, values=255, axis=2)
im_r = im[:, :, [0, 1, 3]]
Image.fromarray(im_r).show()

类似的,我们可以绘制红R、绿G、蓝B中任一个,或任两个组合的彩色图像,只需要改变定义im_r的那一句。
注意,在定义im_r的那一句当中,三个色位的顺序是值得小心的。
红绿组合:

im_r = im[:, :, [0, 1, 3]]

红蓝组合:

im_r = im[:, :, [0, 3, 2]]

绿蓝组合:

im_r = im[:, :, [3, 1, 2]]

红色图像:

im_r = im[:, :, [0, 3, 3]]

绿色图像:

im_r = im[:, :, [3, 1, 3]]

蓝色图像:

im_r = im[:, :, [3, 3, 2]] 

在这里插入图片描述

对上述代码进行了推广,希望对于任意权重的红R、绿G、蓝B,都能够绘制出加工后的图像,于是给出了下述代码。

from PIL import Image
import numpy as np
impho = Image.open('/Users/mac/Documents/photo.png')
im = np.array(impho)
im = np.delete(im, -1, axis=2)
weight1 = input("请输入红R的权重:")
weight2 = input("请输入绿G的权重:")
weight3 = input("请输入蓝B的权重:")
weight1 = np.array(weight1,dtype="float64")
weight2 = np.array(weight2,dtype="float64")
weight3 = np.array(weight3,dtype="float64")
im1 = im[:, :, 0].astype("float64")
im2 = im[:, :, 1].astype("float64")
im3 = im[:, :, 2].astype("float64")
Red = np.around(weight1*im1).astype("uint8")
Green = np.around(weight2*im2).astype("uint8")
Blue = np.around(weight2*im2).astype("uint8")
im = np.insert(im, 3, values=Red, axis=2)
im = np.insert(im, 4, values=Green, axis=2)
im = np.insert(im, 5, values=Blue, axis=2)
im_r = im[:, :, [3,4,5]]
Image.fromarray(im_r).show()

这个代码修修改改了很多遍。首先,input得到的数据类型dtype"<U3",而构建图片需要的数据类型为"uint8"。这就需要进行转化,否则无法进行相乘操作。但是"uint8"类型必然是整数,而input类型的数只能是0至1之间的数,不能直接将其数据类型转化为"uint8",否则失去了权重的意义。
而基于位图的数据类型为"uint8"的整型,所以无可奈何这里的权重也要进行取整处理,这是有误差的。

运行上述代码,我们以

请输入红R的权重:0.8
请输入绿G的权重:0.9
请输入蓝B的权重:0.2

为例,得出的图像为

在这里插入图片描述

有一点复古怀旧滤镜的感觉。
看起来,以后在给照片加滤镜的时候,也可以借助Python完成。

2022年10月3日于北京

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值