You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
655 lines
23 KiB
655 lines
23 KiB
using UnityEngine;
|
|
using com.rfilkov.kinect;
|
|
|
|
|
|
namespace com.rfilkov.components
|
|
{
|
|
/// <summary>
|
|
/// Body slice enum.
|
|
/// </summary>
|
|
public enum BodySlice
|
|
{
|
|
HEIGHT = 0,
|
|
WIDTH = 1,
|
|
|
|
TORSO_1 = 2,
|
|
TORSO_2 = 3,
|
|
TORSO_3 = 4,
|
|
TORSO_4 = 5,
|
|
TORSO_5 = 6,
|
|
|
|
COUNT = 7
|
|
}
|
|
|
|
/// <summary>
|
|
/// Data structure used by the body slicer.
|
|
/// </summary>
|
|
public struct BodySliceData
|
|
{
|
|
public BodySlice sliceType;
|
|
public bool isSliceValid;
|
|
|
|
public float diameter;
|
|
public int depthPointsLength;
|
|
public int colorPointsLength;
|
|
|
|
// public ushort[] depths;
|
|
public Vector2 startDepthPoint;
|
|
public Vector2 endDepthPoint;
|
|
|
|
public Vector2 startColorPoint;
|
|
public Vector2 endColorPoint;
|
|
|
|
public Vector3 startKinectPoint;
|
|
public Vector3 endKinectPoint;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Body slicer is component that estimates the user height from the depth data, as well as several other body sizes.
|
|
/// </summary>
|
|
public class BodySlicer : MonoBehaviour
|
|
{
|
|
[Tooltip("Depth sensor index - 0 is the 1st one, 1 - the 2nd one, etc.")]
|
|
public int sensorIndex = 0;
|
|
|
|
[Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")]
|
|
public int playerIndex = 0;
|
|
|
|
[Tooltip("Camera used to estimate the overlay positions of 3D-objects over the background. By default it is the main camera.")]
|
|
public Camera foregroundCamera;
|
|
|
|
[Tooltip("Whether the sensor is in portrait mode or not.")]
|
|
public bool portraitMode = false;
|
|
|
|
[Tooltip("Whether the body height should estimated or not.")]
|
|
public bool estimateBodyHeight = true;
|
|
|
|
[Tooltip("Whether the body width should estimated or not.")]
|
|
public bool estimateBodyWidth = false;
|
|
|
|
[Tooltip("Whether the body slices should estimated or not.")]
|
|
public bool estimateBodySlices = false;
|
|
|
|
[Tooltip("Whether the slicing should be done on all updates, or only after the user calibration.")]
|
|
public bool continuousSlicing = false;
|
|
|
|
[Tooltip("Whether the detected body slices should be displayed on the screen.")]
|
|
public bool displayBodySlices = false;
|
|
|
|
|
|
private ulong calibratedUserId;
|
|
private byte userBodyIndex;
|
|
|
|
|
|
// The singleton instance of BodySlicer
|
|
//private static BodySlicer instance = null;
|
|
private KinectManager kinectManager;
|
|
private KinectInterop.SensorData sensorData;
|
|
private ulong lastDepthFrameTime;
|
|
|
|
// body slice data
|
|
private BodySliceData[] bodySlices = new BodySliceData[(int)BodySlice.COUNT];
|
|
|
|
// depth image resolution
|
|
private int depthImageWidth;
|
|
private int depthImageHeight;
|
|
|
|
// depth scale
|
|
private Vector3 depthScale = Vector3.one;
|
|
|
|
// screen rectangle taken by the foreground image (in pixels)
|
|
private Rect foregroundImgRect;
|
|
|
|
|
|
///// <summary>
|
|
///// Gets the singleton BodySlicer instance.
|
|
///// </summary>
|
|
///// <value>The singleton BodySlicer instance.</value>
|
|
//public static BodySlicer Instance
|
|
//{
|
|
// get
|
|
// {
|
|
// return instance;
|
|
// }
|
|
//}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the height of the user.
|
|
/// </summary>
|
|
/// <returns>The user height.</returns>
|
|
public float getUserHeight()
|
|
{
|
|
return getSliceWidth(BodySlice.HEIGHT);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the slice width.
|
|
/// </summary>
|
|
/// <returns>The slice width.</returns>
|
|
/// <param name="slice">Slice.</param>
|
|
public float getSliceWidth(BodySlice slice)
|
|
{
|
|
int iSlice = (int)slice;
|
|
|
|
if (bodySlices[iSlice].isSliceValid)
|
|
{
|
|
return bodySlices[iSlice].diameter;
|
|
}
|
|
|
|
return 0f;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the body slice count.
|
|
/// </summary>
|
|
/// <returns>The body slice count.</returns>
|
|
public int getBodySliceCount()
|
|
{
|
|
return bodySlices != null ? bodySlices.Length : 0;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the body slice data.
|
|
/// </summary>
|
|
/// <returns>The body slice data.</returns>
|
|
/// <param name="slice">Slice.</param>
|
|
public BodySliceData getBodySliceData(BodySlice slice)
|
|
{
|
|
return bodySlices[(int)slice];
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the calibrated user ID.
|
|
/// </summary>
|
|
/// <returns>The calibrated user ID.</returns>
|
|
public ulong getCalibratedUserId()
|
|
{
|
|
return calibratedUserId;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the last frame time.
|
|
/// </summary>
|
|
/// <returns>The last frame time.</returns>
|
|
public ulong getLastFrameTime()
|
|
{
|
|
return lastDepthFrameTime;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void Awake()
|
|
{
|
|
//instance = this;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
kinectManager = KinectManager.Instance;
|
|
sensorData = kinectManager ? kinectManager.GetSensorData(sensorIndex) : null;
|
|
|
|
if(kinectManager && kinectManager.IsInitialized())
|
|
{
|
|
depthImageWidth = kinectManager.GetDepthImageWidth(sensorIndex);
|
|
depthImageHeight = kinectManager.GetDepthImageHeight(sensorIndex);
|
|
|
|
depthScale = kinectManager.GetDepthImageScale(sensorIndex);
|
|
}
|
|
|
|
if (foregroundCamera == null)
|
|
{
|
|
// by default use the main camera
|
|
foregroundCamera = Camera.main;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (!kinectManager || !kinectManager.IsInitialized() || sensorData == null)
|
|
return;
|
|
|
|
// calculate the foreground rectangle
|
|
foregroundImgRect = kinectManager.GetForegroundRectDepth(sensorIndex, foregroundCamera);
|
|
|
|
// get required player
|
|
ulong userId = kinectManager.GetUserIdByIndex(playerIndex);
|
|
|
|
if (calibratedUserId == 0)
|
|
{
|
|
if (userId != 0)
|
|
{
|
|
OnCalibrationSuccess(userId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (calibratedUserId != userId)
|
|
{
|
|
OnUserLost(calibratedUserId);
|
|
}
|
|
else if (continuousSlicing)
|
|
{
|
|
EstimateBodySlices(calibratedUserId);
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnRenderObject()
|
|
{
|
|
if (displayBodySlices)
|
|
{
|
|
DrawBodySlice(bodySlices[(int)BodySlice.HEIGHT]);
|
|
|
|
DrawBodySlice(bodySlices[(int)BodySlice.TORSO_1]);
|
|
DrawBodySlice(bodySlices[(int)BodySlice.TORSO_2]);
|
|
DrawBodySlice(bodySlices[(int)BodySlice.TORSO_3]);
|
|
DrawBodySlice(bodySlices[(int)BodySlice.TORSO_4]);
|
|
DrawBodySlice(bodySlices[(int)BodySlice.TORSO_5]);
|
|
}
|
|
}
|
|
|
|
|
|
// draws a body slice line
|
|
private void DrawBodySlice(BodySliceData bodySlice)
|
|
{
|
|
if (bodySlice.isSliceValid && bodySlice.startDepthPoint != Vector2.zero && bodySlice.endDepthPoint != Vector2.zero)
|
|
{
|
|
float rectX = foregroundImgRect.xMin;
|
|
float rectY = foregroundImgRect.yMin;
|
|
|
|
float scaleX = foregroundImgRect.width / depthImageWidth;
|
|
float scaleY = foregroundImgRect.height / depthImageHeight;
|
|
|
|
float x1 = rectX + (depthScale.x >= 0f ? bodySlice.startDepthPoint.x : depthImageWidth - bodySlice.startDepthPoint.x) * scaleX;
|
|
float y1 = rectY + (depthScale.y >= 0f ? bodySlice.startDepthPoint.y : depthImageHeight - bodySlice.startDepthPoint.y) * scaleY;
|
|
|
|
float x2 = rectX + (depthScale.x >= 0f ? bodySlice.endDepthPoint.x : depthImageWidth - bodySlice.endDepthPoint.x) * scaleX;
|
|
float y2 = rectY + (depthScale.y >= 0f ? bodySlice.endDepthPoint.y : depthImageHeight - bodySlice.endDepthPoint.y) * scaleY;
|
|
|
|
KinectInterop.DrawLine((int)x1, (int)y1, (int)x2, (int)y2, 2f, Color.red);
|
|
}
|
|
}
|
|
|
|
|
|
public void OnCalibrationSuccess(ulong userId)
|
|
{
|
|
calibratedUserId = userId;
|
|
|
|
// estimate body slices
|
|
EstimateBodySlices(calibratedUserId);
|
|
}
|
|
|
|
|
|
void OnUserLost(ulong userId)
|
|
{
|
|
calibratedUserId = 0;
|
|
|
|
// invalidate the body slice data
|
|
for (int i = 0; i < bodySlices.Length; i++)
|
|
{
|
|
bodySlices[i].isSliceValid = false;
|
|
}
|
|
}
|
|
|
|
|
|
// estimates the body slice data for the given user
|
|
public bool EstimateBodySlices(ulong userId)
|
|
{
|
|
if (userId <= 0)
|
|
userId = calibratedUserId;
|
|
|
|
if (!kinectManager || userId == 0)
|
|
return false;
|
|
|
|
userBodyIndex = (byte)kinectManager.GetBodyIndexByUserId(userId);
|
|
if (userBodyIndex == 255)
|
|
return false;
|
|
|
|
bool bSliceSuccess = false;
|
|
|
|
if (sensorData.bodyIndexImage != null && sensorData.depthImage != null &&
|
|
sensorData.lastDepthFrameTime != lastDepthFrameTime)
|
|
{
|
|
lastDepthFrameTime = sensorData.lastDepthFrameTime;
|
|
bSliceSuccess = true;
|
|
|
|
Vector2 pointPelvis = kinectManager.MapSpacePointToDepthCoords(sensorIndex, kinectManager.GetJointKinectPosition(userId, (int)KinectInterop.JointType.Pelvis, false));
|
|
|
|
if (estimateBodyHeight)
|
|
{
|
|
bodySlices[(int)BodySlice.HEIGHT] = !portraitMode ? GetUserHeightParams(pointPelvis) : GetUserWidthParams(pointPelvis);
|
|
}
|
|
|
|
if (estimateBodyWidth)
|
|
{
|
|
bodySlices[(int)BodySlice.WIDTH] = !portraitMode ? GetUserWidthParams(pointPelvis) : GetUserHeightParams(pointPelvis);
|
|
}
|
|
|
|
if (estimateBodySlices && kinectManager.IsJointTracked(userId, (int)KinectInterop.JointType.Pelvis) && kinectManager.IsJointTracked(userId, (int)KinectInterop.JointType.Neck))
|
|
{
|
|
Vector2 point1 = pointPelvis;
|
|
Vector2 point2 = kinectManager.MapSpacePointToDepthCoords(sensorIndex, kinectManager.GetJointKinectPosition(userId, (int)KinectInterop.JointType.Neck, false));
|
|
Vector2 sliceDir = (point2 - point1) / 4f;
|
|
|
|
bool sliceOnX = !portraitMode ? true : false;
|
|
bool sliceOnY = !portraitMode ? false : true;
|
|
|
|
Vector2 vSlicePoint = point1;
|
|
bodySlices[(int)BodySlice.TORSO_1] = GetBodySliceParams(BodySlice.TORSO_1, vSlicePoint, sliceOnX, sliceOnY, -1);
|
|
|
|
vSlicePoint += sliceDir;
|
|
bodySlices[(int)BodySlice.TORSO_2] = GetBodySliceParams(BodySlice.TORSO_2, vSlicePoint, sliceOnX, sliceOnY, -1);
|
|
|
|
vSlicePoint += sliceDir;
|
|
bodySlices[(int)BodySlice.TORSO_3] = GetBodySliceParams(BodySlice.TORSO_3, vSlicePoint, sliceOnX, sliceOnY, -1);
|
|
|
|
vSlicePoint += sliceDir;
|
|
bodySlices[(int)BodySlice.TORSO_4] = GetBodySliceParams(BodySlice.TORSO_4, vSlicePoint, sliceOnX, sliceOnY, -1);
|
|
|
|
vSlicePoint = point2;
|
|
bodySlices[(int)BodySlice.TORSO_5] = GetBodySliceParams(BodySlice.TORSO_5, vSlicePoint, sliceOnX, sliceOnY, -1);
|
|
}
|
|
}
|
|
|
|
return bSliceSuccess;
|
|
}
|
|
|
|
|
|
// creates body slice data for user height
|
|
private BodySliceData GetUserHeightParams(Vector2 pointSpineBase)
|
|
{
|
|
int depthLength = sensorData.depthImage.Length;
|
|
int depthWidth = sensorData.depthImageWidth;
|
|
int depthHeight = sensorData.depthImageHeight;
|
|
|
|
Vector2 posTop = new Vector2(0, depthHeight);
|
|
for (int i = 0, x = 0, y = 0; i < depthLength; i++)
|
|
{
|
|
if (sensorData.bodyIndexImage[i] == userBodyIndex)
|
|
{
|
|
//if (posTop.y > y)
|
|
posTop = new Vector2(x, y);
|
|
break;
|
|
}
|
|
|
|
x++;
|
|
if (x >= depthWidth)
|
|
{
|
|
x = 0;
|
|
y++;
|
|
}
|
|
}
|
|
|
|
Vector2 posBottom = new Vector2(0, -1);
|
|
for (int i = depthLength - 1, x = depthWidth - 1, y = depthHeight - 1; i >= 0; i--)
|
|
{
|
|
if (sensorData.bodyIndexImage[i] == userBodyIndex)
|
|
{
|
|
//if (posBottom.y < y)
|
|
posBottom = new Vector2(x, y);
|
|
break;
|
|
}
|
|
|
|
x--;
|
|
if (x < 0)
|
|
{
|
|
x = depthWidth - 1;
|
|
y--;
|
|
}
|
|
}
|
|
|
|
BodySliceData sliceData = new BodySliceData();
|
|
sliceData.sliceType = BodySlice.HEIGHT;
|
|
sliceData.isSliceValid = false;
|
|
|
|
if (posBottom.y >= 0)
|
|
{
|
|
sliceData.startDepthPoint = posTop;
|
|
sliceData.endDepthPoint = posBottom;
|
|
sliceData.depthPointsLength = (int)posBottom.y - (int)posTop.y + 1;
|
|
|
|
int index1 = (int)posTop.y * depthWidth + (int)posTop.x;
|
|
ushort depth1 = sensorData.depthImage[index1];
|
|
sliceData.startKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.startDepthPoint, depth1, true);
|
|
|
|
int index2 = (int)posBottom.y * depthWidth + (int)posBottom.x;
|
|
ushort depth2 = sensorData.depthImage[index2];
|
|
sliceData.endKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.endDepthPoint, depth2, true);
|
|
|
|
sliceData.startColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.startDepthPoint, depth1);
|
|
sliceData.endColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.endDepthPoint, depth2);
|
|
|
|
if (sliceData.startColorPoint.y < 0)
|
|
sliceData.startColorPoint.y = 0;
|
|
if (sliceData.endColorPoint.y >= sensorData.colorImageHeight)
|
|
sliceData.endColorPoint.y = sensorData.colorImageHeight - 1;
|
|
sliceData.colorPointsLength = (int)sliceData.endColorPoint.y - (int)sliceData.startColorPoint.y + 1;
|
|
|
|
// correct x-positions of depth points
|
|
sliceData.startDepthPoint.x = pointSpineBase.x;
|
|
sliceData.endDepthPoint.x = pointSpineBase.x;
|
|
|
|
sliceData.diameter = (sliceData.endKinectPoint - sliceData.startKinectPoint).magnitude;
|
|
sliceData.isSliceValid = true;
|
|
}
|
|
|
|
return sliceData;
|
|
}
|
|
|
|
// creates body slice data for user width
|
|
private BodySliceData GetUserWidthParams(Vector2 pointSpineBase)
|
|
{
|
|
int depthLength = sensorData.depthImage.Length;
|
|
int depthWidth = sensorData.depthImageWidth;
|
|
//int depthHeight = sensorData.depthImageHeight;
|
|
|
|
Vector2 posLeft = new Vector2(depthWidth, 0);
|
|
Vector2 posRight = new Vector2(-1, 0);
|
|
|
|
for (int i = 0, x = 0, y = 0; i < depthLength; i++)
|
|
{
|
|
if (sensorData.bodyIndexImage[i] == userBodyIndex)
|
|
{
|
|
if (posLeft.x > x)
|
|
posLeft = new Vector2(x, y);
|
|
if (posRight.x < x)
|
|
posRight = new Vector2(x, y);
|
|
}
|
|
|
|
x++;
|
|
if (x >= depthWidth)
|
|
{
|
|
x = 0;
|
|
y++;
|
|
}
|
|
}
|
|
|
|
BodySliceData sliceData = new BodySliceData();
|
|
sliceData.sliceType = BodySlice.WIDTH;
|
|
sliceData.isSliceValid = false;
|
|
|
|
if (posRight.x >= 0)
|
|
{
|
|
sliceData.startDepthPoint = posLeft;
|
|
sliceData.endDepthPoint = posRight;
|
|
sliceData.depthPointsLength = (int)posRight.x - (int)posLeft.x + 1;
|
|
|
|
int index1 = (int)posLeft.y * depthWidth + (int)posLeft.x;
|
|
ushort depth1 = sensorData.depthImage[index1];
|
|
sliceData.startKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.startDepthPoint, depth1, true);
|
|
|
|
int index2 = (int)posRight.y * depthWidth + (int)posRight.x;
|
|
ushort depth2 = sensorData.depthImage[index2];
|
|
sliceData.endKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.endDepthPoint, depth2, true);
|
|
|
|
sliceData.startColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.startDepthPoint, depth1);
|
|
sliceData.endColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.endDepthPoint, depth2);
|
|
|
|
if (sliceData.startColorPoint.x < 0)
|
|
sliceData.startColorPoint.x = 0;
|
|
if (sliceData.endColorPoint.x >= sensorData.colorImageWidth)
|
|
sliceData.endColorPoint.x = sensorData.colorImageWidth - 1;
|
|
sliceData.colorPointsLength = (int)sliceData.endColorPoint.x - (int)sliceData.startColorPoint.x + 1;
|
|
|
|
// correct y-positions of depth points
|
|
sliceData.startDepthPoint.y = pointSpineBase.y;
|
|
sliceData.endDepthPoint.y = pointSpineBase.y;
|
|
|
|
sliceData.diameter = (sliceData.endKinectPoint - sliceData.startKinectPoint).magnitude;
|
|
sliceData.isSliceValid = true;
|
|
}
|
|
|
|
return sliceData;
|
|
}
|
|
|
|
// creates body slice data for the given body slice
|
|
private BodySliceData GetBodySliceParams(BodySlice sliceType, Vector2 middlePoint, bool bSliceOnX, bool bSliceOnY, int maxDepthLength)
|
|
{
|
|
BodySliceData sliceData = new BodySliceData();
|
|
sliceData.sliceType = sliceType;
|
|
|
|
sliceData.isSliceValid = false;
|
|
sliceData.depthPointsLength = 0;
|
|
|
|
if (!kinectManager || middlePoint == Vector2.zero)
|
|
return sliceData;
|
|
if (!bSliceOnX && !bSliceOnY)
|
|
return sliceData;
|
|
|
|
middlePoint.x = Mathf.FloorToInt(middlePoint.x + 0.5f);
|
|
middlePoint.y = Mathf.FloorToInt(middlePoint.y + 0.5f);
|
|
|
|
int depthWidth = sensorData.depthImageWidth;
|
|
int depthHeight = sensorData.depthImageHeight;
|
|
|
|
int indexMid = (int)middlePoint.y * depthWidth + (int)middlePoint.x;
|
|
byte userIndex = sensorData.bodyIndexImage[indexMid];
|
|
|
|
if (userIndex != userBodyIndex)
|
|
return sliceData;
|
|
|
|
sliceData.startDepthPoint = middlePoint;
|
|
sliceData.endDepthPoint = middlePoint;
|
|
|
|
int indexDiff1 = 0;
|
|
int indexDiff2 = 0;
|
|
|
|
if (bSliceOnX)
|
|
{
|
|
// min-max
|
|
int minIndex = (int)middlePoint.y * depthWidth;
|
|
int maxIndex = (int)(middlePoint.y + 1) * depthWidth;
|
|
|
|
// horizontal left
|
|
int stepIndex = -1;
|
|
indexDiff1 = TrackSliceInDirection(indexMid, stepIndex, minIndex, maxIndex, userIndex);
|
|
|
|
// horizontal right
|
|
stepIndex = 1;
|
|
indexDiff2 = TrackSliceInDirection(indexMid, stepIndex, minIndex, maxIndex, userIndex);
|
|
}
|
|
else if (bSliceOnY)
|
|
{
|
|
// min-max
|
|
int minIndex = 0;
|
|
int maxIndex = depthHeight * depthWidth;
|
|
|
|
// vertical up
|
|
int stepIndex = -depthWidth;
|
|
indexDiff1 = TrackSliceInDirection(indexMid, stepIndex, minIndex, maxIndex, userIndex);
|
|
|
|
// vertical down
|
|
stepIndex = depthWidth;
|
|
indexDiff2 = TrackSliceInDirection(indexMid, stepIndex, minIndex, maxIndex, userIndex);
|
|
}
|
|
|
|
// calculate depth length
|
|
sliceData.depthPointsLength = indexDiff1 + indexDiff2 + 1;
|
|
|
|
// check for max length (used by upper legs)
|
|
if (maxDepthLength > 0 && sliceData.depthPointsLength > maxDepthLength)
|
|
{
|
|
if (indexDiff1 > indexDiff2)
|
|
indexDiff1 = indexDiff2;
|
|
else
|
|
indexDiff2 = indexDiff1;
|
|
|
|
sliceData.depthPointsLength = indexDiff1 + indexDiff2 + 1;
|
|
}
|
|
|
|
// set start and end depth points
|
|
if (bSliceOnX)
|
|
{
|
|
sliceData.startDepthPoint.x -= indexDiff1;
|
|
sliceData.endDepthPoint.x += indexDiff2;
|
|
}
|
|
else if (bSliceOnY)
|
|
{
|
|
sliceData.startDepthPoint.y -= indexDiff1;
|
|
sliceData.endDepthPoint.y += indexDiff2;
|
|
}
|
|
|
|
// start point
|
|
int index1 = (int)sliceData.startDepthPoint.y * depthWidth + (int)sliceData.startDepthPoint.x;
|
|
ushort depth1 = sensorData.depthImage[index1];
|
|
sliceData.startKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.startDepthPoint, depth1, true);
|
|
|
|
// end point
|
|
int index2 = (int)sliceData.endDepthPoint.y * depthWidth + (int)sliceData.endDepthPoint.x;
|
|
ushort depth2 = sensorData.depthImage[index2];
|
|
sliceData.endKinectPoint = kinectManager.MapDepthPointToSpaceCoords(sensorIndex, sliceData.endDepthPoint, depth2, true);
|
|
|
|
sliceData.startColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.startDepthPoint, depth1);
|
|
sliceData.endColorPoint = kinectManager.MapDepthPointToColorCoords(sensorIndex, sliceData.endDepthPoint, depth2);
|
|
|
|
if (sliceData.startColorPoint.x < 0)
|
|
sliceData.startColorPoint.x = 0;
|
|
if (sliceData.endColorPoint.x >= sensorData.colorImageWidth)
|
|
sliceData.endColorPoint.x = sensorData.colorImageWidth - 1;
|
|
sliceData.colorPointsLength = (int)sliceData.endColorPoint.x - (int)sliceData.startColorPoint.x + 1;
|
|
|
|
// diameter
|
|
sliceData.diameter = (sliceData.endKinectPoint - sliceData.startKinectPoint).magnitude;
|
|
sliceData.isSliceValid = true;
|
|
|
|
return sliceData;
|
|
}
|
|
|
|
// determines the number of points in the given direction
|
|
private int TrackSliceInDirection(int index, int stepIndex, int minIndex, int maxIndex, byte userIndex)
|
|
{
|
|
int indexDiff = 0;
|
|
int errCount = 0;
|
|
|
|
index += stepIndex;
|
|
while (index >= minIndex && index < maxIndex)
|
|
{
|
|
if (sensorData.bodyIndexImage[index] != userIndex)
|
|
{
|
|
errCount++;
|
|
if (errCount > 0) // allow 0 error(s)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
errCount = 0;
|
|
}
|
|
|
|
index += stepIndex;
|
|
indexDiff++;
|
|
}
|
|
|
|
return indexDiff;
|
|
}
|
|
|
|
}
|
|
}
|
|
|