图像的手绘效果
导语
最近在学python数据处理的几个常用库,分别是numpy、matplotlib和pandas。这几个库应该是python数据处理的第三方神器库,学了一招图像手绘风格处理,非常有意思,记录下来。
图像手绘风格
手绘风格示例:
第二幅就是有手绘的感觉,当然是基于第一章图片处理得到的。手绘风格可以总结为以下几点:
- 黑白灰色
- 边界线条较重
- 相邻的像素,如果是相同或者相近色彩趋于白色
- 略有光源效果
具体如何通过程序实现呢?接下来就来逐一介绍下。
梯度的重构
利用像素之间的梯度值和虚拟深度值对图像进行重构,根据灰度变换来模拟人类视觉的明暗程度。代码如下:
import numpy as np
from PIL import Image
a = np.asarray(Image.open('xxx.jpeg').convert('L')).astype('float')
depth = 10.
grad = np.gradient(a)
grad_x, grad_y = grad
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
下面这行代码是通过pillow库读取原先图像,RGB值转为灰度值。
a = np.asarray(Image.open('xxx.jpeg').convert('L')).astype('float')
这几行代码是计算灰度图像的像素间梯度,并且根据虚拟深度重构梯度值,depth初始化为10,depth取值0~100。
depth = 10.
grad = np.gradient(a)
grad_x, grad_y = grad
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
光源效果
根据灰度变化来模拟人类视觉的远近程度。
- 设计一个位于图像斜上方的虚拟光源
- 光源相对于图像的俯视角为Elevation,方位角为Azimuth
- 建立光源对各个点梯度值的影响函数
- 运算各个点的新像素值
代码如下:
vec_el = np.pi/2.2 # 光源的俯视角度,弧度值
vec_az = np.pi/4. # 光源的方位角度,弧度值
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轴的影响
A = np.sqrt(grad_x**2 + grad_y**2 + 1.) # 光源归一化
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A
b = 255*(dx*uni_x+dy*uni_y+dz*uni_z)
最后,对像素值进行裁剪至0~255,防止越界。
b = b.clip(0, 255)
im = Image.fromarray(b.astype('uint8'))
im.save('xxxHD.jpeg')
最后
程序虽然小,效果还是比较有意思的,我给女儿看了,她说你画画不是很丑的吗,为啥画的这么好?哈哈,我和她说,这是计算机处理的,不是我手画的,小小的年纪充满大大的问号。
其实,这里最重要的是对图像灰度值计算梯度,这是Computer Vision里面传统图像处理的关键,CV相关的技术,由于可以可视化,实现之后,还是比较有意思的。