1j01 / tracky-mouse

Mouse control via head tracking, as a cross platform desktop app and JS library. eViacam alternative.
https://trackymouse.js.org/
MIT License
27 stars 5 forks source link

Facemesh results don't correspond to the current camera frame due to latency #39

Open 1j01 opened 2 years ago

1j01 commented 2 years ago

Facemesh is run asynchronously in a Web Worker. It's sent camera frames, does its processing, then returns the face location predictions, but by the time it's processed it, the world has moved on: there have been multiple camera frames, and points tracked on the image have moved, moving the pointer (it doesn't wait for facemesh; it uses point tracking which is faster). The goal is to place (and remove) tracking points on the image based on the face location, but the face location information we get is for an outdated camera frame.

Now, this generally isn't that much of a problem. It causes some jitter due to points being added and removed stupidly, but the software still generally tracks your head movements. It can be a huge issue though, if hardware acceleration is disabled, if I recall correctly?

Ideal Solution

Make facemesh fast enough to run it synchronously.

Invalid Solution

First I tried moving the facemesh result, translating it by the averaged movement of the tracking points during the time it took facemesh to return results. That kind of.. almost works? But it's sort of backwards....

  1. This doesn't account for face rotation, or visual size change (movement towards/away from the camera)
  2. Part of the point is to update which points on the image should be tracked. If these are bad, or don't exist, it doesn't work!

Complex Solution

In order to compensate for the latency of results from the Worker, I made a "time travel" system:

...but it was too slow to actually do the replaying. Tracking the points is fast enough to do in realtime, but when time is bunched up like this, it causes a lot of lag, and makes it unusable.

To make this work I would need to optimize it.

Simple Partial Solution?

To be honest I don't remember if I implemented this in order to address this or not, but I feel like I made the adding and removing of points more strict, more constrained to the facemesh result, and even though the result is outdated, this actually helped a lot?

This isn't a huge issue at this point, since:

As long as the hardware is good enough? Look I worked on this a long time ago, I don't remember the situation.