149 lines
7.7 KiB
Python
149 lines
7.7 KiB
Python
import numpy as np
|
|
import math
|
|
import featureExtractor
|
|
import emilianaFeatureExtractor
|
|
|
|
class FaceInfo():
|
|
def __init__(self, featureType):
|
|
self.featureType = featureType
|
|
self.face_3d = np.array([
|
|
[ 0.4551769692672 , 0.300895790030204, -0.764429433974752],
|
|
[ 0.448998827123556, 0.166995837790733, -0.765143004071253],
|
|
[ 0.437431554952677, 0.022655479179981, -0.739267175112735],
|
|
[ 0.415033422928434, -0.088941454648772, -0.747947437846473],
|
|
[ 0.389123587370091, -0.232380029794684, -0.704788385327458],
|
|
[ 0.334630113904382, -0.361265387599081, -0.615587579236862],
|
|
[ 0.263725112132858, -0.460009725616771, -0.491479221041573],
|
|
[ 0.16241621322721 , -0.558037146073869, -0.339445180872282],
|
|
[ 0. , -0.621079019321682, -0.287294770748887],
|
|
[-0.16241621322721 , -0.558037146073869, -0.339445180872282],
|
|
[-0.263725112132858, -0.460009725616771, -0.491479221041573],
|
|
[-0.334630113904382, -0.361265387599081, -0.615587579236862],
|
|
[-0.389123587370091, -0.232380029794684, -0.704788385327458],
|
|
[-0.415033422928434, -0.088941454648772, -0.747947437846473],
|
|
[-0.437431554952677, 0.022655479179981, -0.739267175112735],
|
|
[-0.448998827123556, 0.166995837790733, -0.765143004071253],
|
|
[-0.4551769692672 , 0.300895790030204, -0.764429433974752],
|
|
[ 0.385529968662985, 0.402800553948697, -0.310031082540741],
|
|
[ 0.322196658344302, 0.464439136821772, -0.250558059367669],
|
|
[ 0.25409760441282 , 0.46420381416882 , -0.208177722146526],
|
|
[ 0.186875436782135, 0.44706071961879 , -0.145299823706503],
|
|
[ 0.120880983543622, 0.423566314072968, -0.110757158774771],
|
|
[-0.120880983543622, 0.423566314072968, -0.110757158774771],
|
|
[-0.186875436782135, 0.44706071961879 , -0.145299823706503],
|
|
[-0.25409760441282 , 0.46420381416882 , -0.208177722146526],
|
|
[-0.322196658344302, 0.464439136821772, -0.250558059367669],
|
|
[-0.385529968662985, 0.402800553948697, -0.310031082540741],
|
|
[ 0. , 0.293332603215811, -0.137582088779393],
|
|
[ 0. , 0.194828701837823, -0.069158109325951],
|
|
[ 0. , 0.103844017393155, -0.009151819844964],
|
|
[ 0. , 0. , 0. ],
|
|
[ 0.080626352317973, -0.041276068128093, -0.134161035564826],
|
|
[ 0.046439347377934, -0.057675223874769, -0.102990627164664],
|
|
[ 0. , -0.068753126205604, -0.090545348482397],
|
|
[-0.046439347377934, -0.057675223874769, -0.102990627164664],
|
|
[-0.080626352317973, -0.041276068128093, -0.134161035564826],
|
|
[ 0.315905195966084, 0.298337502555443, -0.285107407636464],
|
|
[ 0.275252345439353, 0.312721904921771, -0.244558251170671],
|
|
[ 0.176394511553111, 0.311907184376107, -0.219205360345231],
|
|
[ 0.131229723798772, 0.284447361805627, -0.234239149487417],
|
|
[ 0.184124948330084, 0.260179585304867, -0.226590776513707],
|
|
[ 0.279433549294448, 0.267363071770222, -0.248441437111633],
|
|
[-0.131229723798772, 0.284447361805627, -0.234239149487417],
|
|
[-0.176394511553111, 0.311907184376107, -0.219205360345231],
|
|
[-0.275252345439353, 0.312721904921771, -0.244558251170671],
|
|
[-0.315905195966084, 0.298337502555443, -0.285107407636464],
|
|
[-0.279433549294448, 0.267363071770222, -0.248441437111633],
|
|
[-0.184124948330084, 0.260179585304867, -0.226590776513707],
|
|
[ 0.121155252430729, -0.208988660580347, -0.160606287940521],
|
|
[ 0.041356305910044, -0.194484199722098, -0.096159882202821],
|
|
[ 0. , -0.205180167345702, -0.083299217789729],
|
|
[-0.041356305910044, -0.194484199722098, -0.096159882202821],
|
|
[-0.121155252430729, -0.208988660580347, -0.160606287940521],
|
|
[-0.132325402795928, -0.290857984604968, -0.187067868218105],
|
|
[-0.064137791831655, -0.325377847425684, -0.158924039726607],
|
|
[ 0. , -0.343742581679188, -0.113925986025684],
|
|
[ 0.064137791831655, -0.325377847425684, -0.158924039726607],
|
|
[ 0.132325402795928, -0.290857984604968, -0.187067868218105],
|
|
[ 0.181481567104525, -0.243239316141725, -0.231284988892766],
|
|
[ 0.083999507750469, -0.239717753728704, -0.155256465640701],
|
|
[ 0. , -0.256058040176369, -0.0950619498899 ],
|
|
[-0.083999507750469, -0.239717753728704, -0.155256465640701],
|
|
[-0.181481567104525, -0.243239316141725, -0.231284988892766],
|
|
[-0.074036069749345, -0.250689938345682, -0.177346470406188],
|
|
[ 0. , -0.264945854681568, -0.112349967428413],
|
|
[ 0.074036069749345, -0.250689938345682, -0.177346470406188],
|
|
# Pupils and eyeball centers
|
|
[ 0.257990002632141, 0.276080012321472, -0.219998998939991],
|
|
[-0.257990002632141, 0.276080012321472, -0.219998998939991],
|
|
[ 0.257990002632141, 0.276080012321472, -0.324570998549461],
|
|
[-0.257990002632141, 0.276080012321472, -0.324570998549461]
|
|
], np.float32)
|
|
|
|
|
|
self.reset()
|
|
self.alive = False
|
|
self.coord = None
|
|
self.base_scale_v = self.face_3d[27:30, 1] - self.face_3d[28:31, 1]
|
|
self.base_scale_h = np.abs(self.face_3d[[0, 36, 42], 0] - self.face_3d[[16, 39, 45], 0])
|
|
|
|
def reset(self):
|
|
self.alive = False
|
|
self.conf = None
|
|
self.lms = None
|
|
self.eye_state = None
|
|
self.rotation = np.array([0.0, 0.0, 0.0], np.float32)
|
|
self.translation = np.array([0.0, 0.0, 0.0], np.float32)
|
|
self.success = None
|
|
self.quaternion = None
|
|
self.euler = None
|
|
self.pts_3d = None
|
|
self.eye_blink = None
|
|
self.pnp_error = 0
|
|
if self.featureType == 0:
|
|
self.features = featureExtractor.FeatureExtractor()
|
|
else:
|
|
self.features = emilianaFeatureExtractor.FeatureExtractor()
|
|
|
|
self.current_features = {}
|
|
self.contour = np.zeros((21,3))
|
|
self.update_contour()
|
|
|
|
def update(self, result, coord):
|
|
if result is None:
|
|
self.reset()
|
|
else:
|
|
self.conf, (self.lms, self.eye_state) = result
|
|
self.coord = coord
|
|
self.alive = True
|
|
|
|
def update_contour(self):
|
|
self.contour = self.face_3d[[0,1,8,15,16,27,28,29,30,31,32,33,34,35]]
|
|
|
|
def normalize_pts3d(self, pts_3d):
|
|
# Calculate angle using nose
|
|
pts_3d[:, 0:2] -= pts_3d[30, 0:2]
|
|
alpha = (math.atan2(*((pts_3d[27, 0:2]) - pts_3d[30, 0:2])[::-1]) % (2*math.pi))
|
|
cosalpha = math.cos(alpha-(math.pi/2))
|
|
sinalpha = math.sin(alpha-(math.pi/2))
|
|
|
|
R = np.matrix([[cosalpha, -sinalpha], [sinalpha, cosalpha]])
|
|
pts_3d[:, 0:2] = (pts_3d - pts_3d[30])[:, 0:2].dot(R) + pts_3d[30, 0:2]
|
|
|
|
# Vertical scale
|
|
pts_3d[:, 1] /= np.mean((pts_3d[27:30, 1] - pts_3d[28:31, 1]) / self.base_scale_v)
|
|
|
|
# Horizontal scale
|
|
pts_3d[:, 0] /= np.mean(np.abs(pts_3d[[0, 36, 42], 0] - pts_3d[[16, 39, 45], 0]) / self.base_scale_h)
|
|
|
|
return pts_3d
|
|
|
|
def adjust_3d(self):
|
|
if self.conf < 0.4 or self.pnp_error > 300:
|
|
return
|
|
|
|
self.pts_3d = self.normalize_pts3d(self.pts_3d)
|
|
self.current_features = self.features.update(self.pts_3d[:, 0:2])
|
|
self.eye_blink = []
|
|
self.eye_blink.append(1 - min(max(0, -self.current_features["eye_r"]), 1))
|
|
self.eye_blink.append(1 - min(max(0, -self.current_features["eye_l"]), 1))
|