推荐书: Python开发最佳实践

炫技:用numpy和matplotlib绘制卡通人物

分享时@该用户已经被封, 我就能回答你的问题奥!

这是一个台湾的哥们炫技用的一个作品, 他仅仅使用numpy和matplotlib和一些数学知识就能绘制出一个卡通人脸, 是不是很牛逼。

视频教程

代码

以下代码请在Colab或者jupyter notebook中使用:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import warnings
warnings.filterwarnings('ignore')

def mirror(a):
return a|a[:,::-1]

def edge(a, delta=0):
a = np.float32(a)
while len(a.shape)>2:
a = a.sum(axis=-1)
r = np.zeros(a.shape, dtype=np.bool)
b = (a[2:,1:-1]+a[:-2,1:-1]+a[1:-1,2:]+a[1:-1,:-2])/4
r[1:-1,1:-1]= a[1:-1,1:-1]< b-delta
return r

def rwalk(d=1.2):
a = np.random.normal(0, d, size=(700,1))
b = np.random.randint(0, 20, size=a.shape)>0
a[b]=0
return np.cumsum(a, axis=0)

img_size = (700,600)
y,x = np.indices(img_size)

#@title Default title text { run: "auto", vertical-output: true }
hair_r = 0
hair_r = 0.62 #@param {type:"slider", min:0, max:1, step:0.01}
hair_g = 0.35 #@param {type:"slider", min:0, max:1, step:0.01}
hair_b = 0.31 #@param {type:"slider", min:0, max:1, step:0.01}
show_hair = False #@param {type:"boolean"}
mouth_open = 0 #@param {type:"slider", min:0, max:1, step:0.01}
mouth_smile = 0 #@param {type:"slider", min:-1, max:1, step:0.02}


hair_color = (hair_r, hair_g, hair_b)
img = np.ones(img_size+(3,))*0.8

# head circle
head_circle = (y-250)**2+(x-300)**2 < 200**2 # 圓方程式
img[head_circle]=(1,235/255,223/255)

# jaw
line1 = abs(x-300)+0.35*(y-330)-185 # 直線方程式
line2 = (x-300)+1.7*(y-500)-100 # 直線方程式
line3 = line2[:,::-1]
jaw = line1*line2*line3 < -180000
img[jaw & (y>330) & (line2<0) & (line3<0) ]=(1,235/255,223/255)

#eyebrow
eyebrow1 = (x-245)**2 < (y-220)*150 # 拋物線
eyebrow2 = (x-245)**2 > (y-230)*185 # 拋物線
eyebrow_all = eyebrow1 & eyebrow2 & (y-225-(x-250)>0) # 直線方程式
img[mirror(eyebrow_all)] = (163/255, 138/255, 124/255)

# ear
ear1 = (x-110)+1.3*(y-320) # 直線方程式
ear2 = (y-460)-(x-150) # 直線方程式
ear3 = (y-460) # 直線方程式
ear = ear1 * ear2*ear3 - 100000
ear_all = (ear>0) & (img[:,:,0]==0.8) & (x>50) & (y<460) & (x<300)
img[mirror(ear_all)] = (1,235/255,223/255)

lip1 = 484-15*mouth_open # 上嘴唇中心高度
lip2 = 486+15*mouth_open # 下嘴唇中心高度
lip3 = 480-20*mouth_smile # 嘴角高度
# 嘴角高度固定在 x=300±30 y=lip3 計算拋物線參數
k1 = (lip1 - lip3)/30**2
k2 = (lip2 - lip3)/30**2

mouth1 = (lip1-k1*(x-300)**2 - y) # 拋物線
mouth2 = (lip2-k2*(x-300)**2 - y) # 拋物線
img[ (mouth1<=0) & (mouth2>=0)]=(0.6,0.3,0.3)

# make edges
img[edge(img)] = 0
img[edge(jaw)& (line2<0) & (line3<0) & (y>410)]=0