From b663b6d49549ad5b2b90aa6f55a3d6ed1705a7e8 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Mon, 30 May 2022 18:32:31 -0700 Subject: [PATCH] First version of the script. --- .gitignore | 4 ++++ face_track.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ shell.nix | 26 +++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 .gitignore create mode 100755 face_track.py create mode 100644 shell.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..91c8e15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.mdd +*.blend +*.blend? +videos diff --git a/face_track.py b/face_track.py new file mode 100755 index 0000000..e8f5df1 --- /dev/null +++ b/face_track.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 + +from struct import pack +import numpy as np +import cv2 as cv +import mediapipe as mp + +if __name__ == "__main__": + mp_face_mesh = mp.solutions.face_mesh + + # Compute the mesh points. One mesh per frame. + meshes = [] + point_count = 0 + aspect_ratio = 1.0 + with mp_face_mesh.FaceMesh( + static_image_mode=False, # Set false for video. + max_num_faces=1, + refine_landmarks=True, + min_detection_confidence=0.5) as face_mesh: + + i = 1 + cap = cv.VideoCapture("videos/BDGFACE 5_12.mp4") + while cap.isOpened(): + print("\rReading frame", i, end = "") + ret, image = cap.read() + if not ret: + break + + aspect_ratio = image.shape[1] / image.shape[0] + results = face_mesh.process(cv.cvtColor(image, cv.COLOR_BGR2RGB)) + if not results.multi_face_landmarks: + meshes += [None] + else: + point_count = len(results.multi_face_landmarks[0].landmark) + meshes += [results.multi_face_landmarks[0].landmark] + + i += 1 + cap.release() + print("\rRead {} frames. ".format(len(meshes))) + + # Write the mdd file. + fps = 24.0 # TODO: get this from the video file. + frame_count = len(meshes) + if frame_count > 0: + with open("test.mdd", 'wb') as mdd: + print("Vert count:", point_count) + + mdd.write(pack(">2i", frame_count, point_count)) + mdd.write(pack(">%df" % (frame_count), *[frame / fps for frame in range(frame_count)])) + + i = 1 + for mesh in meshes: + print("\rWriting frame", i, end = "") + if mesh is None: + # Put all vertices at the origin for bogus frames. + for n in range(point_count): + mdd.write(pack(">3f", 0.0, 0.0, 0.0)) + else: + for point in mesh: + mdd.write(pack(">3f", point.x, point.y / aspect_ratio, point.z)) + i += 1 + print() + diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..0012f19 --- /dev/null +++ b/shell.nix @@ -0,0 +1,26 @@ +let + # You can replace "unstable" with any channel name to use that channel. + pkgs = import {}; + pypkgs = pkgs.python310Packages; + name = "face_track_dev_env"; +in pkgs.stdenv.mkDerivation { + inherit name; + nativeBuildInputs = with pkgs; [ + pypkgs.python + pypkgs.pip + pypkgs.numpy + pypkgs.opencv4 + pypkgs.dlib + ]; + + shellHook = with pkgs; '' + export PYTHON_LIBRARY="${pypkgs.python.libPrefix}" + export PYTHON_LIBPATH="${pypkgs.python}/lib" + export PYTHON_INCLUDE_DIR="${pypkgs.python}/include/${pypkgs.python.libPrefix}" + export PYTHON_VERSION="${pypkgs.python.pythonVersion}" + export PYTHON_NUMPY_PATH="${pypkgs.numpy}/${pypkgs.python.sitePackages}" + export PYTHON_NUMPY_INCLUDE_DIRS="${pypkgs.numpy}/${pypkgs.python.sitePackages}/numpy/core/include" + export PYTHONPATH="$PYTHONPATH:$HOME/.local/lib/python3.10/site-packages" + export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + ''; +}