Wes xx mediapipe integration
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
/// <summary>
|
||||
/// This class draws annotations on the screen which is the parent of the attached <see cref="GameObject" />.<br />
|
||||
/// That is, it's used like this.<br />
|
||||
/// 1. Select a GameObject where you'd like to draw annotations.<br />
|
||||
/// 2. Create an empty child GameObject (let's say AnnotationLayer) directly under it.<br />
|
||||
/// 3. Attach <see cref="AnnotationController{T}" /> to AnnotationLayer.<br />
|
||||
/// 4. Create an empty child GameObject (let's say RootAnnotation) directly under AnnotationLayer.<br />
|
||||
/// 5. Attach <see cref="HierarchicalAnnotation" /> to RootAnnotation.<br />
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that this class can be accessed from a thread other than main thread.
|
||||
/// Extended classes must be implemented to work in such a situation, since Unity APIs won't work in other threads.
|
||||
/// </remarks>
|
||||
public abstract class AnnotationController<T> : MonoBehaviour where T : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] protected T annotation;
|
||||
protected bool isStale = false;
|
||||
|
||||
public bool isMirrored
|
||||
{
|
||||
get => annotation.isMirrored;
|
||||
set
|
||||
{
|
||||
if (annotation.isMirrored != value)
|
||||
{
|
||||
annotation.isMirrored = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RotationAngle rotationAngle
|
||||
{
|
||||
get => annotation.rotationAngle;
|
||||
set
|
||||
{
|
||||
if (annotation.rotationAngle != value)
|
||||
{
|
||||
annotation.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
if (!TryGetComponent<RectTransform>(out var _))
|
||||
{
|
||||
Logger.LogVerbose(GetType().Name, $"Adding RectTransform to {gameObject.name}");
|
||||
var rectTransform = gameObject.AddComponent<RectTransform>();
|
||||
// stretch width and height by default
|
||||
rectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||||
rectTransform.anchorMin = Vector2.zero;
|
||||
rectTransform.anchorMax = Vector2.one;
|
||||
rectTransform.anchoredPosition3D = Vector3.zero;
|
||||
rectTransform.sizeDelta = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (isStale)
|
||||
{
|
||||
SyncNow();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (annotation != null)
|
||||
{
|
||||
Destroy(annotation);
|
||||
annotation = null;
|
||||
}
|
||||
isStale = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw annotations in current thread.
|
||||
/// This method must set <see cref="isStale" /> to false.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method can only be called from main thread.
|
||||
/// </remarks>
|
||||
protected abstract void SyncNow();
|
||||
|
||||
protected void UpdateCurrentTarget<TValue>(TValue newTarget, ref TValue currentTarget)
|
||||
{
|
||||
if (IsTargetChanged(newTarget, currentTarget))
|
||||
{
|
||||
currentTarget = newTarget;
|
||||
isStale = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsTargetChanged<TValue>(TValue newTarget, TValue currentTarget)
|
||||
{
|
||||
// It's assumed that target has not changed iff previous target and new target are both null.
|
||||
return currentTarget != null || newTarget != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f1980da4d69e05869d4a1cdac8f4ced
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class Arrow : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Color _color = Color.white;
|
||||
[SerializeField] private Vector3 _direction = Vector3.right;
|
||||
[SerializeField] private float _magnitude = 0.0f;
|
||||
[SerializeField] private float _capScale = 1.0f;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
ApplyColor(color);
|
||||
ApplyDirection(_direction);
|
||||
ApplyCapScale(_capScale);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
ApplyMagnitude(_magnitude); // magnitude must be set after _capScale
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyDirection(_direction);
|
||||
ApplyCapScale(_capScale);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
ApplyMagnitude(_magnitude); // magnitude must be set after _capScale
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private Transform _cone;
|
||||
private Transform cone
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cone == null)
|
||||
{
|
||||
_cone = transform.Find("Cone");
|
||||
}
|
||||
return _cone;
|
||||
}
|
||||
}
|
||||
|
||||
private LineRenderer lineRenderer => gameObject.GetComponent<LineRenderer>();
|
||||
|
||||
public Vector3 direction
|
||||
{
|
||||
get => _direction;
|
||||
set
|
||||
{
|
||||
_direction = value.normalized;
|
||||
ApplyDirection(_direction);
|
||||
}
|
||||
}
|
||||
|
||||
public float magnitude
|
||||
{
|
||||
get => _magnitude;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentException("Magnitude must be positive");
|
||||
}
|
||||
_magnitude = value;
|
||||
ApplyMagnitude(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Color color
|
||||
{
|
||||
get => _color;
|
||||
set
|
||||
{
|
||||
_color = value;
|
||||
ApplyColor(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVector(Vector3 v)
|
||||
{
|
||||
direction = v;
|
||||
magnitude = v.magnitude;
|
||||
}
|
||||
|
||||
public void SetCapScale(float capScale)
|
||||
{
|
||||
_capScale = capScale;
|
||||
ApplyCapScale(_capScale);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
lineRenderer.startColor = color;
|
||||
lineRenderer.endColor = color;
|
||||
cone.GetComponent<Renderer>().material.color = color;
|
||||
}
|
||||
|
||||
private void ApplyDirection(Vector3 direction)
|
||||
{
|
||||
lineRenderer.SetPosition(1, _magnitude * direction);
|
||||
cone.localRotation = Quaternion.FromToRotation(Vector3.up, direction);
|
||||
}
|
||||
|
||||
private void ApplyMagnitude(float magnitude)
|
||||
{
|
||||
lineRenderer.SetPosition(1, magnitude * direction);
|
||||
|
||||
if (magnitude == 0)
|
||||
{
|
||||
cone.localScale = Vector3.zero;
|
||||
cone.localPosition = Vector3.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyCapScale(_capScale);
|
||||
cone.localPosition = (cone.localScale.y + magnitude) * direction; // pivot is at the center of cone
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyCapScale(float capScale)
|
||||
{
|
||||
cone.localScale = capScale * Vector3.one;
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
lineRenderer.startWidth = lineWidth;
|
||||
lineRenderer.endWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a793788ee98ea8ea3b28457e7dd7197d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class CircleAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private LineRenderer _lineRenderer;
|
||||
[SerializeField] private Color _color = Color.green;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ApplyLineWidth(0.0f);
|
||||
_lineRenderer.positionCount = 0;
|
||||
_lineRenderer.SetPositions(new Vector3[] { });
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void Draw(Vector3 center, float radius, int vertices = 128)
|
||||
{
|
||||
var start = new Vector3(radius, 0, 0);
|
||||
var positions = new Vector3[vertices];
|
||||
|
||||
for (var i = 0; i < positions.Length; i++)
|
||||
{
|
||||
var q = Quaternion.Euler(0, 0, i * 360 / positions.Length);
|
||||
positions[i] = (q * start) + center;
|
||||
}
|
||||
|
||||
_lineRenderer.positionCount = positions.Length;
|
||||
_lineRenderer.SetPositions(positions);
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startColor = color;
|
||||
_lineRenderer.endColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startWidth = lineWidth;
|
||||
_lineRenderer.endWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98e622123dd1b9ac1a87d8609ce21d37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class Connection
|
||||
{
|
||||
public readonly HierarchicalAnnotation start;
|
||||
public readonly HierarchicalAnnotation end;
|
||||
|
||||
public Connection(HierarchicalAnnotation start, HierarchicalAnnotation end)
|
||||
{
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e71b609a71e6232a8043e02da04b2bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class ConnectionAnnotation : LineAnnotation
|
||||
{
|
||||
private Connection _currentTarget;
|
||||
|
||||
public bool isEmpty => _currentTarget == null;
|
||||
|
||||
public void Draw(Connection target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
|
||||
if (ActivateFor(_currentTarget))
|
||||
{
|
||||
Draw(_currentTarget.start.gameObject, _currentTarget.end.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Redraw()
|
||||
{
|
||||
Draw(_currentTarget);
|
||||
}
|
||||
|
||||
protected bool ActivateFor(Connection target)
|
||||
{
|
||||
if (target == null || !target.start.isActiveInHierarchy || !target.end.isActiveInHierarchy)
|
||||
{
|
||||
SetActive(false);
|
||||
return false;
|
||||
}
|
||||
SetActive(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90aa7330426be071f9141dd20224e6cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class ConnectionListAnnotation : ListAnnotation<ConnectionAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _color = Color.red;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Fill(IList<(int, int)> connections, PointListAnnotation points)
|
||||
{
|
||||
Draw(connections.Select(pair => new Connection(points[pair.Item1], points[pair.Item2])).ToList());
|
||||
}
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<Connection> targets)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) => { if (annotation != null) { annotation.Draw(target); } });
|
||||
}
|
||||
}
|
||||
|
||||
public void Redraw()
|
||||
{
|
||||
foreach (var connection in children)
|
||||
{
|
||||
if (connection != null) { connection.Redraw(); }
|
||||
}
|
||||
}
|
||||
|
||||
protected override ConnectionAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetColor(_color);
|
||||
annotation.SetLineWidth(_lineWidth);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
foreach (var line in children)
|
||||
{
|
||||
if (line != null) { line.SetColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
foreach (var line in children)
|
||||
{
|
||||
if (line != null) { line.SetLineWidth(lineWidth); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03e2158a34405b74280f0e793ae6d083
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 4824063073641375834, guid: ce6db8ad8200781fc9201c21237ce23b,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class CuboidAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private PointListAnnotation _pointListAnnotation;
|
||||
[SerializeField] private ConnectionListAnnotation _lineListAnnotation;
|
||||
[SerializeField] private TransformAnnotation _transformAnnotation;
|
||||
[SerializeField] private float _arrowLengthScale = 1.0f;
|
||||
|
||||
/// 3 ----------- 7
|
||||
/// /| /|
|
||||
/// ../ | 0 / |
|
||||
/// .4 ----------- 8 |
|
||||
/// | 1 ---------|- 5
|
||||
/// | / | /
|
||||
/// |/ |/
|
||||
/// 2 ----------- 6
|
||||
private readonly List<(int, int)> _connections = new List<(int, int)> {
|
||||
(1, 2),
|
||||
(3, 4),
|
||||
(5, 6),
|
||||
(7, 8),
|
||||
(1, 3),
|
||||
(2, 4),
|
||||
(5, 7),
|
||||
(6, 8),
|
||||
(1, 5),
|
||||
(2, 6),
|
||||
(3, 7),
|
||||
(4, 8),
|
||||
};
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_pointListAnnotation.isMirrored = value;
|
||||
_lineListAnnotation.isMirrored = value;
|
||||
_transformAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_pointListAnnotation.rotationAngle = value;
|
||||
_lineListAnnotation.rotationAngle = value;
|
||||
_transformAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_pointListAnnotation.Fill(9);
|
||||
_lineListAnnotation.Fill(_connections, _pointListAnnotation);
|
||||
}
|
||||
|
||||
public void SetPointColor(Color color)
|
||||
{
|
||||
_pointListAnnotation.SetColor(color);
|
||||
}
|
||||
|
||||
public void SetLineColor(Color color)
|
||||
{
|
||||
_lineListAnnotation.SetColor(color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineListAnnotation.SetLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void SetArrowCapScale(float arrowCapScale)
|
||||
{
|
||||
_transformAnnotation.SetArrowCapScale(arrowCapScale);
|
||||
}
|
||||
|
||||
public void SetArrowLengthScale(float arrowLengthScale)
|
||||
{
|
||||
_arrowLengthScale = arrowLengthScale;
|
||||
}
|
||||
|
||||
public void SetArrowWidth(float arrowWidth)
|
||||
{
|
||||
_transformAnnotation.SetArrowWidth(arrowWidth);
|
||||
}
|
||||
|
||||
public void Draw(ObjectAnnotation target, Vector2 focalLength, Vector2 principalPoint, float zScale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_pointListAnnotation.Draw(target.Keypoints, focalLength, principalPoint, zScale, visualizeZ);
|
||||
_lineListAnnotation.Redraw();
|
||||
_transformAnnotation.Draw(target, _pointListAnnotation[0].transform.localPosition, _arrowLengthScale, visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e88663936c139fb4971d8ab54a85a11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _pointListAnnotation: {instanceID: 0}
|
||||
- _lineListAnnotation: {instanceID: 0}
|
||||
- _transformAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class CuboidListAnnotation : ListAnnotation<CuboidAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _pointColor = Color.green;
|
||||
[SerializeField] private Color _lineColor = Color.red;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
[SerializeField] private float _arrowCapScale = 2.0f;
|
||||
[SerializeField] private float _arrowLengthScale = 1.0f;
|
||||
[SerializeField, Range(0, 1)] private float _arrowWidth = 1.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyPointColor(_pointColor);
|
||||
ApplyLineColor(_lineColor);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
ApplyArrowCapScale(_arrowCapScale);
|
||||
ApplyArrowLengthScale(_arrowLengthScale);
|
||||
ApplyArrowWidth(_arrowWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetPointColor(Color pointColor)
|
||||
{
|
||||
_pointColor = pointColor;
|
||||
ApplyPointColor(pointColor);
|
||||
}
|
||||
|
||||
public void SetLineColor(Color lineColor)
|
||||
{
|
||||
_lineColor = lineColor;
|
||||
ApplyLineColor(lineColor);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void SetArrowCapScale(float arrowCapScale)
|
||||
{
|
||||
_arrowCapScale = arrowCapScale;
|
||||
ApplyArrowCapScale(arrowCapScale);
|
||||
}
|
||||
|
||||
public void SetArrowLengthScale(float arrowLengthScale)
|
||||
{
|
||||
_arrowLengthScale = arrowLengthScale;
|
||||
ApplyArrowLengthScale(arrowLengthScale);
|
||||
}
|
||||
|
||||
public void SetArrowWidth(float arrowWidth)
|
||||
{
|
||||
_arrowWidth = arrowWidth;
|
||||
ApplyArrowWidth(arrowWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<ObjectAnnotation> targets, Vector2 focalLength, Vector2 principalPoint, float scale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, focalLength, principalPoint, scale, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(FrameAnnotation target, Vector2 focalLength, Vector2 principalPoint, float scale, bool visualizeZ = true)
|
||||
{
|
||||
Draw(target?.Annotations, focalLength, principalPoint, scale, visualizeZ);
|
||||
}
|
||||
|
||||
protected override CuboidAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetPointColor(_pointColor);
|
||||
annotation.SetLineColor(_lineColor);
|
||||
annotation.SetLineWidth(_lineWidth);
|
||||
annotation.SetArrowCapScale(_arrowCapScale);
|
||||
annotation.SetArrowLengthScale(_arrowLengthScale);
|
||||
annotation.SetArrowWidth(_arrowWidth);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyPointColor(Color pointColor)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetPointColor(pointColor); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineColor(Color lineColor)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetLineColor(lineColor); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetLineWidth(lineWidth); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyArrowCapScale(float arrowCapScale)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetArrowCapScale(arrowCapScale); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyArrowLengthScale(float arrowLengthScale)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetArrowLengthScale(arrowLengthScale); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyArrowWidth(float arrowWidth)
|
||||
{
|
||||
foreach (var cuboid in children)
|
||||
{
|
||||
if (cuboid != null) { cuboid.SetArrowWidth(arrowWidth); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69c9a763206a6fa938324ba456924e67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 2519151911608524794, guid: 915f3c383a25ff9bd985b1394fc052de,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class DetectionAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private RectangleAnnotation _locationDataAnnotation;
|
||||
[SerializeField] private PointListAnnotation _relativeKeypointsAnnotation;
|
||||
[SerializeField] private LabelAnnotation _labelAnnotation;
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_locationDataAnnotation.isMirrored = value;
|
||||
_relativeKeypointsAnnotation.isMirrored = value;
|
||||
_labelAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_locationDataAnnotation.rotationAngle = value;
|
||||
_relativeKeypointsAnnotation.rotationAngle = value;
|
||||
_labelAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_locationDataAnnotation.SetLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void SetKeypointRadius(float radius)
|
||||
{
|
||||
_relativeKeypointsAnnotation.SetRadius(radius);
|
||||
}
|
||||
|
||||
/// <param name="threshold">
|
||||
/// Score threshold. This value must be between 0 and 1.
|
||||
/// This will affect the rectangle's color. For example, if the score is below the threshold, the rectangle will be transparent.
|
||||
/// The default value is 0.
|
||||
/// </param>
|
||||
public void Draw(Detection target, float threshold = 0.0f)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
var score = target.Score.Count > 0 ? target.Score[0] : 1.0f;
|
||||
var color = GetColor(score, Mathf.Clamp(threshold, 0.0f, 1.0f));
|
||||
|
||||
// Assume that location data's format is always RelativeBoundingBox
|
||||
// TODO: fix if there are cases where this assumption is not correct.
|
||||
var rectVertices = GetScreenRect().GetRectVertices(target.LocationData.RelativeBoundingBox, rotationAngle, isMirrored);
|
||||
_locationDataAnnotation.SetColor(GetColor(score, Mathf.Clamp(threshold, 0.0f, 1.0f)));
|
||||
_locationDataAnnotation.Draw(rectVertices);
|
||||
|
||||
var width = rectVertices[2].x - rectVertices[0].x;
|
||||
var height = rectVertices[2].y - rectVertices[0].y;
|
||||
var labelText = target.Label.Count > 0 ? target.Label[0] : null;
|
||||
var vertexId = (((int)rotationAngle / 90) + 1) % 4;
|
||||
var isInverted = ImageCoordinate.IsInverted(rotationAngle);
|
||||
var (maxWidth, maxHeight) = isInverted ? (height, width) : (width, height);
|
||||
_labelAnnotation.Draw(labelText, rectVertices[vertexId], color, maxWidth, maxHeight);
|
||||
|
||||
_relativeKeypointsAnnotation.Draw(target.LocationData.RelativeKeypoints);
|
||||
}
|
||||
}
|
||||
|
||||
private Color GetColor(float score, float threshold)
|
||||
{
|
||||
var t = (score - threshold) / (1 - threshold);
|
||||
var h = Mathf.Lerp(90, 0, t) / 360; // from yellow-green to red
|
||||
var color = Color.HSVToRGB(h, 1, 1);
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
// below the threshold
|
||||
color.a = 0.5f;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a82b9904ff34cc4fb66157217fe48a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _locationDataAnnotation: {instanceID: 0}
|
||||
- _relativeKeypointsAnnotation: {instanceID: 0}
|
||||
- _labelAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class DetectionAnnotationController : AnnotationController<DetectionAnnotation>
|
||||
{
|
||||
[SerializeField, Range(0, 1)] private float _threshold = 0.0f;
|
||||
|
||||
private Detection _currentTarget;
|
||||
|
||||
public void DrawNow(Detection target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(Detection target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 275060fa7ac08c4128c0ea18c71b73dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 5404176935574894484, guid: 9e4308c3e97d26a388364cbe0ea8bfb4,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public sealed class DetectionListAnnotation : ListAnnotation<DetectionAnnotation>
|
||||
{
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
[SerializeField] private float _keypointRadius = 15.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyLineWidth(_lineWidth);
|
||||
ApplyKeypointRadius(_keypointRadius);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
public void SetKeypointRadius(float keypointRadius)
|
||||
{
|
||||
_keypointRadius = keypointRadius;
|
||||
ApplyKeypointRadius(keypointRadius);
|
||||
}
|
||||
|
||||
/// <param name="threshold">
|
||||
/// Score threshold. This value must be between 0 and 1.
|
||||
/// This will affect the rectangle's color. For example, if the score is below the threshold, the rectangle will be transparent.
|
||||
/// The default value is 0.
|
||||
/// </param>
|
||||
public void Draw(IList<Detection> targets, float threshold = 0.0f)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, threshold); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="threshold">
|
||||
/// Score threshold. This value must be between 0 and 1.
|
||||
/// This will affect the rectangle's color. For example, if the score is below the threshold, the rectangle will be transparent.
|
||||
/// The default value is 0.
|
||||
/// </param>
|
||||
public void Draw(DetectionList target, float threshold = 0.0f)
|
||||
{
|
||||
Draw(target?.Detection, threshold);
|
||||
}
|
||||
|
||||
protected override DetectionAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetLineWidth(_lineWidth);
|
||||
annotation.SetKeypointRadius(_keypointRadius);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
foreach (var detection in children)
|
||||
{
|
||||
if (detection != null) { detection.SetLineWidth(lineWidth); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyKeypointRadius(float keypointRadius)
|
||||
{
|
||||
foreach (var detection in children)
|
||||
{
|
||||
if (detection != null) { detection.SetKeypointRadius(keypointRadius); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d433cdb024dfd584696eeb11efb71102
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 5404176935574894484, guid: 9e4308c3e97d26a388364cbe0ea8bfb4,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class DetectionListAnnotationController : AnnotationController<DetectionListAnnotation>
|
||||
{
|
||||
[SerializeField, Range(0, 1)] private float _threshold = 0.0f;
|
||||
|
||||
private IList<Detection> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<Detection> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(DetectionList target)
|
||||
{
|
||||
DrawNow(target?.Detection);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<Detection> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(DetectionList target)
|
||||
{
|
||||
DrawLater(target?.Detection);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8741257e98d0a1560b37e577decc0e2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 6320745076577806712, guid: 26114bc9cccb92454a468ea4d41f400a,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,217 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class FaceLandmarkListAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private PointListAnnotation _landmarkListAnnotation;
|
||||
[SerializeField] private ConnectionListAnnotation _connectionListAnnotation;
|
||||
|
||||
private const int _LandmarkCount = 468;
|
||||
private readonly List<(int, int)> _connections = new List<(int, int)> {
|
||||
// Face Oval
|
||||
(10, 338),
|
||||
(338, 297),
|
||||
(297, 332),
|
||||
(332, 284),
|
||||
(284, 251),
|
||||
(251, 389),
|
||||
(389, 356),
|
||||
(356, 454),
|
||||
(454, 323),
|
||||
(323, 361),
|
||||
(361, 288),
|
||||
(288, 397),
|
||||
(397, 365),
|
||||
(365, 379),
|
||||
(379, 378),
|
||||
(378, 400),
|
||||
(400, 377),
|
||||
(377, 152),
|
||||
(152, 148),
|
||||
(148, 176),
|
||||
(176, 149),
|
||||
(149, 150),
|
||||
(150, 136),
|
||||
(136, 172),
|
||||
(172, 58),
|
||||
(58, 132),
|
||||
(132, 93),
|
||||
(93, 234),
|
||||
(234, 127),
|
||||
(127, 162),
|
||||
(162, 21),
|
||||
(21, 54),
|
||||
(54, 103),
|
||||
(103, 67),
|
||||
(67, 109),
|
||||
(109, 10),
|
||||
// Left Eye
|
||||
(33, 7),
|
||||
(7, 163),
|
||||
(163, 144),
|
||||
(144, 145),
|
||||
(145, 153),
|
||||
(153, 154),
|
||||
(154, 155),
|
||||
(155, 133),
|
||||
(33, 246),
|
||||
(246, 161),
|
||||
(161, 160),
|
||||
(160, 159),
|
||||
(159, 158),
|
||||
(158, 157),
|
||||
(157, 173),
|
||||
(173, 133),
|
||||
// Left Eyebrow
|
||||
(46, 53),
|
||||
(53, 52),
|
||||
(52, 65),
|
||||
(65, 55),
|
||||
(70, 63),
|
||||
(63, 105),
|
||||
(105, 66),
|
||||
(66, 107),
|
||||
// Right Eye
|
||||
(263, 249),
|
||||
(249, 390),
|
||||
(390, 373),
|
||||
(373, 374),
|
||||
(374, 380),
|
||||
(380, 381),
|
||||
(381, 382),
|
||||
(382, 362),
|
||||
(263, 466),
|
||||
(466, 388),
|
||||
(388, 387),
|
||||
(387, 386),
|
||||
(386, 385),
|
||||
(385, 384),
|
||||
(384, 398),
|
||||
(398, 362),
|
||||
// Right Eyebrow
|
||||
(276, 283),
|
||||
(283, 282),
|
||||
(282, 295),
|
||||
(295, 285),
|
||||
(300, 293),
|
||||
(293, 334),
|
||||
(334, 296),
|
||||
(296, 336),
|
||||
// Lips (Inner)
|
||||
(78, 95),
|
||||
(95, 88),
|
||||
(88, 178),
|
||||
(178, 87),
|
||||
(87, 14),
|
||||
(14, 317),
|
||||
(317, 402),
|
||||
(402, 318),
|
||||
(318, 324),
|
||||
(324, 308),
|
||||
(78, 191),
|
||||
(191, 80),
|
||||
(80, 81),
|
||||
(81, 82),
|
||||
(82, 13),
|
||||
(13, 312),
|
||||
(312, 311),
|
||||
(311, 310),
|
||||
(310, 415),
|
||||
(415, 308),
|
||||
// Lips (Outer)
|
||||
(61, 146),
|
||||
(146, 91),
|
||||
(91, 181),
|
||||
(181, 84),
|
||||
(84, 17),
|
||||
(17, 314),
|
||||
(314, 405),
|
||||
(405, 321),
|
||||
(321, 375),
|
||||
(375, 291),
|
||||
(61, 185),
|
||||
(185, 40),
|
||||
(40, 39),
|
||||
(39, 37),
|
||||
(37, 0),
|
||||
(0, 267),
|
||||
(267, 269),
|
||||
(269, 270),
|
||||
(270, 409),
|
||||
(409, 291),
|
||||
};
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.isMirrored = value;
|
||||
_connectionListAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.rotationAngle = value;
|
||||
_connectionListAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_landmarkListAnnotation.Fill(_LandmarkCount);
|
||||
_connectionListAnnotation.Fill(_connections, _landmarkListAnnotation);
|
||||
}
|
||||
|
||||
public void SetLandmarkColor(Color landmarkColor)
|
||||
{
|
||||
_landmarkListAnnotation.SetColor(landmarkColor);
|
||||
}
|
||||
|
||||
public void SetLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
_landmarkListAnnotation.SetRadius(landmarkRadius);
|
||||
}
|
||||
|
||||
public void SetConnectionColor(Color connectionColor)
|
||||
{
|
||||
_connectionListAnnotation.SetColor(connectionColor);
|
||||
}
|
||||
|
||||
public void SetConnectionWidth(float connectionWidth)
|
||||
{
|
||||
_connectionListAnnotation.SetLineWidth(connectionWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_landmarkListAnnotation.Draw(target, visualizeZ);
|
||||
// Draw explicitly because connection annotation's targets remain the same.
|
||||
_connectionListAnnotation.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target?.Landmark, visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1275dad009e98d9f490bd65e83f7eba5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _landmarkListAnnotation: {instanceID: 0}
|
||||
- _connectionListAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class FaceLandmarkListAnnotationController : AnnotationController<FaceLandmarkListWithIrisAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
[SerializeField] private int _circleVertices = 128;
|
||||
|
||||
private IList<NormalizedLandmark> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmark> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(NormalizedLandmarkList target)
|
||||
{
|
||||
DrawNow(target?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmark> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(NormalizedLandmarkList target)
|
||||
{
|
||||
DrawLater(target?.Landmark);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _visualizeZ, _circleVertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1fe9c61c434938249e2c9d067a337a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class FaceLandmarkListWithIrisAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private FaceLandmarkListAnnotation _faceLandmarkListAnnotation;
|
||||
[SerializeField] private IrisLandmarkListAnnotation _leftIrisLandmarkListAnnotation;
|
||||
[SerializeField] private IrisLandmarkListAnnotation _rightIrisLandmarkListAnnotation;
|
||||
|
||||
private const int _FaceLandmarkCount = 468;
|
||||
private const int _IrisLandmarkCount = 5;
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_faceLandmarkListAnnotation.isMirrored = value;
|
||||
_leftIrisLandmarkListAnnotation.isMirrored = value;
|
||||
_rightIrisLandmarkListAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_faceLandmarkListAnnotation.rotationAngle = value;
|
||||
_leftIrisLandmarkListAnnotation.rotationAngle = value;
|
||||
_rightIrisLandmarkListAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFaceLandmarkColor(Color color)
|
||||
{
|
||||
_faceLandmarkListAnnotation.SetLandmarkColor(color);
|
||||
}
|
||||
|
||||
public void SetIrisLandmarkColor(Color color)
|
||||
{
|
||||
_leftIrisLandmarkListAnnotation.SetLandmarkColor(color);
|
||||
_rightIrisLandmarkListAnnotation.SetLandmarkColor(color);
|
||||
}
|
||||
|
||||
public void SetFaceLandmarkRadius(float radius)
|
||||
{
|
||||
_faceLandmarkListAnnotation.SetLandmarkRadius(radius);
|
||||
}
|
||||
|
||||
public void SetIrisLandmarkRadius(float radius)
|
||||
{
|
||||
_leftIrisLandmarkListAnnotation.SetLandmarkRadius(radius);
|
||||
_rightIrisLandmarkListAnnotation.SetLandmarkRadius(radius);
|
||||
}
|
||||
|
||||
public void SetFaceConnectionColor(Color color)
|
||||
{
|
||||
_faceLandmarkListAnnotation.SetConnectionColor(color);
|
||||
}
|
||||
|
||||
public void SetFaceConnectionWidth(float width)
|
||||
{
|
||||
_faceLandmarkListAnnotation.SetConnectionWidth(width);
|
||||
}
|
||||
|
||||
public void SetIrisCircleColor(Color color)
|
||||
{
|
||||
_leftIrisLandmarkListAnnotation.SetCircleColor(color);
|
||||
_rightIrisLandmarkListAnnotation.SetCircleColor(color);
|
||||
}
|
||||
|
||||
public void SetIrisCircleWidth(float width)
|
||||
{
|
||||
_leftIrisLandmarkListAnnotation.SetCircleWidth(width);
|
||||
_rightIrisLandmarkListAnnotation.SetCircleWidth(width);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
var (faceLandmarks, leftLandmarks, rightLandmarks) = PartitionLandmarkList(target);
|
||||
DrawFaceLandmarkList(faceLandmarks, visualizeZ);
|
||||
DrawLeftIrisLandmarkList(leftLandmarks, visualizeZ, circleVertices);
|
||||
DrawRightIrisLandmarkList(rightLandmarks, visualizeZ, circleVertices);
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
Draw(target.Landmark, visualizeZ, circleVertices);
|
||||
}
|
||||
|
||||
public void DrawFaceLandmarkList(IList<NormalizedLandmark> target, bool visualizeZ = false)
|
||||
{
|
||||
_faceLandmarkListAnnotation.Draw(target, visualizeZ);
|
||||
}
|
||||
|
||||
public void DrawLeftIrisLandmarkList(IList<NormalizedLandmark> target, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
// does not deactivate if the target is null as long as face landmarks are present.
|
||||
_leftIrisLandmarkListAnnotation.Draw(target, visualizeZ, circleVertices);
|
||||
}
|
||||
|
||||
public void DrawRightIrisLandmarkList(IList<NormalizedLandmark> target, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
// does not deactivate if the target is null as long as face landmarks are present.
|
||||
_rightIrisLandmarkListAnnotation.Draw(target, visualizeZ, circleVertices);
|
||||
}
|
||||
|
||||
private static (IList<NormalizedLandmark>, IList<NormalizedLandmark>, IList<NormalizedLandmark>) PartitionLandmarkList(IList<NormalizedLandmark> landmarks)
|
||||
{
|
||||
if (landmarks == null)
|
||||
{
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
var enumerator = landmarks.GetEnumerator();
|
||||
var faceLandmarks = new List<NormalizedLandmark>(_FaceLandmarkCount);
|
||||
for (var i = 0; i < _FaceLandmarkCount; i++)
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
faceLandmarks.Add(enumerator.Current);
|
||||
}
|
||||
}
|
||||
if (faceLandmarks.Count < _FaceLandmarkCount)
|
||||
{
|
||||
return (null, null, null);
|
||||
}
|
||||
|
||||
var leftIrisLandmarks = new List<NormalizedLandmark>(_IrisLandmarkCount);
|
||||
for (var i = 0; i < _IrisLandmarkCount; i++)
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
leftIrisLandmarks.Add(enumerator.Current);
|
||||
}
|
||||
}
|
||||
if (leftIrisLandmarks.Count < _IrisLandmarkCount)
|
||||
{
|
||||
return (faceLandmarks, null, null);
|
||||
}
|
||||
|
||||
var rightIrisLandmarks = new List<NormalizedLandmark>(_IrisLandmarkCount);
|
||||
for (var i = 0; i < _IrisLandmarkCount; i++)
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
rightIrisLandmarks.Add(enumerator.Current);
|
||||
}
|
||||
}
|
||||
return rightIrisLandmarks.Count < _IrisLandmarkCount ? (faceLandmarks, leftIrisLandmarks, null) : (faceLandmarks, leftIrisLandmarks, rightIrisLandmarks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3266a44159f9c0f495c095447ca1e5f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _faceLandmarkListAnnotation: {instanceID: 0}
|
||||
- _leftIrisLandmarkListAnnotation: {instanceID: 0}
|
||||
- _rightIrisLandmarkListAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class FrameAnnotationController : AnnotationController<CuboidListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = true;
|
||||
[SerializeField] private float _translateZ = -10.0f;
|
||||
[SerializeField] private float _scaleZ = 1.0f;
|
||||
|
||||
[HideInInspector] public Vector2 focalLength = Vector2.zero;
|
||||
[HideInInspector] public Vector2 principalPoint = Vector2.zero;
|
||||
|
||||
private FrameAnnotation _currentTarget;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
ApplyTranslateZ(_translateZ);
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
ApplyTranslateZ(_translateZ);
|
||||
}
|
||||
|
||||
public void DrawNow(FrameAnnotation target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(FrameAnnotation target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, focalLength, principalPoint, _scaleZ, _visualizeZ);
|
||||
}
|
||||
|
||||
private void ApplyTranslateZ(float translateZ)
|
||||
{
|
||||
annotation.transform.localPosition = _visualizeZ ? new Vector3(0, 0, translateZ) : Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ec6e7b1749fd598a93275c583e1ceb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class HandLandmarkListAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private PointListAnnotation _landmarkListAnnotation;
|
||||
[SerializeField] private ConnectionListAnnotation _connectionListAnnotation;
|
||||
[SerializeField] private Color _leftLandmarkColor = Color.green;
|
||||
[SerializeField] private Color _rightLandmarkColor = Color.green;
|
||||
|
||||
public enum Hand
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
private const int _LandmarkCount = 21;
|
||||
private readonly List<(int, int)> _connections = new List<(int, int)> {
|
||||
(0, 1),
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(3, 4),
|
||||
(0, 5),
|
||||
(5, 9),
|
||||
(9, 13),
|
||||
(13, 17),
|
||||
(0, 17),
|
||||
(5, 6),
|
||||
(6, 7),
|
||||
(7, 8),
|
||||
(9, 10),
|
||||
(10, 11),
|
||||
(11, 12),
|
||||
(13, 14),
|
||||
(14, 15),
|
||||
(15, 16),
|
||||
(17, 18),
|
||||
(18, 19),
|
||||
(19, 20),
|
||||
};
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.isMirrored = value;
|
||||
_connectionListAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.rotationAngle = value;
|
||||
_connectionListAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PointAnnotation this[int index] => _landmarkListAnnotation[index];
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_landmarkListAnnotation.Fill(_LandmarkCount);
|
||||
_connectionListAnnotation.Fill(_connections, _landmarkListAnnotation);
|
||||
}
|
||||
|
||||
public void SetLeftLandmarkColor(Color leftLandmarkColor)
|
||||
{
|
||||
_leftLandmarkColor = leftLandmarkColor;
|
||||
}
|
||||
|
||||
public void SetRightLandmarkColor(Color rightLandmarkColor)
|
||||
{
|
||||
_rightLandmarkColor = rightLandmarkColor;
|
||||
}
|
||||
|
||||
public void SetLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
_landmarkListAnnotation.SetRadius(landmarkRadius);
|
||||
}
|
||||
|
||||
public void SetConnectionColor(Color connectionColor)
|
||||
{
|
||||
_connectionListAnnotation.SetColor(connectionColor);
|
||||
}
|
||||
|
||||
public void SetConnectionWidth(float connectionWidth)
|
||||
{
|
||||
_connectionListAnnotation.SetLineWidth(connectionWidth);
|
||||
}
|
||||
|
||||
public void SetHandedness(Hand handedness)
|
||||
{
|
||||
if (handedness == Hand.Left)
|
||||
{
|
||||
_landmarkListAnnotation.SetColor(_leftLandmarkColor);
|
||||
}
|
||||
else if (handedness == Hand.Right)
|
||||
{
|
||||
_landmarkListAnnotation.SetColor(_rightLandmarkColor);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHandedness(IList<Classification> handedness)
|
||||
{
|
||||
if (handedness == null || handedness.Count == 0 || handedness[0].Label == "Left")
|
||||
{
|
||||
SetHandedness(Hand.Left);
|
||||
}
|
||||
else if (handedness[0].Label == "Right")
|
||||
{
|
||||
SetHandedness(Hand.Right);
|
||||
}
|
||||
// ignore unknown label
|
||||
}
|
||||
|
||||
public void SetHandedness(ClassificationList handedness)
|
||||
{
|
||||
SetHandedness(handedness.Classification);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_landmarkListAnnotation.Draw(target, visualizeZ);
|
||||
// Draw explicitly because connection annotation's targets remain the same.
|
||||
_connectionListAnnotation.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target?.Landmark, visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: febd88b13c7a8e91b855c9dd35dd65d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _landmarkListAnnotation: {instanceID: 0}
|
||||
- _connectionListAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public interface IHierachicalAnnotation
|
||||
{
|
||||
IHierachicalAnnotation root { get; }
|
||||
Transform transform { get; }
|
||||
RectTransform GetAnnotationLayer();
|
||||
UnityEngine.Rect GetScreenRect();
|
||||
}
|
||||
|
||||
public abstract class HierarchicalAnnotation : MonoBehaviour, IHierachicalAnnotation
|
||||
{
|
||||
private IHierachicalAnnotation _root;
|
||||
public IHierachicalAnnotation root
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
var parentObj = transform.parent == null ? null : transform.parent.gameObject;
|
||||
_root = (parentObj != null && parentObj.TryGetComponent<IHierachicalAnnotation>(out var parent)) ? parent.root : this;
|
||||
}
|
||||
return _root;
|
||||
}
|
||||
protected set => _root = value;
|
||||
}
|
||||
|
||||
public RectTransform GetAnnotationLayer()
|
||||
{
|
||||
return root.transform.parent.gameObject.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
public UnityEngine.Rect GetScreenRect()
|
||||
{
|
||||
return GetAnnotationLayer().rect;
|
||||
}
|
||||
|
||||
public bool isActive => gameObject.activeSelf;
|
||||
public bool isActiveInHierarchy => gameObject.activeInHierarchy;
|
||||
|
||||
public void SetActive(bool isActive)
|
||||
{
|
||||
if (this.isActive != isActive)
|
||||
{
|
||||
gameObject.SetActive(isActive);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare to annotate <paramref name="target" />.
|
||||
/// If <paramref name="target" /> is not null, it activates itself.
|
||||
/// </summary>
|
||||
/// <return>
|
||||
/// If it is activated and <paramref name="target" /> can be drawn.
|
||||
/// In effect, it returns if <paramref name="target" /> is null or not.
|
||||
/// </return>
|
||||
/// <param name="target">Data to be annotated</param>
|
||||
protected bool ActivateFor<T>(T target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
SetActive(false);
|
||||
return false;
|
||||
}
|
||||
SetActive(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool isMirrored { get; set; }
|
||||
public virtual RotationAngle rotationAngle { get; set; } = RotationAngle.Rotation0;
|
||||
|
||||
protected TAnnotation InstantiateChild<TAnnotation>(GameObject prefab) where TAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
var annotation = Instantiate(prefab, transform).GetComponent<TAnnotation>();
|
||||
annotation.isMirrored = isMirrored;
|
||||
annotation.rotationAngle = rotationAngle;
|
||||
return annotation;
|
||||
}
|
||||
|
||||
protected TAnnotation InstantiateChild<TAnnotation>(string name = "Game Object") where TAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
var gameObject = new GameObject(name);
|
||||
gameObject.transform.SetParent(transform);
|
||||
|
||||
return gameObject.AddComponent<TAnnotation>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 167652b13248a643192ac447671499d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public sealed class HolisticLandmarkListAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private FaceLandmarkListWithIrisAnnotation _faceLandmarkListAnnotation;
|
||||
[SerializeField] private PoseLandmarkListAnnotation _poseLandmarkListAnnotation;
|
||||
[SerializeField] private HandLandmarkListAnnotation _leftHandLandmarkListAnnotation;
|
||||
[SerializeField] private HandLandmarkListAnnotation _rightHandLandmarkListAnnotation;
|
||||
[SerializeField] private ConnectionListAnnotation _connectionListAnnotation;
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_faceLandmarkListAnnotation.isMirrored = value;
|
||||
_poseLandmarkListAnnotation.isMirrored = value;
|
||||
_leftHandLandmarkListAnnotation.isMirrored = value;
|
||||
_rightHandLandmarkListAnnotation.isMirrored = value;
|
||||
_connectionListAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_faceLandmarkListAnnotation.rotationAngle = value;
|
||||
_poseLandmarkListAnnotation.rotationAngle = value;
|
||||
_leftHandLandmarkListAnnotation.rotationAngle = value;
|
||||
_rightHandLandmarkListAnnotation.rotationAngle = value;
|
||||
_connectionListAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_leftHandLandmarkListAnnotation.SetHandedness(HandLandmarkListAnnotation.Hand.Left);
|
||||
_rightHandLandmarkListAnnotation.SetHandedness(HandLandmarkListAnnotation.Hand.Right);
|
||||
_connectionListAnnotation.Fill(2); // left/right wrist joint
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> faceLandmarks, IList<NormalizedLandmark> poseLandmarks,
|
||||
IList<NormalizedLandmark> leftHandLandmarks, IList<NormalizedLandmark> rightHandLandmarks, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
var mask = PoseLandmarkListAnnotation.BodyParts.All;
|
||||
if (faceLandmarks != null)
|
||||
{
|
||||
mask ^= PoseLandmarkListAnnotation.BodyParts.Face;
|
||||
}
|
||||
if (leftHandLandmarks != null)
|
||||
{
|
||||
mask ^= PoseLandmarkListAnnotation.BodyParts.LeftHand;
|
||||
}
|
||||
if (rightHandLandmarks != null)
|
||||
{
|
||||
mask ^= PoseLandmarkListAnnotation.BodyParts.RightHand;
|
||||
}
|
||||
_faceLandmarkListAnnotation.Draw(faceLandmarks, visualizeZ, circleVertices);
|
||||
_poseLandmarkListAnnotation.Draw(poseLandmarks, mask, visualizeZ);
|
||||
_leftHandLandmarkListAnnotation.Draw(leftHandLandmarks, visualizeZ);
|
||||
_rightHandLandmarkListAnnotation.Draw(rightHandLandmarks, visualizeZ);
|
||||
RedrawWristJoints();
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList faceLandmarks, NormalizedLandmarkList poseLandmarks,
|
||||
NormalizedLandmarkList leftHandLandmarks, NormalizedLandmarkList rightHandLandmarks, bool visualizeZ = false, int circleVertices = 128)
|
||||
{
|
||||
Draw(
|
||||
faceLandmarks?.Landmark,
|
||||
poseLandmarks?.Landmark,
|
||||
leftHandLandmarks?.Landmark,
|
||||
rightHandLandmarks?.Landmark,
|
||||
visualizeZ,
|
||||
circleVertices
|
||||
);
|
||||
}
|
||||
|
||||
private void RedrawWristJoints()
|
||||
{
|
||||
if (_connectionListAnnotation[0].isEmpty)
|
||||
{
|
||||
// connect left elbow and wrist
|
||||
_connectionListAnnotation[0].Draw(new Connection(_poseLandmarkListAnnotation[13], _leftHandLandmarkListAnnotation[0]));
|
||||
}
|
||||
if (_connectionListAnnotation[1].isEmpty)
|
||||
{
|
||||
// connect right elbow and wrist
|
||||
_connectionListAnnotation[1].Draw(new Connection(_poseLandmarkListAnnotation[14], _rightHandLandmarkListAnnotation[0]));
|
||||
}
|
||||
_connectionListAnnotation.Redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8778d2c5de1025526bb9fccf445db529
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _faceLandmarkListAnnotation: {instanceID: 0}
|
||||
- _poseLandmarkListAnnotation: {instanceID: 0}
|
||||
- _leftHandLandmarkListAnnotation: {instanceID: 0}
|
||||
- _rightHandLandmarkListAnnotation: {instanceID: 0}
|
||||
- _leftIrisLandmarkListAnnotation: {instanceID: 0}
|
||||
- _rightIrisLandmarkListAnnotation: {instanceID: 0}
|
||||
- _connectionListAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class HolisticLandmarkListAnnotationController : AnnotationController<HolisticLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
[SerializeField] private int _circleVertices = 128;
|
||||
|
||||
private IList<NormalizedLandmark> _currentFaceLandmarkList;
|
||||
private IList<NormalizedLandmark> _currentPoseLandmarkList;
|
||||
private IList<NormalizedLandmark> _currentLeftHandLandmarkList;
|
||||
private IList<NormalizedLandmark> _currentRightHandLandmarkList;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmark> faceLandmarkList, IList<NormalizedLandmark> poseLandmarkList,
|
||||
IList<NormalizedLandmark> leftHandLandmarkList, IList<NormalizedLandmark> rightHandLandmarkList)
|
||||
{
|
||||
_currentFaceLandmarkList = faceLandmarkList;
|
||||
_currentPoseLandmarkList = poseLandmarkList;
|
||||
_currentLeftHandLandmarkList = leftHandLandmarkList;
|
||||
_currentRightHandLandmarkList = rightHandLandmarkList;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(NormalizedLandmarkList faceLandmarkList, NormalizedLandmarkList poseLandmarkList,
|
||||
NormalizedLandmarkList leftHandLandmarkList, NormalizedLandmarkList rightHandLandmarkList)
|
||||
{
|
||||
DrawNow(
|
||||
faceLandmarkList?.Landmark,
|
||||
poseLandmarkList?.Landmark,
|
||||
leftHandLandmarkList?.Landmark,
|
||||
rightHandLandmarkList?.Landmark
|
||||
);
|
||||
}
|
||||
|
||||
public void DrawFaceLandmarkListLater(IList<NormalizedLandmark> faceLandmarkList)
|
||||
{
|
||||
UpdateCurrentTarget(faceLandmarkList, ref _currentFaceLandmarkList);
|
||||
}
|
||||
|
||||
public void DrawFaceLandmarkListLater(NormalizedLandmarkList faceLandmarkList)
|
||||
{
|
||||
DrawFaceLandmarkListLater(faceLandmarkList?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawPoseLandmarkListLater(IList<NormalizedLandmark> poseLandmarkList)
|
||||
{
|
||||
UpdateCurrentTarget(poseLandmarkList, ref _currentPoseLandmarkList);
|
||||
}
|
||||
|
||||
public void DrawPoseLandmarkListLater(NormalizedLandmarkList poseLandmarkList)
|
||||
{
|
||||
DrawPoseLandmarkListLater(poseLandmarkList?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawLeftHandLandmarkListLater(IList<NormalizedLandmark> leftHandLandmarkList)
|
||||
{
|
||||
UpdateCurrentTarget(leftHandLandmarkList, ref _currentLeftHandLandmarkList);
|
||||
}
|
||||
|
||||
public void DrawLeftHandLandmarkListLater(NormalizedLandmarkList leftHandLandmarkList)
|
||||
{
|
||||
DrawLeftHandLandmarkListLater(leftHandLandmarkList?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawRightHandLandmarkListLater(IList<NormalizedLandmark> rightHandLandmarkList)
|
||||
{
|
||||
UpdateCurrentTarget(rightHandLandmarkList, ref _currentRightHandLandmarkList);
|
||||
}
|
||||
|
||||
public void DrawRightHandLandmarkListLater(NormalizedLandmarkList rightHandLandmarkList)
|
||||
{
|
||||
DrawRightHandLandmarkListLater(rightHandLandmarkList?.Landmark);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(
|
||||
_currentFaceLandmarkList,
|
||||
_currentPoseLandmarkList,
|
||||
_currentLeftHandLandmarkList,
|
||||
_currentRightHandLandmarkList,
|
||||
_visualizeZ,
|
||||
_circleVertices
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d476bc13b66983ac4b7ac1f48fb6aff9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class IrisLandmarkListAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private PointListAnnotation _landmarkListAnnotation;
|
||||
[SerializeField] private CircleAnnotation _circleAnnotation;
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.isMirrored = value;
|
||||
_circleAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.rotationAngle = value;
|
||||
_circleAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLandmarkColor(Color landmarkColor)
|
||||
{
|
||||
_landmarkListAnnotation.SetColor(landmarkColor);
|
||||
}
|
||||
|
||||
public void SetLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
_landmarkListAnnotation.SetRadius(landmarkRadius);
|
||||
}
|
||||
|
||||
public void SetCircleColor(Color circleColor)
|
||||
{
|
||||
_circleAnnotation.SetColor(circleColor);
|
||||
}
|
||||
|
||||
public void SetCircleWidth(float circleWidth)
|
||||
{
|
||||
_circleAnnotation.SetLineWidth(circleWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, bool visualizeZ = false, int vertices = 128)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_landmarkListAnnotation.Draw(target, visualizeZ);
|
||||
|
||||
var rect = GetScreenRect();
|
||||
var center = rect.GetPoint(target[0], rotationAngle, isMirrored);
|
||||
if (!visualizeZ)
|
||||
{
|
||||
center.z = 0.0f;
|
||||
}
|
||||
var radius = CalculateRadius(rect, target);
|
||||
_circleAnnotation.Draw(center, radius, vertices);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, bool visualizeZ = false, int vertices = 128)
|
||||
{
|
||||
Draw(target?.Landmark, visualizeZ, vertices);
|
||||
}
|
||||
|
||||
private float CalculateRadius(UnityEngine.Rect rect, IList<NormalizedLandmark> target)
|
||||
{
|
||||
var r1 = CalculateDistance(rect, target[1], target[3]);
|
||||
var r2 = CalculateDistance(rect, target[2], target[4]);
|
||||
return (r1 + r2) / 4;
|
||||
}
|
||||
|
||||
private float CalculateDistance(UnityEngine.Rect rect, NormalizedLandmark a, NormalizedLandmark b)
|
||||
{
|
||||
var aPos = rect.GetPoint(a, rotationAngle, isMirrored);
|
||||
var bPos = rect.GetPoint(b, rotationAngle, isMirrored);
|
||||
aPos.z = 0.0f;
|
||||
bPos.z = 0.0f;
|
||||
return Vector3.Distance(aPos, bPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1663d4d6a7ce17fdbad3dcb3e667ee85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _landmarkListAnnotation: {instanceID: 0}
|
||||
- _circleAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class LabelAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private Text _labelText;
|
||||
[SerializeField] private Transform _backgroundTransform;
|
||||
|
||||
public void Draw(string text, Vector3 position, Color color, float maxWidth, float maxHeight)
|
||||
{
|
||||
if (ActivateFor(text))
|
||||
{
|
||||
// move to the front to show background plane.
|
||||
_labelText.transform.localPosition = new Vector3(position.x, position.y, -1);
|
||||
_labelText.transform.localRotation = Quaternion.Euler(0, 0, -(int)rotationAngle);
|
||||
_labelText.text = text;
|
||||
_labelText.color = DecideTextColor(color);
|
||||
_labelText.fontSize = GetFontSize(text, maxWidth, Mathf.Min(maxHeight, 48.0f));
|
||||
|
||||
var width = Mathf.Min(_labelText.preferredWidth + 24, maxWidth); // add margin
|
||||
var height = _labelText.preferredHeight;
|
||||
var rectTransform = _labelText.GetComponent<RectTransform>();
|
||||
rectTransform.sizeDelta = new Vector2(width, height);
|
||||
|
||||
_backgroundTransform.localScale = new Vector3(width / 10, 1, height / 10);
|
||||
_backgroundTransform.gameObject.GetComponent<Renderer>().material.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetFontSize(string text, float maxWidth, float maxHeight)
|
||||
{
|
||||
var ch = Mathf.Min(maxWidth / text.Length, maxHeight);
|
||||
return (int)Mathf.Clamp(ch, 24.0f, 72.0f);
|
||||
}
|
||||
|
||||
private Color DecideTextColor(Color backgroundColor)
|
||||
{
|
||||
var lw = CalcContrastRatio(Color.white, backgroundColor);
|
||||
var lb = CalcContrastRatio(backgroundColor, Color.black);
|
||||
return lw < lb ? Color.black : Color.white;
|
||||
}
|
||||
|
||||
private float CalcRelativeLuminance(Color color)
|
||||
{
|
||||
var r = color.r <= 0.03928f ? color.r / 12.92f : Mathf.Pow((color.r + 0.055f) / 1.055f, 2.4f);
|
||||
var g = color.g <= 0.03928f ? color.g / 12.92f : Mathf.Pow((color.g + 0.055f) / 1.055f, 2.4f);
|
||||
var b = color.b <= 0.03928f ? color.b / 12.92f : Mathf.Pow((color.b + 0.055f) / 1.055f, 2.4f);
|
||||
return (0.2126f * r) + (0.7152f * g) + (0.0722f * b);
|
||||
}
|
||||
|
||||
private float CalcContrastRatio(Color lighter, Color darker)
|
||||
{
|
||||
var l1 = CalcRelativeLuminance(lighter);
|
||||
var l2 = CalcRelativeLuminance(darker);
|
||||
return (l1 + 0.05f) / (l2 + 0.05f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96652e94527a9f3e1b4079bc3d139d06
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class LineAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private LineRenderer _lineRenderer;
|
||||
[SerializeField] private Color _color = Color.green;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ApplyLineWidth(0.0f);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(_color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
public void Draw(Vector3 a, Vector3 b)
|
||||
{
|
||||
_lineRenderer.SetPositions(new Vector3[] { a, b });
|
||||
}
|
||||
|
||||
public void Draw(GameObject a, GameObject b)
|
||||
{
|
||||
_lineRenderer.SetPositions(new Vector3[] { a.transform.localPosition, b.transform.localPosition });
|
||||
}
|
||||
|
||||
public void ApplyColor(Color color)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startColor = color;
|
||||
_lineRenderer.endColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startWidth = lineWidth;
|
||||
_lineRenderer.endWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6253cad9b27173aaaf2b82ac82f421c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public abstract class ListAnnotation<T> : HierarchicalAnnotation where T : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private GameObject _annotationPrefab;
|
||||
|
||||
private List<T> _children;
|
||||
protected List<T> children
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_children == null)
|
||||
{
|
||||
_children = new List<T>();
|
||||
}
|
||||
return _children;
|
||||
}
|
||||
}
|
||||
|
||||
public T this[int index] => children[index];
|
||||
|
||||
public int count => children.Count;
|
||||
|
||||
public void Fill(int count)
|
||||
{
|
||||
while (children.Count < count)
|
||||
{
|
||||
children.Add(InstantiateChild(false));
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(T element)
|
||||
{
|
||||
children.Add(element);
|
||||
}
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
child.isMirrored = value;
|
||||
}
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
child.rotationAngle = value;
|
||||
}
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Destroy()
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
Destroy(child);
|
||||
}
|
||||
_children = null;
|
||||
}
|
||||
|
||||
protected virtual T InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = InstantiateChild<T>(_annotationPrefab);
|
||||
annotation.SetActive(isActive);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zip <see cref="children" /> and <paramref name="argumentList" />, and call <paramref name="action" /> with each pair.
|
||||
/// If <paramref name="argumentList" /> has more elements than <see cref="children" />, <see cref="children" /> elements will be initialized with <see cref="InstantiateChild" />.
|
||||
/// </summary>
|
||||
/// <param name="action">
|
||||
/// This will receive 2 arguments and return void.
|
||||
/// The 1st argument is <typeparamref name="T" />, that is an ith element in <see cref="children" />.
|
||||
/// The 2nd argument is <typeparamref name="TArg" />, that is also an ith element in <paramref name="argumentList" />.
|
||||
/// </param>
|
||||
protected void CallActionForAll<TArg>(IList<TArg> argumentList, Action<T, TArg> action)
|
||||
{
|
||||
for (var i = 0; i < Mathf.Max(children.Count, argumentList.Count); i++)
|
||||
{
|
||||
if (i >= argumentList.Count)
|
||||
{
|
||||
// children.Count > argumentList.Count
|
||||
action(children[i], default);
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset annotations
|
||||
if (i >= children.Count)
|
||||
{
|
||||
// children.Count < argumentList.Count
|
||||
children.Add(InstantiateChild());
|
||||
}
|
||||
else if (children[i] == null)
|
||||
{
|
||||
// child is not initialized yet
|
||||
children[i] = InstantiateChild();
|
||||
}
|
||||
action(children[i], argumentList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab5e576d5ced309e9a79c434be1a9741
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class MaskAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private RawImage _screen;
|
||||
[SerializeField] private Shader _maskShader;
|
||||
[SerializeField] private Texture2D _maskTexture;
|
||||
[SerializeField] private Color _color = Color.blue;
|
||||
[SerializeField, Range(0, 1)] private float _threshold = 0.9f;
|
||||
|
||||
private Material _prevMaterial;
|
||||
private Material _material;
|
||||
private GraphicsBuffer _maskBuffer;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyMaskTexture(_maskTexture, _color);
|
||||
ApplyThreshold(_threshold);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (_prevMaterial != null)
|
||||
{
|
||||
ApplyMaterial(_prevMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyMaskTexture(_maskTexture, _color);
|
||||
ApplyThreshold(_threshold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_maskBuffer != null)
|
||||
{
|
||||
_maskBuffer.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(int width, int height)
|
||||
{
|
||||
_material = new Material(_maskShader)
|
||||
{
|
||||
renderQueue = (int)RenderQueue.Transparent
|
||||
};
|
||||
|
||||
_material.SetTexture("_MainTex", _screen.texture);
|
||||
ApplyMaskTexture(_maskTexture, _color);
|
||||
_material.SetInt("_Width", width);
|
||||
_material.SetInt("_Height", height);
|
||||
ApplyThreshold(_threshold);
|
||||
InitMaskBuffer(width, height);
|
||||
}
|
||||
|
||||
public void Draw(float[] mask, int width, int height)
|
||||
{
|
||||
if (mask == null)
|
||||
{
|
||||
ApplyMaterial(_prevMaterial);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask.Length != width * height)
|
||||
{
|
||||
throw new ArgumentException("mask size must equal width * height");
|
||||
}
|
||||
|
||||
ApplyMaterial(_material);
|
||||
_maskBuffer.SetData(mask);
|
||||
}
|
||||
|
||||
private Texture2D CreateMonoColorTexture(Color color)
|
||||
{
|
||||
var texture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
|
||||
var textureColor = new Color32((byte)(255 * color.r), (byte)(255 * color.g), (byte)(255 * color.b), (byte)(255 * color.a));
|
||||
texture.SetPixels32(new Color32[] { textureColor });
|
||||
texture.Apply();
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
private void InitMaskBuffer(int width, int height)
|
||||
{
|
||||
if (_maskBuffer != null)
|
||||
{
|
||||
_maskBuffer.Release();
|
||||
}
|
||||
var stride = Marshal.SizeOf(typeof(float));
|
||||
_maskBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, width * height, stride);
|
||||
_material.SetBuffer("_MaskBuffer", _maskBuffer);
|
||||
}
|
||||
|
||||
private void ApplyMaterial(Material material)
|
||||
{
|
||||
if (_prevMaterial == null)
|
||||
{
|
||||
// backup
|
||||
_prevMaterial = _screen.material;
|
||||
}
|
||||
if (_screen.material != material)
|
||||
{
|
||||
_screen.material = material;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyMaskTexture(Texture maskTexture, Color maskColor)
|
||||
{
|
||||
if (_material != null)
|
||||
{
|
||||
_material.SetTexture("_MaskTex", maskTexture == null ? CreateMonoColorTexture(maskColor) : maskTexture);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyThreshold(float threshold)
|
||||
{
|
||||
if (_material != null)
|
||||
{
|
||||
_material.SetFloat("_Threshold", threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f993d16dcccfcecb6892ad3cc2ea76c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class MaskAnnotationController : AnnotationController<MaskAnnotation>
|
||||
{
|
||||
private int _maskWidth;
|
||||
private int _maskHeight;
|
||||
|
||||
private ImageFrame _currentTarget;
|
||||
private float[] _maskArray;
|
||||
|
||||
public void InitScreen(int maskWidth, int maskHeight)
|
||||
{
|
||||
_maskWidth = maskWidth;
|
||||
_maskHeight = maskHeight;
|
||||
_maskArray = new float[_maskWidth * _maskHeight];
|
||||
annotation.Init(_maskWidth, _maskHeight);
|
||||
}
|
||||
|
||||
public void DrawNow(ImageFrame target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
UpdateMaskArray(_currentTarget);
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(ImageFrame target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
UpdateMaskArray(_currentTarget);
|
||||
}
|
||||
|
||||
private void UpdateMaskArray(ImageFrame imageFrame)
|
||||
{
|
||||
if (imageFrame != null)
|
||||
{
|
||||
// NOTE: assume that the image is transformed properly by calculators.
|
||||
var _ = imageFrame.TryReadChannelNormalized(0, _maskArray);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget == null ? null : _maskArray, _maskWidth, _maskHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ece564ad16755f1ef94c4fe04bd7ce2e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class MultiFaceLandmarkListAnnotation : ListAnnotation<FaceLandmarkListWithIrisAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _faceLandmarkColor = Color.green;
|
||||
[SerializeField] private Color _irisLandmarkColor = Color.yellow;
|
||||
[SerializeField] private float _faceLandmarkRadius = 10.0f;
|
||||
[SerializeField] private float _irisLandmarkRadius = 10.0f;
|
||||
[SerializeField] private Color _faceConnectionColor = Color.red;
|
||||
[SerializeField] private Color _irisCircleColor = Color.blue;
|
||||
[SerializeField, Range(0, 1)] private float _faceConnectionWidth = 1.0f;
|
||||
[SerializeField, Range(0, 1)] private float _irisCircleWidth = 1.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyFaceLandmarkColor(_faceLandmarkColor);
|
||||
ApplyIrisLandmarkColor(_irisLandmarkColor);
|
||||
ApplyFaceLandmarkRadius(_faceLandmarkRadius);
|
||||
ApplyIrisLandmarkRadius(_irisLandmarkRadius);
|
||||
ApplyFaceConnectionColor(_faceConnectionColor);
|
||||
ApplyIrisCircleColor(_irisCircleColor);
|
||||
ApplyFaceConnectionWidth(_faceConnectionWidth);
|
||||
ApplyIrisCircleWidth(_irisCircleWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetFaceLandmarkRadius(float radius)
|
||||
{
|
||||
_faceLandmarkRadius = radius;
|
||||
ApplyFaceLandmarkRadius(_faceLandmarkRadius);
|
||||
}
|
||||
|
||||
public void SetIrisLandmarkRadius(float radius)
|
||||
{
|
||||
_irisLandmarkRadius = radius;
|
||||
ApplyIrisLandmarkRadius(_irisLandmarkRadius);
|
||||
}
|
||||
|
||||
public void SetFaceLandmarkColor(Color color)
|
||||
{
|
||||
_faceLandmarkColor = color;
|
||||
ApplyFaceLandmarkColor(_faceLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetIrisLandmarkColor(Color color)
|
||||
{
|
||||
_irisLandmarkColor = color;
|
||||
ApplyIrisLandmarkColor(_irisLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetFaceConnectionWidth(float width)
|
||||
{
|
||||
_faceConnectionWidth = width;
|
||||
ApplyFaceConnectionWidth(_faceConnectionWidth);
|
||||
}
|
||||
|
||||
public void SetFaceConnectionColor(Color color)
|
||||
{
|
||||
_faceConnectionColor = color;
|
||||
ApplyFaceConnectionColor(_faceConnectionColor);
|
||||
}
|
||||
|
||||
public void SetIrisCircleWidth(float width)
|
||||
{
|
||||
_irisCircleWidth = width;
|
||||
ApplyIrisCircleWidth(_irisCircleWidth);
|
||||
}
|
||||
|
||||
public void SetIrisCircleColor(Color color)
|
||||
{
|
||||
_irisCircleColor = color;
|
||||
ApplyIrisCircleColor(_irisCircleColor);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmarkList> targets, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override FaceLandmarkListWithIrisAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetFaceLandmarkRadius(_faceLandmarkRadius);
|
||||
annotation.SetIrisLandmarkRadius(_irisLandmarkRadius);
|
||||
annotation.SetFaceLandmarkColor(_faceLandmarkColor);
|
||||
annotation.SetIrisLandmarkColor(_irisLandmarkColor);
|
||||
annotation.SetFaceConnectionWidth(_faceConnectionWidth);
|
||||
annotation.SetFaceConnectionColor(_faceConnectionColor);
|
||||
annotation.SetIrisCircleWidth(_irisCircleWidth);
|
||||
annotation.SetIrisCircleColor(_irisCircleColor);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyFaceLandmarkRadius(float radius)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetFaceLandmarkRadius(radius); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyIrisLandmarkRadius(float radius)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetIrisLandmarkRadius(radius); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFaceLandmarkColor(Color color)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetFaceLandmarkColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyIrisLandmarkColor(Color color)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetIrisLandmarkColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFaceConnectionWidth(float width)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetFaceConnectionWidth(width); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFaceConnectionColor(Color color)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetFaceConnectionColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyIrisCircleWidth(float width)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetIrisCircleWidth(width); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyIrisCircleColor(Color color)
|
||||
{
|
||||
foreach (var faceLandmarkList in children)
|
||||
{
|
||||
if (faceLandmarkList != null) { faceLandmarkList.SetIrisCircleColor(color); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1ec0e202f29d7ee28cccba68415d95b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 7273100862690186831, guid: 16074ce928b0558829296ab0d9ccadf3,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class MultiFaceLandmarkListAnnotationController : AnnotationController<MultiFaceLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
|
||||
private IList<NormalizedLandmarkList> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmarkList> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmarkList> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417bb930807ba51e9bfcc5d0e24ef3ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class MultiHandLandmarkListAnnotation : ListAnnotation<HandLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _leftLandmarkColor = Color.green;
|
||||
[SerializeField] private Color _rightLandmarkColor = Color.green;
|
||||
[SerializeField] private float _landmarkRadius = 15.0f;
|
||||
[SerializeField] private Color _connectionColor = Color.white;
|
||||
[SerializeField, Range(0, 1)] private float _connectionWidth = 1.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyLeftLandmarkColor(_leftLandmarkColor);
|
||||
ApplyRightLandmarkColor(_rightLandmarkColor);
|
||||
ApplyLandmarkRadius(_landmarkRadius);
|
||||
ApplyConnectionColor(_connectionColor);
|
||||
ApplyConnectionWidth(_connectionWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetLeftLandmarkColor(Color leftLandmarkColor)
|
||||
{
|
||||
_leftLandmarkColor = leftLandmarkColor;
|
||||
ApplyLeftLandmarkColor(_leftLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetRightLandmarkColor(Color rightLandmarkColor)
|
||||
{
|
||||
_rightLandmarkColor = rightLandmarkColor;
|
||||
ApplyRightLandmarkColor(_rightLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
_landmarkRadius = landmarkRadius;
|
||||
ApplyLandmarkRadius(_landmarkRadius);
|
||||
}
|
||||
|
||||
public void SetConnectionColor(Color connectionColor)
|
||||
{
|
||||
_connectionColor = connectionColor;
|
||||
ApplyConnectionColor(_connectionColor);
|
||||
}
|
||||
|
||||
public void SetConnectionWidth(float connectionWidth)
|
||||
{
|
||||
_connectionWidth = connectionWidth;
|
||||
ApplyConnectionWidth(_connectionWidth);
|
||||
}
|
||||
|
||||
public void SetHandedness(IList<ClassificationList> handedness)
|
||||
{
|
||||
var count = handedness == null ? 0 : handedness.Count;
|
||||
for (var i = 0; i < Mathf.Min(count, children.Count); i++)
|
||||
{
|
||||
children[i].SetHandedness(handedness[i]);
|
||||
}
|
||||
for (var i = count; i < children.Count; i++)
|
||||
{
|
||||
children[i].SetHandedness((IList<Classification>)null);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmarkList> targets, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override HandLandmarkListAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetLeftLandmarkColor(_leftLandmarkColor);
|
||||
annotation.SetRightLandmarkColor(_rightLandmarkColor);
|
||||
annotation.SetLandmarkRadius(_landmarkRadius);
|
||||
annotation.SetConnectionColor(_connectionColor);
|
||||
annotation.SetConnectionWidth(_connectionWidth);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyLeftLandmarkColor(Color leftLandmarkColor)
|
||||
{
|
||||
foreach (var handLandmarkList in children)
|
||||
{
|
||||
if (handLandmarkList != null) { handLandmarkList.SetLeftLandmarkColor(leftLandmarkColor); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyRightLandmarkColor(Color rightLandmarkColor)
|
||||
{
|
||||
foreach (var handLandmarkList in children)
|
||||
{
|
||||
if (handLandmarkList != null) { handLandmarkList.SetRightLandmarkColor(rightLandmarkColor); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
foreach (var handLandmarkList in children)
|
||||
{
|
||||
if (handLandmarkList != null) { handLandmarkList.SetLandmarkRadius(landmarkRadius); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyConnectionColor(Color connectionColor)
|
||||
{
|
||||
foreach (var handLandmarkList in children)
|
||||
{
|
||||
if (handLandmarkList != null) { handLandmarkList.SetConnectionColor(connectionColor); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyConnectionWidth(float connectionWidth)
|
||||
{
|
||||
foreach (var handLandmarkList in children)
|
||||
{
|
||||
if (handLandmarkList != null) { handLandmarkList.SetConnectionWidth(connectionWidth); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ba3c50c2cb46dc9e916dd3a33c8a488
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 4724242833946851653, guid: b420c3106bd9cc5b6871a7df5459dba0,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class MultiHandLandmarkListAnnotationController : AnnotationController<MultiHandLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
|
||||
private IList<NormalizedLandmarkList> _currentHandLandmarkLists;
|
||||
private IList<ClassificationList> _currentHandedness;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmarkList> handLandmarkLists, IList<ClassificationList> handedness = null)
|
||||
{
|
||||
_currentHandLandmarkLists = handLandmarkLists;
|
||||
_currentHandedness = handedness;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmarkList> handLandmarkLists)
|
||||
{
|
||||
UpdateCurrentTarget(handLandmarkLists, ref _currentHandLandmarkLists);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<ClassificationList> handedness)
|
||||
{
|
||||
UpdateCurrentTarget(handedness, ref _currentHandedness);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentHandLandmarkLists, _visualizeZ);
|
||||
|
||||
if (_currentHandedness != null)
|
||||
{
|
||||
annotation.SetHandedness(_currentHandedness);
|
||||
}
|
||||
_currentHandedness = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3f533a3b3fececba86462b46ff711ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 7434967355688441420, guid: 87a9be2a7620991a78342ef9a56fa62c,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class NormalizedLandmarkListAnnotationController : AnnotationController<PointListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
|
||||
private IList<NormalizedLandmark> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmark> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(NormalizedLandmarkList target)
|
||||
{
|
||||
DrawNow(target?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmarkList> landmarkLists)
|
||||
{
|
||||
DrawNow(FlattenNormalizedLandmarkLists(landmarkLists));
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmark> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(NormalizedLandmarkList target)
|
||||
{
|
||||
UpdateCurrentTarget(target?.Landmark, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmarkList> landmarkLists)
|
||||
{
|
||||
UpdateCurrentTarget(FlattenNormalizedLandmarkLists(landmarkLists), ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _visualizeZ);
|
||||
}
|
||||
|
||||
private IList<NormalizedLandmark> FlattenNormalizedLandmarkLists(IList<NormalizedLandmarkList> landmarkLists)
|
||||
{
|
||||
return landmarkLists?.Select((x) => x.Landmark).SelectMany(x => x).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acbf25ab09c7f4115948d7981b6024c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class NormalizedRectAnnotationController : AnnotationController<RectangleAnnotation>
|
||||
{
|
||||
private NormalizedRect _currentTarget;
|
||||
|
||||
public void DrawNow(NormalizedRect target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(NormalizedRect target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 145060647209d6d1c86b8ccce9fcaf5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class NormalizedRectListAnnotationController : AnnotationController<RectangleListAnnotation>
|
||||
{
|
||||
private IList<NormalizedRect> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<NormalizedRect> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedRect> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f4190c4421f92d5187d2ebdc88a9594
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 9058686056784979840, guid: 94ee148c30d93d3c8aaa3aaf5ab54853,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
using UnityEngine;
|
||||
|
||||
using mplt = Mediapipe.LocationData.Types;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class PointAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private Color _color = Color.green;
|
||||
[SerializeField] private float _radius = 15.0f;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyRadius(_radius);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ApplyRadius(0.0f);
|
||||
}
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(_color);
|
||||
}
|
||||
|
||||
public void SetRadius(float radius)
|
||||
{
|
||||
_radius = radius;
|
||||
ApplyRadius(_radius);
|
||||
}
|
||||
|
||||
public void Draw(Vector3 position)
|
||||
{
|
||||
SetActive(true); // Vector3 is not nullable
|
||||
transform.localPosition = position;
|
||||
}
|
||||
|
||||
public void Draw(Landmark target, Vector3 scale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
var position = GetScreenRect().GetPoint(target, scale, rotationAngle, isMirrored);
|
||||
if (!visualizeZ)
|
||||
{
|
||||
position.z = 0.0f;
|
||||
}
|
||||
transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmark target, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
var position = GetScreenRect().GetPoint(target, rotationAngle, isMirrored);
|
||||
if (!visualizeZ)
|
||||
{
|
||||
position.z = 0.0f;
|
||||
}
|
||||
transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedPoint2D target)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
var position = GetScreenRect().GetPoint(target, rotationAngle, isMirrored);
|
||||
transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(Point3D target, Vector2 focalLength, Vector2 principalPoint, float zScale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
var position = GetScreenRect().GetPoint(target, focalLength, principalPoint, zScale, rotationAngle, isMirrored);
|
||||
if (!visualizeZ)
|
||||
{
|
||||
position.z = 0.0f;
|
||||
}
|
||||
transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(AnnotatedKeyPoint target, Vector2 focalLength, Vector2 principalPoint, float zScale, bool visualizeZ = true)
|
||||
{
|
||||
if (visualizeZ)
|
||||
{
|
||||
Draw(target?.Point3D, focalLength, principalPoint, zScale, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Draw(target?.Point2D);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(mplt.RelativeKeypoint target, float threshold = 0.0f)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
Draw(GetScreenRect().GetPoint(target, rotationAngle, isMirrored));
|
||||
SetColor(GetColor(target.Score, threshold));
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
GetComponent<Renderer>().material.color = color;
|
||||
}
|
||||
|
||||
private void ApplyRadius(float radius)
|
||||
{
|
||||
transform.localScale = radius * Vector3.one;
|
||||
}
|
||||
|
||||
private Color GetColor(float score, float threshold)
|
||||
{
|
||||
var t = (score - threshold) / (1 - threshold);
|
||||
var h = Mathf.Lerp(90, 0, t) / 360; // from yellow-green to red
|
||||
return Color.HSVToRGB(h, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0476f607871e33f2783b582f7a75703c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using mplt = Mediapipe.LocationData.Types;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class PointListAnnotation : ListAnnotation<PointAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _color = Color.green;
|
||||
[SerializeField] private float _radius = 15.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyRadius(_radius);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(_color);
|
||||
}
|
||||
|
||||
public void SetRadius(float radius)
|
||||
{
|
||||
_radius = radius;
|
||||
ApplyRadius(_radius);
|
||||
}
|
||||
|
||||
public void Draw(IList<Vector3> targets)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(IList<Landmark> targets, Vector3 scale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, scale, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(LandmarkList targets, Vector3 scale, bool visualizeZ = true)
|
||||
{
|
||||
Draw(targets.Landmark, scale, visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> targets, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList targets, bool visualizeZ = true)
|
||||
{
|
||||
Draw(targets.Landmark, visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(IList<AnnotatedKeyPoint> targets, Vector2 focalLength, Vector2 principalPoint, float zScale, bool visualizeZ = true)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, focalLength, principalPoint, zScale, visualizeZ); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(IList<mplt.RelativeKeypoint> targets, float threshold = 0.0f)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, threshold); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override PointAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetColor(_color);
|
||||
annotation.SetRadius(_radius);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
foreach (var point in children)
|
||||
{
|
||||
if (point != null) { point.SetColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyRadius(float radius)
|
||||
{
|
||||
foreach (var point in children)
|
||||
{
|
||||
if (point != null) { point.SetRadius(radius); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae7563ab8645734c6b682cbbca130f6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 5105739270100195971, guid: cd50999c161e69345953a2cb517dd339,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,278 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public sealed class PoseLandmarkListAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private PointListAnnotation _landmarkListAnnotation;
|
||||
[SerializeField] private ConnectionListAnnotation _connectionListAnnotation;
|
||||
[SerializeField] private Color _leftLandmarkColor = Color.green;
|
||||
[SerializeField] private Color _rightLandmarkColor = Color.green;
|
||||
|
||||
[Flags]
|
||||
public enum BodyParts : short
|
||||
{
|
||||
None = 0,
|
||||
Face = 1,
|
||||
// Torso = 2,
|
||||
LeftArm = 4,
|
||||
LeftHand = 8,
|
||||
RightArm = 16,
|
||||
RightHand = 32,
|
||||
LowerBody = 64,
|
||||
All = 127,
|
||||
}
|
||||
|
||||
private const int _LandmarkCount = 33;
|
||||
private static readonly int[] _LeftLandmarks = new int[] {
|
||||
1, 2, 3, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
|
||||
};
|
||||
private static readonly int[] _RightLandmarks = new int[] {
|
||||
4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32
|
||||
};
|
||||
private static readonly List<(int, int)> _Connections = new List<(int, int)> {
|
||||
// Left Eye
|
||||
(0, 1),
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(3, 7),
|
||||
// Right Eye
|
||||
(0, 4),
|
||||
(4, 5),
|
||||
(5, 6),
|
||||
(6, 8),
|
||||
// Lips
|
||||
(9, 10),
|
||||
// Left Arm
|
||||
(11, 13),
|
||||
(13, 15),
|
||||
// Left Hand
|
||||
(15, 17),
|
||||
(15, 19),
|
||||
(15, 21),
|
||||
(17, 19),
|
||||
// Right Arm
|
||||
(12, 14),
|
||||
(14, 16),
|
||||
// Right Hand
|
||||
(16, 18),
|
||||
(16, 20),
|
||||
(16, 22),
|
||||
(18, 20),
|
||||
// Torso
|
||||
(11, 12),
|
||||
(12, 24),
|
||||
(24, 23),
|
||||
(23, 11),
|
||||
// Left Leg
|
||||
(23, 25),
|
||||
(25, 27),
|
||||
(27, 29),
|
||||
(27, 31),
|
||||
(29, 31),
|
||||
// Right Leg
|
||||
(24, 26),
|
||||
(26, 28),
|
||||
(28, 30),
|
||||
(28, 32),
|
||||
(30, 32),
|
||||
};
|
||||
|
||||
public override bool isMirrored
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.isMirrored = value;
|
||||
_connectionListAnnotation.isMirrored = value;
|
||||
base.isMirrored = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override RotationAngle rotationAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
_landmarkListAnnotation.rotationAngle = value;
|
||||
_connectionListAnnotation.rotationAngle = value;
|
||||
base.rotationAngle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PointAnnotation this[int index] => _landmarkListAnnotation[index];
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_landmarkListAnnotation.Fill(_LandmarkCount);
|
||||
ApplyLeftLandmarkColor(_leftLandmarkColor);
|
||||
ApplyRightLandmarkColor(_rightLandmarkColor);
|
||||
|
||||
_connectionListAnnotation.Fill(_Connections, _landmarkListAnnotation);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyLeftLandmarkColor(_leftLandmarkColor);
|
||||
ApplyRightLandmarkColor(_rightLandmarkColor);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetLeftLandmarkColor(Color leftLandmarkColor)
|
||||
{
|
||||
_leftLandmarkColor = leftLandmarkColor;
|
||||
ApplyLeftLandmarkColor(_leftLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetRightLandmarkColor(Color rightLandmarkColor)
|
||||
{
|
||||
_rightLandmarkColor = rightLandmarkColor;
|
||||
ApplyRightLandmarkColor(_rightLandmarkColor);
|
||||
}
|
||||
|
||||
public void SetLandmarkRadius(float landmarkRadius)
|
||||
{
|
||||
_landmarkListAnnotation.SetRadius(landmarkRadius);
|
||||
}
|
||||
|
||||
public void SetConnectionColor(Color connectionColor)
|
||||
{
|
||||
_connectionListAnnotation.SetColor(connectionColor);
|
||||
}
|
||||
|
||||
public void SetConnectionWidth(float connectionWidth)
|
||||
{
|
||||
_connectionListAnnotation.SetLineWidth(connectionWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<Landmark> target, Vector3 scale, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_landmarkListAnnotation.Draw(target, scale, visualizeZ);
|
||||
// Draw explicitly because connection annotation's targets remain the same.
|
||||
_connectionListAnnotation.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(LandmarkList target, Vector3 scale, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target?.Landmark, scale, visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, BodyParts mask, bool visualizeZ = false)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
_landmarkListAnnotation.Draw(target, visualizeZ);
|
||||
ApplyMask(mask);
|
||||
// Draw explicitly because connection annotation's targets remain the same.
|
||||
_connectionListAnnotation.Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, BodyParts mask, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target?.Landmark, mask, visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedLandmark> target, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target, BodyParts.All, visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(NormalizedLandmarkList target, bool visualizeZ = false)
|
||||
{
|
||||
Draw(target?.Landmark, BodyParts.All, visualizeZ);
|
||||
}
|
||||
|
||||
private void ApplyLeftLandmarkColor(Color color)
|
||||
{
|
||||
var annotationCount = _landmarkListAnnotation == null ? 0 : _landmarkListAnnotation.count;
|
||||
if (annotationCount >= _LandmarkCount)
|
||||
{
|
||||
foreach (var index in _LeftLandmarks)
|
||||
{
|
||||
_landmarkListAnnotation[index].SetColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyRightLandmarkColor(Color color)
|
||||
{
|
||||
var annotationCount = _landmarkListAnnotation == null ? 0 : _landmarkListAnnotation.count;
|
||||
if (annotationCount >= _LandmarkCount)
|
||||
{
|
||||
foreach (var index in _RightLandmarks)
|
||||
{
|
||||
_landmarkListAnnotation[index].SetColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyMask(BodyParts mask)
|
||||
{
|
||||
if (mask == BodyParts.All)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mask.HasFlag(BodyParts.Face))
|
||||
{
|
||||
// deactivate face landmarks
|
||||
for (var i = 0; i <= 10; i++)
|
||||
{
|
||||
_landmarkListAnnotation[i].SetActive(false);
|
||||
}
|
||||
}
|
||||
if (!mask.HasFlag(BodyParts.LeftArm))
|
||||
{
|
||||
// deactivate left elbow to hide left arm
|
||||
_landmarkListAnnotation[13].SetActive(false);
|
||||
}
|
||||
if (!mask.HasFlag(BodyParts.LeftHand))
|
||||
{
|
||||
// deactive left wrist, thumb, index and pinky to hide left hand
|
||||
_landmarkListAnnotation[15].SetActive(false);
|
||||
_landmarkListAnnotation[17].SetActive(false);
|
||||
_landmarkListAnnotation[19].SetActive(false);
|
||||
_landmarkListAnnotation[21].SetActive(false);
|
||||
}
|
||||
if (!mask.HasFlag(BodyParts.RightArm))
|
||||
{
|
||||
// deactivate right elbow to hide right arm
|
||||
_landmarkListAnnotation[14].SetActive(false);
|
||||
}
|
||||
if (!mask.HasFlag(BodyParts.RightHand))
|
||||
{
|
||||
// deactivate right wrist, thumb, index and pinky to hide right hand
|
||||
_landmarkListAnnotation[16].SetActive(false);
|
||||
_landmarkListAnnotation[18].SetActive(false);
|
||||
_landmarkListAnnotation[20].SetActive(false);
|
||||
_landmarkListAnnotation[22].SetActive(false);
|
||||
}
|
||||
if (!mask.HasFlag(BodyParts.LowerBody))
|
||||
{
|
||||
// deactivate lower body landmarks
|
||||
for (var i = 25; i <= 32; i++)
|
||||
{
|
||||
_landmarkListAnnotation[i].SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39bac9dd52c31ae7aa01a7383bc44853
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _landmarkListAnnotation: {instanceID: 0}
|
||||
- _connectionListAnnotation: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class PoseLandmarkListAnnotationController : AnnotationController<PoseLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private bool _visualizeZ = false;
|
||||
|
||||
private IList<NormalizedLandmark> _currentTarget;
|
||||
|
||||
public void DrawNow(IList<NormalizedLandmark> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(NormalizedLandmarkList target)
|
||||
{
|
||||
DrawNow(target?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<NormalizedLandmark> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(NormalizedLandmarkList target)
|
||||
{
|
||||
DrawLater(target?.Landmark);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70c2b36b394190968977c6493e60e0af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 1915238444563462411, guid: 4418f6a92856c5b51b58a36e3be7ed5c,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public class PoseWorldLandmarkListAnnotationController : AnnotationController<PoseLandmarkListAnnotation>
|
||||
{
|
||||
[SerializeField] private float _hipHeightMeter = 0.9f;
|
||||
[SerializeField] private Vector3 _scale = new Vector3(100, 100, 100);
|
||||
[SerializeField] private bool _visualizeZ = true;
|
||||
|
||||
private IList<Landmark> _currentTarget;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
transform.localPosition = new Vector3(0, _hipHeightMeter * _scale.y, 0);
|
||||
}
|
||||
|
||||
public void DrawNow(IList<Landmark> target)
|
||||
{
|
||||
_currentTarget = target;
|
||||
SyncNow();
|
||||
}
|
||||
|
||||
public void DrawNow(LandmarkList target)
|
||||
{
|
||||
DrawNow(target?.Landmark);
|
||||
}
|
||||
|
||||
public void DrawLater(IList<Landmark> target)
|
||||
{
|
||||
UpdateCurrentTarget(target, ref _currentTarget);
|
||||
}
|
||||
|
||||
public void DrawLater(LandmarkList target)
|
||||
{
|
||||
DrawLater(target?.Landmark);
|
||||
}
|
||||
|
||||
protected override void SyncNow()
|
||||
{
|
||||
isStale = false;
|
||||
annotation.Draw(_currentTarget, _scale, _visualizeZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f152430ce9da8f9f2ae5cfd135b4d061
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- annotationPrefab: {fileID: 8684491236681850282, guid: e076022eee6a6227698c34a5ba1d25ea,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
using UnityEngine;
|
||||
|
||||
using mplt = Mediapipe.LocationData.Types;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class RectangleAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private LineRenderer _lineRenderer;
|
||||
[SerializeField] private Color _color = Color.red;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
private static readonly Vector3[] _EmptyPositions = new Vector3[] { Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ApplyLineWidth(0.0f);
|
||||
_lineRenderer.SetPositions(_EmptyPositions);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(_color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
public void Draw(Vector3[] positions)
|
||||
{
|
||||
_lineRenderer.SetPositions(positions ?? _EmptyPositions);
|
||||
}
|
||||
|
||||
public void Draw(Rect target, Vector2Int imageSize)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
Draw(GetScreenRect().GetRectVertices(target, imageSize, rotationAngle, isMirrored));
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NormalizedRect target)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
Draw(GetScreenRect().GetRectVertices(target, rotationAngle, isMirrored));
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(LocationData target, Vector2Int imageSize)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
switch (target.Format)
|
||||
{
|
||||
case mplt.Format.BoundingBox:
|
||||
{
|
||||
Draw(GetScreenRect().GetRectVertices(target.BoundingBox, imageSize, rotationAngle, isMirrored));
|
||||
break;
|
||||
}
|
||||
case mplt.Format.RelativeBoundingBox:
|
||||
{
|
||||
Draw(GetScreenRect().GetRectVertices(target.RelativeBoundingBox, rotationAngle, isMirrored));
|
||||
break;
|
||||
}
|
||||
case mplt.Format.Global:
|
||||
case mplt.Format.Mask:
|
||||
default:
|
||||
{
|
||||
throw new System.ArgumentException($"The format of the LocationData must be BoundingBox or RelativeBoundingBox, but {target.Format}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(LocationData target)
|
||||
{
|
||||
if (ActivateFor(target))
|
||||
{
|
||||
switch (target.Format)
|
||||
{
|
||||
case mplt.Format.RelativeBoundingBox:
|
||||
{
|
||||
Draw(GetScreenRect().GetRectVertices(target.RelativeBoundingBox, rotationAngle, isMirrored));
|
||||
break;
|
||||
}
|
||||
case mplt.Format.BoundingBox:
|
||||
case mplt.Format.Global:
|
||||
case mplt.Format.Mask:
|
||||
default:
|
||||
{
|
||||
throw new System.ArgumentException($"The format of the LocationData must be RelativeBoundingBox, but {target.Format}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startColor = color;
|
||||
_lineRenderer.endColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.startWidth = lineWidth;
|
||||
_lineRenderer.endWidth = lineWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba39488de81a63b298a92a9d09ac42db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
#pragma warning disable IDE0065
|
||||
using Color = UnityEngine.Color;
|
||||
#pragma warning restore IDE0065
|
||||
|
||||
public class RectangleListAnnotation : ListAnnotation<RectangleAnnotation>
|
||||
{
|
||||
[SerializeField] private Color _color = Color.red;
|
||||
[SerializeField, Range(0, 1)] private float _lineWidth = 1.0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfAnyPrefab(this))
|
||||
{
|
||||
ApplyColor(_color);
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_color = color;
|
||||
ApplyColor(_color);
|
||||
}
|
||||
|
||||
public void SetLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
ApplyLineWidth(_lineWidth);
|
||||
}
|
||||
|
||||
public void Draw(IList<Rect> targets, Vector2Int imageSize)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target, imageSize); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(IList<NormalizedRect> targets)
|
||||
{
|
||||
if (ActivateFor(targets))
|
||||
{
|
||||
CallActionForAll(targets, (annotation, target) =>
|
||||
{
|
||||
if (annotation != null) { annotation.Draw(target); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override RectangleAnnotation InstantiateChild(bool isActive = true)
|
||||
{
|
||||
var annotation = base.InstantiateChild(isActive);
|
||||
annotation.SetLineWidth(_lineWidth);
|
||||
annotation.SetColor(_color);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
foreach (var rect in children)
|
||||
{
|
||||
if (rect != null) { rect.SetColor(color); }
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLineWidth(float lineWidth)
|
||||
{
|
||||
foreach (var rect in children)
|
||||
{
|
||||
if (rect != null) { rect.SetLineWidth(lineWidth); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff689dc19c0db10608af875e2c24ade9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- _annotationPrefab: {fileID: 4965192403804369243, guid: 3b696480602fe21de85315216956bd42,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2021 homuler
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
using Mediapipe.Unity.CoordinateSystem;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mediapipe.Unity
|
||||
{
|
||||
public sealed class TransformAnnotation : HierarchicalAnnotation
|
||||
{
|
||||
[SerializeField] private Arrow _xArrow;
|
||||
[SerializeField] private Arrow _yArrow;
|
||||
[SerializeField] private Arrow _zArrow;
|
||||
|
||||
public Vector3 origin
|
||||
{
|
||||
get => transform.localPosition;
|
||||
set => transform.localPosition = value;
|
||||
}
|
||||
|
||||
public void SetArrowCapScale(float arrowCapScale)
|
||||
{
|
||||
_xArrow.SetCapScale(arrowCapScale);
|
||||
_yArrow.SetCapScale(arrowCapScale);
|
||||
_zArrow.SetCapScale(arrowCapScale);
|
||||
}
|
||||
|
||||
public void SetArrowWidth(float arrowWidth)
|
||||
{
|
||||
_xArrow.SetLineWidth(arrowWidth);
|
||||
_yArrow.SetLineWidth(arrowWidth);
|
||||
_zArrow.SetLineWidth(arrowWidth);
|
||||
}
|
||||
|
||||
public void Draw(Quaternion rotation, Vector3 scale, bool visualizeZ = true)
|
||||
{
|
||||
var q = Quaternion.Euler(0, 0, -(int)rotationAngle);
|
||||
DrawArrow(_xArrow, scale.x * (q * rotation * Vector3.right), visualizeZ);
|
||||
DrawArrow(_yArrow, scale.y * (q * rotation * Vector3.up), visualizeZ);
|
||||
DrawArrow(_zArrow, scale.z * (q * rotation * Vector3.forward), visualizeZ);
|
||||
}
|
||||
|
||||
public void Draw(ObjectAnnotation target, Vector3 position, float arrowLengthScale = 1.0f, bool visualizeZ = true)
|
||||
{
|
||||
origin = position;
|
||||
|
||||
var (xDir, yDir, zDir) = CameraCoordinate.GetDirections(target, rotationAngle, isMirrored);
|
||||
DrawArrow(_xArrow, arrowLengthScale * xDir, visualizeZ);
|
||||
DrawArrow(_yArrow, arrowLengthScale * yDir, visualizeZ);
|
||||
DrawArrow(_zArrow, arrowLengthScale * zDir, visualizeZ);
|
||||
}
|
||||
|
||||
private void DrawArrow(Arrow arrow, Vector3 vec, bool visualizeZ)
|
||||
{
|
||||
var magnitude = vec.magnitude;
|
||||
var direction = vec.normalized;
|
||||
|
||||
if (!visualizeZ)
|
||||
{
|
||||
var direction2d = new Vector3(direction.x, direction.y, 0);
|
||||
magnitude *= direction2d.magnitude;
|
||||
direction = direction2d;
|
||||
}
|
||||
arrow.direction = direction;
|
||||
arrow.magnitude = magnitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 219b3f9aac8f8d18db8e85142b28db7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user