Select a specific skeleton - Unity / Orbbec Astra Pro

Hi all,

I just started to use nuitrack with unity and Orbbec Astra Pro.

I used the “Native Avatar” script and it works very well. The problem is that it seems to track only one person, I need to select which skeleton track.

Is there a script that track all the skeletons in the scene? I need to “draw” all skeleton and consider the nearest to the camera. Each frame I want to know who is the closest…

Thank you

Nuitrack can detect up to 6 bodies at any one time - and by default has the ability to track 2 of those as skeletons. It uses a first in best dressed type approach to this.

There is a setting in the nuitrack.config that would let you increase the number of skeletons tracked up to 6 - but you need a very high powered computer to keep that sort of number of skeletons going - And beyond that - you would also need to look closely at the occlusion reporting IMHO

Westa

Ok thank you! is there an example script in c# where it tracks the nearest body as a skeleton?

I would need 2 things:
1 - The person has to be in the center of the camera (within a range)
2 - The person has to be the nearest to the camera

Hi Guybrush

I’ve had to do something kind similar recently. This is how i’ve approached it:

First disabled the autoskeleton tracking :

  void Start()
  {
    NuitrackManager.skeletonTracker.SetAutoTracking(false);
    NuitrackManager.skeletonTracker.SetNumActiveUsers(1);  
}

then listen to the data UsertrackerUpdates:

private void OnEnable()
{
    NuitrackManager.onUserTrackerUpdate += OnUserTrackerUpdate;
}

private void OnDisable()
{
    NuitrackManager.onUserTrackerUpdate -= OnUserTrackerUpdate;
}

In the usertracker update, you can then check for the closed user and assign/remove the user skeleton to track. This way you only calculate one skeleton.

       private void OnUserTrackerUpdate( UserFrame frame )
       {

        int nSkeletonTracked = NuitrackManager.skeletonTracker.GetSkeletonData().NumUsers;

        foreach (User user in frame.Users)
        {
            bool foundInSpot = CheckInSpot(user);

            if (NuitrackManager.skeletonTracker != null)
			{
				if (foundInSpot)
				{
                    InSpot = true;

                    if (nSkeletonTracked == 0)
					{
						Debug.Log("In spot user.ID:" + user.ID);
						NuitrackManager.skeletonTracker.StartTracking(user.ID);
					}
				}
				else
				{
					bool isTrackingUser = NuitrackManager.skeletonTracker.IsTracking(user.ID);
					NuitrackManager.skeletonTracker.IsTracking ?" + isTrackingUser + " nSkeletonTracked:"+ nSkeletonTracked);
					if (isTrackingUser && nSkeletonTracked >= 1)
						NuitrackManager.skeletonTracker.StopTracking(user.ID);
					
				}
			}
		}
}


	 private bool CheckInSpot(User user)
     {
            BoundingBox bb = user.Box;
     
            userPosition = user.Real.ToVector3();

           //SpotPosition is the Vector3 position where you want your detrection to happen
            var diff = userPosition - SpotPosition;
            diff = new UnityEngine.Vector3(Mathf.Abs(diff.x), Mathf.Abs(diff.y), Mathf.Abs(diff.z));

           // SpotRadius the area/zone where you want the detection to happen
            if (diff.x > SpotRadius.x)
                return false;
            if (diff.z > SpotRadius.z)
                return false;

            return true;
}

lastlysomewhere else you can check for the skeleton on Update

void Update()
{
    if (CurrentUserTracker.CurrentSkeleton != null)
    {
        ProcessSkeleton(CurrentUserTracker.CurrentSkeleton); // do something with  nuitrack.Skeleton
    } 
}

This code is copy paste from different part of a project so it will need adaptation, but you’ll get the idea.

There is another route using the config file that the support team gave me, yet i needed the full camera frame so didn’t go for it. might be of use for you/others tho. This is what they suggested:

1) open %NUITRACK_HOME%/data/nuitrack.config file in a text editor;
2) set "Skeletonization.ActiveUsers" to 1;
3) add this line

"BoxCutter":{"x":"0","y":"0","z":"0","width":"1000","height":"4000","depth":"3000","alpha":"0","beta":"-1.5"},

as the first line to "Segmentation" section.

Notes about 3rd step:

- depth map will be thresholded by height/2 mm (depth values [0...height/2] will be processed only);
- "beta" parameter is the BoxCutter's rotation angle in radians along X-axis of a sensor.

Please note this configuration of nuitrack.config file isn't default and could lead to accuracy issues.

Good luck!

1 Like

wow! Thank you very much for the answer.

Today or Monday I’m gonna try it and then I’ll let you know!

Thank you again!

I’ve 2 problems:
1 - How can you access the position of the skeletons in CheckInSpot(user)?

2 - I tried just to print “frame.Users.Length” but it doesn’t enter in “private void OnUserTrackerUpdate( UserFrame frame )”

This is the code: (I’m trying to add the to the text the number of skeletons)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using nuitrack;

public class testScheletroSelection : MonoBehaviour {

public bool InSpot;
public Text text;
public int nSkeletonTracked;

// Use this for initialization
void Start()
{
	NuitrackManager.skeletonTracker.SetAutoTracking(false);
	NuitrackManager.skeletonTracker.SetNumActiveUsers(1);  
}

private void OnEnable()
{
	NuitrackManager.onUserTrackerUpdate += OnUserTrackerUpdate;
}

private void OnDisable()
{
	NuitrackManager.onUserTrackerUpdate -= OnUserTrackerUpdate;
}

private void OnUserTrackerUpdate( UserFrame frame )

{

    nSkeletonTracked = NuitrackManager.skeletonTracker.GetSkeletonData().NumUsers;
	text.text = "" + nSkeletonTracked;

    foreach (User user in frame.Users)
    {
        bool foundInSpot = CheckInSpot(user);

        if (NuitrackManager.skeletonTracker != null)
		{
			if (foundInSpot)
			{
                InSpot = true;

                if (nSkeletonTracked == 0)
				{
					Debug.Log("In spot user.ID:" + user.ID);
					NuitrackManager.skeletonTracker.StartTracking(user.ID);
				}
			}
			else
			{
				bool isTrackingUser = NuitrackManager.skeletonTracker.IsTracking(user.ID);
				//NuitrackManager.skeletonTracker.IsTracking ?" + isTrackingUser + " nSkeletonTracked :"+ nSkeletonTracked);
				if (isTrackingUser && nSkeletonTracked >= 1)
					NuitrackManager.skeletonTracker.StopTracking(user.ID);
				
			}
		}
	}
}


// Update is called once per frame
void Update()

{
if (CurrentUserTracker.CurrentSkeleton != null)
{
// ProcessSkeleton(CurrentUserTracker.CurrentSkeleton); // do something with nuitrack.Skeleton

} 

}
public bool CheckInSpot(User user){
return true;
}
}

EDIT: I can’t understand why, but it doesn’t enter in:

private void OnUserTrackerUpdate( UserFrame frame ){

The idea is to check the user position, then tell the skeleton manager to track that user.

userPosition = user.Real.ToVector3();

is position of the user.

Not sure why OnUserTrackerUpdate isn’t called. They might have changed the way to listen to such events in the new sdk? Check if the demo scene works. Maybe its a setup issue?