Skip to content

Matrix4x4 in FaceLandmarkerResult seems to be corrupt #1354

@malaybaku

Description

@malaybaku

Plugin Version or Commit ID

v0.16.0

Unity Version

2022.3.7f1

Your Host OS

Windows 11 Pro

Target Platform

Windows Standalone

Target Device

No response

[Windows Only] Visual Studio C++ and Windows SDK Version

Visual Studio C++: 19.43.34809
Windows SDK: 10.0.22000.0

[Linux Only] GCC/G++ and GLIBC Version

No response

[Android Only] Android Build Tools and NDK Version

No response

[iOS Only] XCode Version

No response

Build Command

N/A

Bug Description

When applying rotation of matrix from FaceLandmarkerResult.facialTransformationMatrixes, the rotation behaves very odd.

Steps to Reproduce the Bug

  1. Prepare a script based on Tutorial-Task-API
  2. In Face Landmark Detection scene, replace FaceLandmarkerRunner component by replaced script.
  3. Start Play Mode to watch how cube rotation changes.
using System.Collections;
using UnityEngine;
using Mediapipe.Tasks.Vision.FaceLandmarker;
using Stopwatch = System.Diagnostics.Stopwatch;

namespace Mediapipe.Unity.Tutorial
{
  public class FaceLandmarkerRunner_RotationIssue : MonoBehaviour
  {
    [SerializeField] private int width;
    [SerializeField] private int height;
    [SerializeField] private int fps;
    [SerializeField] private TextAsset modelAsset;

    // 1: define rotation apply target object (e.g. Cube)
    [SerializeField] private Transform rotationApplyTarget;

    private WebCamTexture webCamTexture;

    private IEnumerator Start()
    {
      var webCamDevice = WebCamTexture.devices[0];
      webCamTexture = new WebCamTexture(webCamDevice.name, width, height, fps);
      webCamTexture.Play();
      yield return new WaitUntil(() => webCamTexture.width > 16);

      var options = new FaceLandmarkerOptions(
        baseOptions: new Tasks.Core.BaseOptions(
          Tasks.Core.BaseOptions.Delegate.CPU,
          modelAssetBuffer: modelAsset.bytes
        ),
        runningMode: Tasks.Vision.Core.RunningMode.VIDEO,
        // 2: Specify the option so that matrix will be included in result
        outputFaceTransformationMatrixes: true 
      );

      using var faceLandmarker = FaceLandmarker.CreateFromOptions(options);

      var stopwatch = new Stopwatch();
      stopwatch.Start();

      var waitForEndOfFrame = new WaitForEndOfFrame();
      using var textureFrame = new Experimental.TextureFrame(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32);

      while (true)
      {
        textureFrame.ReadTextureOnCPU(webCamTexture, flipHorizontally: false, flipVertically: true);
        using var image = textureFrame.BuildCPUImage();

        var result = faceLandmarker.DetectForVideo(image, stopwatch.ElapsedMilliseconds);
        // 3: Apply rotation to target object
        if (result.facialTransformationMatrixes?.Count > 0)
        {
          var matrix = result.facialTransformationMatrixes[0];
          rotationApplyTarget.localRotation = matrix.rotation;
        }
        yield return waitForEndOfFrame;
      }
    }

    private void OnDestroy()
    {
      if (webCamTexture != null)
      {
        webCamTexture.Stop();
      }
    }
  }
}

Log

N/A: video should be better to share what is happening.

Screenshot/Video

2025-03-21.17-39-24.mp4

Additional Context

I found that updating MatrixDataExtension.ToMatrix4x4() will be straight-forward fix. I will create a PR with this approach.

https://chatgpt.com/c/67dd1705-4b54-8007-8db2-0365174df47e

*Though the prompts and answers are in Japanese, I think math and code says most of important parts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions