Skip to content

Commit

Permalink
Implement Tracking (#254)
Browse files Browse the repository at this point in the history
* create `MediapipeGraphStore`, `TrackingComponent` and `AvatarController`

* fix graph encoding

* get landmarks

* update Akihabara to latest version

* check if camera is ready

* Revert "check if camera is ready"

This reverts commit 5e8f82a.

* use bitmap instead

* null check

* fix annoying crash -yet again-

* install linux package and begin BGR24 to BGRA32 conversion

* convert pixel format

* full encoding

* Improved vscode launch and tasks

* Fix color encoding

* upgrade akihabara windows runtime

* remove debugging code

* Improve image encoding speed by 30x

* check if Mat is empty

* Ignore empty mat

* Remove duplicate if

* add TryGetRawFrame

* cleanup useless garbage

* Ignore mediapipe folder for VSCode testing

* Adding a FaceControlPoints class

* Enclose it in correct namespace

* Math.

* Adding a FaceControlPoints to the TrackingComponent

* refactor and use `FaceData`

* Keep memory under control and check for mediapipe errors

* add custom timestamp counter

* make image conversion better

* check if it's byte array

* Add CONSTANT_CASE parameters for other avatars

* Fix "data cannot be null" bug

* fix memory leak

* remove because i forgor

* Use exceptions instead of booleans

* Improve TryGetRawFrame()

* Add an OutputFrame to facilitate camera preview

* Do not expose the ImageFrame to avoid AccessViolation

* update camera preview to show tracking

* fix colors and stuff poggers

* properly dispose image

* Add a ConvertRaw util function

* Remove conversion

* Remove unnecessary code and use ConvertRaw util function

* Bloating FaceData with names

* First implementation of 3d angles

* improve gitignore ffs

* Refactor distance functions

* Re-refactor distance functions

* Add angle movement

* Bypass compositor on Linux while debugging

* Refactor angle formulas

* Refactor AvatarController

* OPEN THE EYES

* Flip X angle

* move away from update thread and only send data to mediapipe when a camera has a new frame

* - add hardcoded model
- add disclaimer
- send frame to mediapipe every camera tick
- refactor `TrackingComponent`

* Nitrous forgor 💀

* Figured out the math for additive breathing

* Fixed CubismBreathController

* Add body angle control

* Make the breath controller absolute instead of additive

We'll implement a safe way to combine them at some point.

* Set default arm opacity

* Apply smoothing

* Add Calibrate feature

* Remove hard-coded offset

* use an easeInOutQuint function for the eyes

Seems slightly better, but still janky.

* fix tracker not running on camera tick and remove camera preview (for now)

* final steps!
- move Calibrate to `RecognitionSection` and add hint text
- prevent movement jittering

Co-authored-by: Nathan Alo <nathan.alo2000@gmail.com>
Co-authored-by: Adryzz <46694241+adryzz@users.noreply.github.com>
Co-authored-by: Speykious <speykious@gmail.com>
  • Loading branch information
4 people authored Nov 2, 2021
1 parent 9cf8b28 commit 62e26f4
Show file tree
Hide file tree
Showing 50 changed files with 15,321 additions and 169 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,13 @@ $RECYCLE.BIN/
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# Mediapipe graphs and modules for testing
mediapipe/

# osu!framework cache
cache/

# configuration files
config.dev.ini
framework.ini
72 changes: 60 additions & 12 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,96 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch (Debug)",
"name": "Launch (Linux Debug)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build (Debug)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Debug/net5.0/Vignette.dll",
"preLaunchTask": "Build (Linux Debug)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Debug/net5.0/ubuntu.20.04-x64/Vignette.dll",
"args": [],
"env": { "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR": "0" },
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch (Release)",
"name": "Launch (Linux Release)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build (Release)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Release/net5.0/Vignette.dll",
"preLaunchTask": "Build (Linux Release)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Release/net5.0/ubuntu.20.04-x64/Vignette.dll",
"args": [],
"env": { "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR": "0" },
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch Tests (Debug)",
"name": "Launch Tests (Linux Debug)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Tests (Debug)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Debug/net5.0/Vignette.Game.Tests.dll",
"preLaunchTask": "Build Tests (Linux Debug)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Debug/net5.0/ubuntu.20.04-x64/Vignette.Game.Tests.dll",
"args": [],
"env": { "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR": "0" },
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch Tests (Release)",
"name": "Launch Tests (Linux Release)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Tests (Release)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Release/net5.0/Vignette.Game.Tests.dll",
"preLaunchTask": "Build Tests (Linux Release)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Release/net5.0/ubuntu.20.04-x64/Vignette.Game.Tests.dll",
"args": [],
"env": { "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR": "0" },
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch (Windows Debug)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build (Windows Debug)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Debug/net5.0/win-x64/Vignette.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch (Windows Release)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build (Windows Release)",
"program": "${workspaceFolder}/Vignette.Desktop/bin/Release/net5.0/win-x64/Vignette.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch Tests (Windows Debug)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Tests (Windows Debug)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Debug/net5.0/win-x64/Vignette.Game.Tests.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Launch Tests (Windows Release)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Tests (Windows Release)",
"program": "${workspaceFolder}/Vignette.Game.Tests/bin/Release/net5.0/win-x64/Vignette.Game.Tests.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
}
]
}
94 changes: 90 additions & 4 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
"version": "2.0.0",
"tasks": [
{
"label": "Build (Debug)",
"label": "Build (Linux Debug)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"ubuntu.20.04-x64",
"Vignette.Desktop"
],
"group": "build",
Expand All @@ -21,7 +23,7 @@
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release)",
"label": "Build (Linux Release)",
"command": "dotnet",
"type": "shell",
"args": [
Expand All @@ -30,6 +32,8 @@
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"ubuntu.20.04-x64",
"Vignette.Desktop"
],
"group": "build",
Expand All @@ -39,14 +43,16 @@
"problemMatcher": "$msCompile"
},
{
"label": "Build Tests (Debug)",
"label": "Build Tests (Linux Debug)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"/property:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"ubuntu.20.04-x64",
"Vignette.Game.Tests"
],
"group": "build",
Expand All @@ -56,7 +62,7 @@
"problemMatcher": "$msCompile"
},
{
"label": "Build Tests (Release)",
"label": "Build Tests (Linux Release)",
"command": "dotnet",
"type": "shell",
"args": [
Expand All @@ -65,6 +71,86 @@
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"ubuntu.20.04-x64",
"Vignette.Game.Tests"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "Build (Windows Debug)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"win-x64",
"Vignette.Desktop"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "Build (Windows Release)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"-p:Configuration=Release",
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"win-x64",
"Vignette.Desktop"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "Build Tests (Windows Debug)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"/property:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"win-x64",
"Vignette.Game.Tests"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "Build Tests (Windows Release)",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"-p:Configuration=Release",
"-p:GenerateFullPaths=true",
"-m",
"-verbosity:m",
"-r",
"win-x64",
"Vignette.Game.Tests"
],
"group": "build",
Expand Down
2 changes: 1 addition & 1 deletion Vignette.Camera/Camera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public abstract class Camera : IDisposable, ICamera

protected DecoderState State { get; private set; } = DecoderState.Ready;

protected Mat Mat { get; private set; }
public Mat Mat { get; private set; }

private static Logger logger => Logger.GetLogger("performance-camera");

Expand Down
2 changes: 2 additions & 0 deletions Vignette.Desktop/Vignette.Desktop.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Akihabara.Runtime.Linux_x64.CPU" Version="2021.1030.0" />
<PackageReference Include="Akihabara.Runtime.Windows_x64.CPU" Version="2021.1030.0" />
<PackageReference Include="Emgu.CV.runtime.ubuntu.20.04-x64" Version="4.5.3.4721" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.3.4721" />
</ItemGroup>
Expand Down
63 changes: 63 additions & 0 deletions Vignette.Game.Resources/Graphs/face_mesh_desktop_live.pbtxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# MediaPipe graph that performs face mesh with TensorFlow Lite on CPU.

# Input image. (ImageFrame)
input_stream: "input_video"

# Output image with rendered results. (ImageFrame)
output_stream: "output_video"
# Collection of detected/processed faces, each represented as a list of
# landmarks. (std::vector<NormalizedLandmarkList>)
output_stream: "multi_face_landmarks"

# Throttles the images flowing downstream for flow control. It passes through
# the very first incoming image unaltered, and waits for downstream nodes
# (calculators and subgraphs) in the graph to finish their tasks before it
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# real-time mobile applications. It also eliminates unnecessarily computation,
# e.g., the output produced by a node may get dropped downstream if the
# subsequent nodes are still busy processing previous inputs.
node {
calculator: "FlowLimiterCalculator"
input_stream: "input_video"
input_stream: "FINISHED:output_video"
input_stream_info: {
tag_index: "FINISHED"
back_edge: true
}
output_stream: "throttled_input_video"
}

# Defines side packets for further use in the graph.
node {
calculator: "ConstantSidePacketCalculator"
output_side_packet: "PACKET:num_faces"
node_options: {
[type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
packet { int_value: 1 }
}
}
}
# Subgraph that detects faces and corresponding landmarks.
node {
calculator: "FaceLandmarkFrontCpu"
input_stream: "IMAGE:throttled_input_video"
input_side_packet: "NUM_FACES:num_faces"
output_stream: "LANDMARKS:multi_face_landmarks"
output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
output_stream: "DETECTIONS:face_detections"
output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
}
# Subgraph that renders face-landmark annotation onto the input image.
node {
calculator: "FaceRendererCpu"
input_stream: "IMAGE:throttled_input_video"
input_stream: "LANDMARKS:multi_face_landmarks"
input_stream: "NORM_RECTS:face_rects_from_landmarks"
input_stream: "DETECTIONS:face_detections"
output_stream: "IMAGE:output_video"
}
Binary file added Vignette.Game.Resources/Model/Hiyori.moc3
Binary file not shown.
Loading

1 comment on commit 62e26f4

@iojcde
Copy link
Member

@iojcde iojcde commented on 62e26f4 Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Please sign in to comment.