3.图像的手绘风格

本文最后更新于:2022年6月19日 下午

RGB色彩模式

图像一般使用RGB色彩模式,即每个像素点的颜色由红、绿、蓝组成,RGB三个颜色通道的变化和叠加得到各种颜色,其中每种颜色的取值范围都是0-255,RGB形成的颜色包括了人类视力所能感知的所有颜色。

PIL库

PIL,Python Image Library,是一个具有强大图像处理能力的第三方库,使用pip install pillow安装PIL库。

我们可以使用from PIL import Image调用PIL库的Image类,Image是PIL库中代表一个图像的类(对象)。

图像的数组表示

图像时一个由像素组成的二维矩阵,每个元素是一个RGB值。

1
2
3
4
im=np.array(Image.open("D:/image/wallpaper/62f1481863a6757ab665044b7606fb22.png"))

print(im.shape,im.dtype)
(2960, 1440, 4) uint8 # 2960代表图像的高度,1440是宽度,4是像素的颜色值,如果是RGB为3

使用spyder可以很方便的对数组进行修改,甚至可以直接修改图片的像素点。

图像的变换

大致流程:读入图像后,获得像素RGB值,修改后保存为新的文件

1
2
3
4
5
6
7
8
9
10
from PIL import Image
import numpy as np
a=np.array(Image.open("D:/image/wallpaper/62f1481863a6757ab665044b7606fb22.png"))

print(im.shape,im.dtype)
(2960, 1440, 4) uint8

b=[255,255,255,255]-a
im=Image.fromarray(b.astyle('uint8'))
im.save('C:/Users/shinelon/Downloads/test.png')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
a=np.array(Image.open("D:/image/wallpaper/1c12ee47091e23e8ac89238d7c5bc1c3.jpg").convert('L'))  # convert函数将rgb值变成灰度值,只有两个维度

print(a.shape,a.dtype)
(3840, 2160) uint8

b=255-a

im=Image.fromarray(b.astype('uint8')) # 用255-a(灰度值),也就是补色

im.save("C:/Users/shinelon/Downloads/test.jpg")

im=Image.fromarray(a.astype('uint8'))

im.save('C:/Users/shinelon/Downloads/test1.jpg')

c=(100/255)*a+150 # 进行区间变换,降低rgb的颜色变成原来的100/255+150

im=Image.fromarray(c.astype('uint8'))

im.save('C:/Users/shinelon/Downloads/test2.jpg')


d=255*(a/255)**2 # 进行像素平方

im=Image.fromarray(d.astype('uint8'))

im.save('C:/Users/shinelon/Downloads/test.jpg')

test

test1

test2

test

## 图像的手绘效果

  • 黑白灰色
  • 边界线条较重
  • 相同或相近色彩趋于白色
  • 略有光源效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from PIL import Image
import numpy as np

a = np.asarray(Image.open("D:/image/wallpaper/1c12ee47091e23e8ac89238d7c5bc1c3.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.) # 将灰度归一化,构造x和y轴梯度的三维归一化单位坐标系
#
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

# 光源效果
# el也就是俯视角Elevation,az也就是Azimuth方位角
vec_el = np.pi/2.2 # 光源的俯视角度,弧度值
vec_az = np.pi/4. # 光源的方位角度,弧度值
# np.cos(vec_el)为单位光线在地平面上的投影长度
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) # 设置RGB值不超过2

im = Image.fromarray(b.astype('uint8')) #重构图像
im.save('C:/Users/shinelon/Downloads/test3.jpg')

test3