图像是有规律的二维数据,利用numpy库可以将图像转换为数组对象,那我们又知道图像也是由很多很多的像素点构成,那我们如果操作这些像素点,对其转变,是不是可以改变这个图像呢?没错,下面我分享一下如何操作。
__________________________________________________________
如果安装numpy函数库遇到问题建议用清华镜像安装
__________________________________________________________
本次测试图:
效果图:
因为这次要用到numpy库和image库,由于这二个库的知识点有点多,我就不做介绍,在这里只讲需要的函数,达到这个效果就好
image中:
函数名 | 作用 |
---|---|
Image.open() | 打开图片 转换为image类 |
Image.show() | 显示图片 |
convert() | 操作对象是Image类 一般转换’L’模式即灰度,图像将由彩色变成带有灰度的黑白色 |
Image.fromarray() | 可以将像素点重新转换成图像 |
Image.save() | 保存图片 |
numpy中:
函数名 | 作用 |
---|---|
np.asarray() | 将数据类型转换为ndarray类型 但不会复制该对象 |
np.astype() | 改变数据类型 |
np.gradient() | 直接提取灰度图像梯度 |
np.cos() | 内置的cos函数 |
np.sin() | 内置的sin函数 |
np.pi | 内置的圆周率 |
np.sqrt() | 内置的开方函数 |
clip() | 防止溢出,参数为元组 |
# -*- coding : utf-8 -*-
# @Time : 2020/3/20 13:55
# @author : 沙漏在下雨
# @Software : PyCharm
import numpy as np
from PIL import Image
def main():
vec_fu = np.pi / 2.2 # 光源的俯视角,弧度
vec_fa = np.pi / 4.0 # 光源的方位角,弧度
depth = 20.0 # 深度权值 越大 背景颜色越深
im = Image.open("D://py词云//lol.jpg").convert('L') # 打开并转换为灰度
am = np.asarray(im).astype('float') # 图片转换为数组, 类型转换为单精度
tm = np.gradient(am) # 获取图像灰度的梯度值 是一个元组类型
tm_x, tm_y = tm # 将梯度值分别赋值
tm_x = tm_x * depth / 100 # x轴 y轴 梯度变化
tm_y = tm_y * depth / 100 # 得到x轴 和y轴的 总梯度值
dx = np.cos(vec_fu) * np.sin(vec_fa)
dy = np.cos(vec_fu) * np.sin(vec_fa)
dz = np.sin(vec_fu) # 光源对x y z 轴的 加权向量
a = np.sqrt(tm_x ** 2 + tm_y ** 2 + 1.0) # 梯度幅值
uni_x = tm_x / a # x轴每个像素单元的梯度值
uni_y = tm_y / a # y轴每个像素单元的梯度值
uni_z = 1.0 / a # z轴每个像素单元的梯度值
a2 = 255 * (dx * uni_x + dy * uni_y + dz * uni_z) # 合成灰度值
a2 = a2.clip(0, 255) # 灰度值保持在0,255 防止溢出
im2 = Image.fromarray(a2.astype('uint8')) # 重构图像
im2.save("D://py词云//lol_draw.jpg") # 保存展示
im2.show()
if __name__ == '__main__':
main()
思路:我们利用numpy中的gradient()这个函数提取灰色图像的梯度,然后对梯度值进行操作,重构每个像素值,我们加了一个光源,建立了光源对各点梯度值的函数,进行新的运算,最后重构图像。说实话,这里确实很难理解,涉及到了三维空间映射,对数学的要求有点,觉得好玩就直接copy就行。