图像的数组表示:
PIL库,Python Image Library (mac命令行下载该第三方库的命令:pip3 install pillow , 如果没用,可以在该命令后面加--user)
from PIL import Image (图像类)
图像用ndarray的三维数组表示: 高度、宽度、RBG值
图像变换:
例1:将图像变为补色保存:
通过修改每个像素的rgb的值,将每个像素的颜色改为对应的补色。
原图:
修改后的图片:
例2:照片灰度变换
convert函数:下面代码convert('L') 将原图片改为一个灰度值的图片,则生成的图片数组并非三维数组,而变成二维数组,其中每一个元素并不对应一个rgb值,而是对应灰度值。(convert详解可参考:https://blog.csdn.net/icamera0/article/details/50843172)
输入的图片:
输出的图片则变成了老照片一样的黑白画面:
例三:输出浅灰度值的图片
由例二的输出可以看出,当前的灰度值太高,接近于黑,可以适当调整参数降低灰度值。将当前元素的灰度值进行区间压缩,再扩充区间范围,使灰度的透明度变低。
输出的图片如下:明显灰度减少了很多。
同理,如果需要灰度继续加深,可以扩大c的值(比如平方)。
总结:这三变换都只改变了中间那一行图像数组的值,通过改变数组的元素值,可以实现所有的图像色彩变换。
手绘效果的生成:
手绘效果是在灰度化的基础上由立体效果和明暗效果叠加而成。
手绘效果的特点:
- 一般都是灰色系的
- 在边界上的线条比较重
- 相同或相近色偏白色
- 略有光源效果
方法:
- 梯度的重构
梯度值:明暗的变化率 图像数组的梯度可以通过numpy中的gradient()函数获取。
2. 光源效果:
3. 梯度和光源的归一化:
源代码如下:
from PIL import Image
import numpy as np
a = np.asarray(Image.open("/Users/sijiahoe/Downloads/IMG_20200605_190915.jpg").convert('L')).astype('float')
depth = 10. # 虚拟深度值 (0-100)
grad = np.gradient(a) # 读取图像灰度的梯度值
grad_x, grad_y = grad # 分别取横纵图像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.) # 梯度归一化
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A
vec_el = np.pi/2.2 # 光源的俯视角度,弧度值
vec_az = np.pi/4. # 光源的方位角度,弧度值
# np.cos(vec_az)为单位光线在平面上的投影长度
dx = np.cos(vec_el)*np.cos(vec_az) # 光源对x轴的影响
dy = np.cos(vec_el)*np.sin(vec_az) # 光源对y 轴的影响
dz = np.sin(vec_el) #光源对z 轴的影响
b = 255*(dx*uni_x + dy*uni_y + dz*uni_z) # 光源和梯度相互作用,将梯度转化为灰度
b = b.clip(0,255) # 为避免数组越界,将生成的灰度截取在0-255内
im = Image.fromarray(b.astype('uint8')) #重构图像
im.save('/Users/sijiahoe/Downloads/handDraw.jpg)
测试原图:
输出的图片:
(此生成的图像灰度和对比度较低,可以通过调节相关参数改进)
全文所有内容非原创,转载链接如下。