Setup a feature to allow the use of EmilianaVT's featureExtracotor

will need to test it, it seems to work better than I rememebr, if it keeps working that good I might juse make it the default
This commit is contained in:
Cowwan 2024-02-06 09:53:08 -05:00
parent 18b7c03cc6
commit 76390857f8
6 changed files with 56 additions and 23 deletions

View file

@ -1,22 +1,39 @@
import numpy as np
import time
import math
import emilianaFeature
def angle(p1, p2):
p1 = np.array(p1)
p2 = np.array(p2)
a = np.arctan2(*(p2 - p1)[::-1])
return (a % (2 * np.pi))
def rotate(origin, point, a):
a = -a
ox, oy = origin
px, py = point
qx = ox + math.cos(a) * (px - ox) - math.sin(a) * (py - oy)
qy = oy + math.sin(a) * (px - ox) + math.cos(a) * (py - oy)
return qx, qy
class FeatureExtractor():
def __init__(self, max_feature_updates=0):
self.eye_l = Feature(max_feature_updates=max_feature_updates)
self.eye_r = Feature(max_feature_updates=max_feature_updates)
self.eyebrow_updown_l = Feature(max_feature_updates=max_feature_updates)
self.eyebrow_updown_r = Feature(max_feature_updates=max_feature_updates)
self.eyebrow_quirk_l = Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_quirk_r = Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_steepness_l = Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_steepness_r = Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.mouth_corner_updown_l = Feature(max_feature_updates=max_feature_updates)
self.mouth_corner_updown_r = Feature(max_feature_updates=max_feature_updates)
self.mouth_corner_inout_l = Feature(threshold=0.02, max_feature_updates=max_feature_updates)
self.mouth_corner_inout_r = Feature(threshold=0.02, max_feature_updates=max_feature_updates)
self.mouth_open = Feature(max_feature_updates=max_feature_updates)
self.mouth_wide = Feature(threshold=0.02, max_feature_updates=max_feature_updates)
self.eye_l = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.eye_r = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.eyebrow_updown_l = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.eyebrow_updown_r = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.eyebrow_quirk_l = emilianaFeature.Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_quirk_r = emilianaFeature.Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_steepness_l = emilianaFeature.Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.eyebrow_steepness_r = emilianaFeature.Feature(threshold=0.05, max_feature_updates=max_feature_updates)
self.mouth_corner_updown_l = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.mouth_corner_updown_r = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.mouth_corner_inout_l = emilianaFeature.Feature(threshold=0.02, max_feature_updates=max_feature_updates)
self.mouth_corner_inout_r = emilianaFeature.Feature(threshold=0.02, max_feature_updates=max_feature_updates)
self.mouth_open = emilianaFeature.Feature(max_feature_updates=max_feature_updates)
self.mouth_wide = emilianaFeature.Feature(threshold=0.02, max_feature_updates=max_feature_updates)
def align_points(self, a, b, pts):
a = tuple(a)

14
face.py
View file

@ -1,9 +1,11 @@
import numpy as np
import math
import featureExtractor
import emilianaFeatureExtractor
class FaceInfo():
def __init__(self, id, tracker):
def __init__(self, id, tracker, featureType):
self.featureType = featureType
self.id = id
self.tracker = tracker
self.face_3d = np.array([
@ -100,7 +102,11 @@ class FaceInfo():
self.pts_3d = None
self.eye_blink = None
self.pnp_error = 0
self.features = featureExtractor.FeatureExtractor()
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()
@ -140,4 +146,6 @@ class FaceInfo():
self.pts_3d = self.normalize_pts3d(self.pts_3d)
self.current_features = self.features.update(self.pts_3d[:, 0:2])
self.eye_blink = [self.current_features["eye_r"],self.current_features["eye_l"] ]
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))

View file

