在Blender中使用代码控制人物模型的眼部动作 - 睁眼与闭眼
flyfish
眼睛eyeBlink_R闭眼的数值分别是0、0.5、1。而眼睛的纵横比与之相反,眼睛的纵横比越大,眼睛睁的越大。
眼睛的纵横比的计算方法
眼睛的纵横比越大,眼睛睁的越大。
代码实现
关于眼部的关键点在mediapipe中的定义
定义左右眼常量
from enum import Enum
class Eyes(Enum):
LEFT = 1
RIGHT = 2
下面定义的函数都放在FacialFeatures类中
eye_key_indicies=[
[
# Left eye
# eye lower contour
33,
7,
163,
144,
145,
153,
154,
155,
133,
# eye upper contour (excluding corners)
246,
161,
160,
159,
158,
157,
173
],
[
# Right eye
# eye lower contour
263,
249,
390,
373,
374,
380,
381,
382,
362,
# eye upper contour (excluding corners)
466,
388,
387,
386,
385,
384,
398
]
]
根据公式计算眼睛的纵横比
def eye_aspect_ratio(image_points, side):
p1, p2, p3, p4, p5, p6 = 0, 0, 0, 0, 0, 0
if side == Eyes.LEFT:
eye_key_left = FacialFeatures.eye_key_indicies[0]
p2 = np.true_divide(
np.sum([image_points[eye_key_left[10]], image_points[eye_key_left[11]]], axis=0),
2)
p3 = np.true_divide(
np.sum([image_points[eye_key_left[13]], image_points[eye_key_left[14]]], axis=0),
2)
p6 = np.true_divide(
np.sum([image_points[eye_key_left[2]], image_points[eye_key_left[3]]], axis=0),
2)
p5 = np.true_divide(
np.sum([image_points[eye_key_left[5]], image_points[eye_key_left[6]]], axis=0),
2)
p1 = image_points[eye_key_left[0]]
p4 = image_points[eye_key_left[8]]
elif side == Eyes.RIGHT:
eye_key_right = FacialFeatures.eye_key_indicies[1]
p3 = np.true_divide(
np.sum([image_points[eye_key_right[10]], image_points[eye_key_right[11]]], axis=0),
2)
p2 = np.true_divide(
np.sum([image_points[eye_key_right[13]], image_points[eye_key_right[14]]], axis=0),
2)
p5 = np.true_divide(
np.sum([image_points[eye_key_right[2]], image_points[eye_key_right[3]]], axis=0),
2)
p6 = np.true_divide(
np.sum([image_points[eye_key_right[5]], image_points[eye_key_right[6]]], axis=0),
2)
p1 = image_points[eye_key_right[8]]
p4 = image_points[eye_key_right[0]]
eye = np.linalg.norm(p2-p6) + np.linalg.norm(p3-p5)
eye /= (2 * np.linalg.norm(p1-p4) + 1e-6)
return eye
调用eye_aspect_ratio函数
eye_left = FacialFeatures.eye_aspect_ratio(self.image_points, Eyes.LEFT)
eye_right = FacialFeatures.eye_aspect_ratio(self.image_points, Eyes.RIGHT)
关于纵横比的数值如下
结论是
眼睛的纵横比越大,眼睛睁的越大。 1 表示close ,0 表示open
闭眼的数值 close
eyeBlink_L: 0.034907369694056445
eyeBlink_L: 0.02886449999216779
eyeBlink_L: 0.027779683008495676
eyeBlink_L: 0.0296733873711843
eyeBlink_L: 0.025194830756791985
eyeBlink_L: 0.023925703810540076
eyeBlink_L: 0.02362555158269431
eyeBlink_L: 0.024502263712133474
eyeBlink_L: 0.02261911947849663
eyeBlink_L: 0.030179823404591934
eyeBlink_L: 0.02952825209564929
eyeBlink_L: 0.032452940890050824
eyeBlink_L: 0.024476440135416905
睁眼的数值 open
eyeBlink_L: 0.2934850903969735
eyeBlink_L: 0.27661537962019994
eyeBlink_L: 0.27586431888208146
eyeBlink_L: 0.26969061962212526
eyeBlink_L: 0.29001642888895196
eyeBlink_L: 0.28746851414952634
eyeBlink_L: 0.2790754801372039
eyeBlink_L: 0.2734639228995299
eyeBlink_L: 0.280324166145431
eyeBlink_L: 0.29565485858355134
eyeBlink_L: 0.2897504295557396
eyeBlink_L: 0.29699920831651744
根据上述展示的数值定义一个阈值
eye_threshold = 0.2
if eye_left > eye_threshold:
eye_left = 0
else:
eye_left = 1
if eye_right > eye_threshold:
eye_right = 0
else:
eye_right = 1
向模型的形态键赋值
shape_keys['eyeBlink_L'].value = eye_left
shape_keys['eyeBlink_L'].keyframe_insert(data_path='value')
shape_keys['eyeBlink_R'].value = eye_right
shape_keys['eyeBlink_R'].keyframe_insert(data_path='value')