using UnityEngine; namespace TensorFlowLite { /// /// RectTransformationCalculator from MediaPipe /// https://github.com/google/mediapipe/blob/master/mediapipe/calculators/util/rect_transformation_calculator.cc /// public class RectTransformationCalculator { public ref struct Options { /// /// The Normalized Rect (0, 0, 1, 1) /// public Rect rect; public float rotationDegree; public Vector2 shift; public Vector2 scale; public bool mirrorHorizontal; public bool mirrorVertical; public bool IsCameraModified => mirrorHorizontal || mirrorVertical; } public static readonly Matrix4x4 POP_MATRIX = Matrix4x4.Translate(new Vector3(0.5f, 0.5f, 0)); public static readonly Matrix4x4 PUSH_MATRIX = Matrix4x4.Translate(new Vector3(-0.5f, -0.5f, 0)); public static Matrix4x4 CalcMatrix(in Options options) { Quaternion rotation = Quaternion.Euler(0, 0, options.rotationDegree); Vector2 size = Vector2.Scale(options.rect.size, options.scale); Vector2 shift = options.shift; // Calc center position Vector2 center = options.rect.center + new Vector2(-0.5f, -0.5f); center = (Vector2)(rotation * center); center += shift * size; center /= size; Matrix4x4 trs = Matrix4x4.TRS( new Vector3(-center.x, -center.y, 0), rotation, new Vector3(1 / size.x, -1 / size.y, 1) ); if (!options.IsCameraModified) { return POP_MATRIX * trs * PUSH_MATRIX; } Matrix4x4 cameraMtx = Matrix4x4.TRS( new Vector3(0, 0, 0), Quaternion.identity, new Vector3( options.mirrorHorizontal ? -1 : 1, options.mirrorVertical ? -1 : 1, 1 ) ); return POP_MATRIX * trs * cameraMtx * PUSH_MATRIX; } } }