@ -31,6 +31,8 @@ parser.add_argument("-d", "--detection-threshold", type=float, help="Set minimum
parser.add_argument("-s", "--silent", type=int, help="Set this to 1 to prevent text output on the console", default=0)
parser.add_argument("--model", type=int, help="This can be used to select the tracking model. Higher numbers are models with better tracking quality, but slower speed, except for model 4, which is wink optimized.", default=3, choices=[0, 1, 2, 3, 4])
parser.add_argument("--preview", type=int, help="Preview the frames sent to the tracker", default=0)
parser.add_argument("--feature-type", type=int, help="Sets which version of feature extraction is used. 0 is my new version that works well for me and allows for some customization, 1 is EmilianaVT's version aka, normal OpenSeeFace operation", default=0, choices=[0, 1])
args = parser.parse_args()
@ -48,6 +50,7 @@ height = args.height
width = args.width
previewFlag = (args.preview == 1)
mirror_input = args.mirror_input
featureType = args.feature_type
#I make a minor tweak to the framerate to help the camera out
#it's an inpercetible amount of time per frame
@ -110,7 +113,7 @@ peak_camera_latency = 0.0
total_camera_latency = 0.0
failures = 0
tracker = Tracker(width, height, messageQueue, threshold=args.threshold, silent=silent, model_type=args.model, detection_threshold=args.detection_threshold)
tracker = Tracker(width, height, messageQueue, featureType, threshold=args.threshold, silent=silent, model_type=args.model, detection_threshold=args.detection_threshold)
#don't start until the webcam is ready
while frameQueue.qsize() < 1:

View file

@ -77,10 +77,10 @@ class FeatureExtractor():
f_pts = self.align_points(pts[42], pts[45], pts[[43, 44, 47, 46]])
f = (f_pts[0][1]/2 + f_pts[1][1]/2) - (f_pts[2][1]/2 + f_pts[3][1]/2)
features["eye_l"] = self.eye_l.update(f)
features["eye_l"] = -self.eye_l.update(f)
f_pts = self.align_points(pts[36], pts[39], pts[[37, 38, 41, 40]])
f = (f_pts[0][1]/2 + f_pts[1][1]/2) - (f_pts[2][1]/2 + f_pts[3][1]/2)
features["eye_r"] = self.eye_r.update(f)
features["eye_r"] = -self.eye_r.update(f)
f = ((pts[22][1]/2 + pts[26][1]/2) - (pts[42][1]/2 + pts[45][1]/2))/norm_distance_y
features["eyebrow_updown_l"] = self.eyebrow_updown_l.update(f)

View file

@ -6,6 +6,7 @@ import eyes
import landmarks
import face
import featureExtractor
import emilianaFeatureExtractor
#this file is so much smaller than it used to be, lol
@ -33,12 +34,16 @@ def clamp_to_im(pt, w, h): #8 times per frame, but that only accounts for 0.005m
return (int(x),int(y+1))
class Tracker():
def __init__(self, width, height, messageQueue, model_type=3, detection_threshold=0.6, threshold=0.6, silent=False):
def __init__(self, width, height, messageQueue, featureType, model_type=3, detection_threshold=0.6, threshold=0.6, silent=False):
self.FaceDetector = facedetection.FaceDetector(detection_threshold = detection_threshold)
self.EyeTracker = eyes.EyeTracker()
self.Landmarks = landmarks.Landmarks(width, height, model_type, threshold)
self.FeatureExtractor = featureExtractor.FeatureExtractor()
if featureType == 0:
self.FeatureExtractor = featureExtractor.FeatureExtractor()
else:
self.FeatureExtractor = emilianaFeatureExtractor.FeatureExtractor()
# Image normalization constants
self.mean = np.float32(np.array([-2.1179, -2.0357, -1.8044]))
@ -52,7 +57,7 @@ class Tracker():
self.threshold = threshold
self.faces = []
self.face_info = [face.FaceInfo(0, self)]
self.face_info = [face.FaceInfo(0, self, featureType)]
self.messageQueue = messageQueue
def preprocess(self, im):