generate - params comments c#
Seguimiento de esqueleto lateral Kinect (3)
Actualmente estoy usando Microsoft Kinect para medir ángulos entre juntas. La mayoría de las medidas funcionan correctamente. Cuando una persona está sentada de lado (en una silla), Kinect no rastreará el esqueleto con precisión. Para ilustrar mi problema, he agregado 3 imágenes de la vista en profundidad de Kinect.
Como se puede ver, 2 de cada 3 mediciones funcionan "correctamente". Cada vez que levanto mi pierna, el Kinect detiene el seguimiento del esqueleto correctamente. ¿Alguien tiene una solución a este problema o es solo una limitación del Kinect?
Gracias.
Actualización 1: la JointTrackingState-Enumeration
en estas uniones rastreadas que se muestra en la captura de pantalla 2 está marcada como Inferred
, sin embargo, la vista de profundidad está rastreando todo mi cuerpo.
Actualización 2: En la captura de pantalla 2, estoy tratando de rastrear mi pierna delantera, resaltada en verde. Sé que la otra pierna no está rastreada, pero esto no importa, supongo.
Actualización 3: El siguiente código selecciona un esqueleto:
private Skeleton StickySkeleton(Skeleton[] skeletons)
{
if (skeletons.Count<Skeleton>(skeleton => skeleton.TrackingId == _trackedSkeletonId) <= 0)
{
_trackedSkeletonId = -1;
_skeleton = null;
}
if (_trackedSkeletonId == -1)
{
Skeleton foundSkeleton = skeletons.FirstOrDefault<Skeleton>(skeleton => skeleton.TrackingState == SkeletonTrackingState.Tracked);
if (foundSkeleton != null)
{
_trackedSkeletonId = foundSkeleton.TrackingId;
return foundSkeleton;
}
}
return _skeleton;
}
Cada vez que se rastrea un esqueleto, se utilizarán datos para dibujar los puntos de unión y calcular el ángulo entre las juntas.
Actualización 4: He probado sentarme en un ''bloque'', mucho más simplificado que una silla. Desafortunadamente el Kinect sigue actuando igual.
A continuación 2 capturas de pantalla:
Como Renaud Dumont dijo, haría algo con JointTrackingState
. Desde que rightknee
rodillas, usé las variables leftknee
y rightknee
que son Joints
para hacerlo. Aquí está el código, puede usar JointType.FootRight
y JointType.FootLeft
y los tipos de Hip
, pero se lo dejaré a usted.
static Skeleton first = new Skeleton();
Joint leftknee = first.Joints[JointType.KneeLeft];
Joint rightknee = first.Joints[JointType.KneeRight];
if ((leftknee.TrackingState == JointTrackingState.Inferred ||
leftknee.TrackingState == JointTrackingState.Tracked) &&
(rightknee.TrackingState == JointTrackingState.Tracked ||
rightknee.TrackingState == JointTrackingState.Inferred))
{
}
O alternativamente, si solo desea que se rastree una rodilla a la vez, o ambas cosas, puede hacer esto:
if ((leftknee.TrackingState == JointTrackingState.Inferred ||
leftknee.TrackingState == JointTrackingState.Tracked) &&
(rightknee.TrackingState == JointTrackingState.Tracked ||
rightknee.TrackingState == JointTrackingState.Inferred))
{
}
else if (leftknee.TrackingState == JointTrackingState.Inferred ||
leftknee.TrackingState == JointTrackingState.Tracked)
{
}
else if (rightknee.TrackingState == JointTrackingState.Inferred ||
rightknee.TrackingState == JointTrackingState.Tracked)
{
}
Para su información, la razón por la que el Skeleton
es first
es static
es porque luego puede usarse para hacer las articulaciones
static Skeleton first;
Oposición a
Skeleton first;
Editar 1
Llegué a la conclusión de que esto es extremadamente difícil de hacer, creo que el método anterior funcionará, pero solo quería incluir lo que estoy trabajando en caso de que puedas encontrar alguna manera de hacerlo funcionar. De todos modos, aquí está el código en el que estaba trabajando, que es otra
class
que es simplemente otro SkeletalTrackingState
que estaba tratando de hacer una enum
Inferred
. Pero lamentablemente enum
son impossible de inherit
. Si encuentra algo en este sentido que funcione, lo respetaré como un programador superior para siempre;). Sin más preámbulos: el .dll
que estaba tratando de hacer: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;
namespace IsInferred
{
public abstract class SkeletonInferred : Skeleton
{
public bool inferred;
static Skeleton first1 = new Skeleton();
Joint handright;
Joint handleft;
Joint footright;
Joint footleft;
Joint ankleleft;
Joint ankleright;
Joint elbowleft;
Joint elbowright;
Joint head;
Joint hipcenter;
Joint hipleft;
Joint hipright;
Joint shouldercenter;
Joint shoulderleft;
Joint shoulderright;
Joint kneeleft;
Joint kneeright;
Joint spine;
Joint wristleft;
Joint wristright;
public SkeletonInferred(bool inferred)
{
}
public enum Inferred
{
NotTracked = SkeletonTrackingState.NotTracked,
PositionOnly = SkeletonTrackingState.PositionOnly,
Tracked = SkeletonTrackingState.Tracked,
Inferred = 3,
}
private void IsInferred(object sender, AllFramesReadyEventArgs e)
{
handright = first1.Joints[JointType.HandRight];
handleft = first1.Joints[JointType.HandLeft];
footright = first1.Joints[JointType.FootRight];
footleft = first1.Joints[JointType.FootLeft];
ankleleft = first1.Joints[JointType.AnkleLeft];
ankleright = first1.Joints[JointType.AnkleRight];
elbowleft = first1.Joints[JointType.ElbowLeft];
elbowright = first1.Joints[JointType.ElbowRight];
head = first1.Joints[JointType.Head];
hipcenter = first1.Joints[JointType.HipCenter];
hipleft = first1.Joints[JointType.HipLeft];
hipright = first1.Joints[JointType.HipRight];
shouldercenter = first1.Joints[JointType.ShoulderCenter];
shoulderleft = first1.Joints[JointType.ShoulderLeft];
shoulderright = first1.Joints[JointType.ShoulderRight];
kneeleft = first1.Joints[JointType.KneeLeft];
kneeright = first1.Joints[JointType.KneeRight];
spine = first1.Joints[JointType.Spine];
wristleft = first1.Joints[JointType.WristLeft];
wristright = first1.Joints[JointType.WristRight];
if (handleft.TrackingState == JointTrackingState.Inferred &
handright.TrackingState == JointTrackingState.Inferred &
head.TrackingState == JointTrackingState.Inferred &
footleft.TrackingState == JointTrackingState.Inferred &
footright.TrackingState == JointTrackingState.Inferred &
ankleleft.TrackingState == JointTrackingState.Inferred &
ankleright.TrackingState == JointTrackingState.Inferred &
elbowleft.TrackingState == JointTrackingState.Inferred &
elbowright.TrackingState == JointTrackingState.Inferred &
hipcenter.TrackingState == JointTrackingState.Inferred &
hipleft.TrackingState == JointTrackingState.Inferred &
hipright.TrackingState == JointTrackingState.Inferred &
shouldercenter.TrackingState == JointTrackingState.Inferred &
shoulderleft.TrackingState == JointTrackingState.Inferred &
shoulderright.TrackingState == JointTrackingState.Inferred &
kneeleft.TrackingState == JointTrackingState.Inferred &
kneeright.TrackingState == JointTrackingState.Inferred &
spine.TrackingState == JointTrackingState.Inferred &
wristleft.TrackingState == JointTrackingState.Inferred &
wristright.TrackingState == JointTrackingState.Inferred)
{
inferred = true;
}
}
}
}
El código en tu proyecto (error del compilador)
using IsInferred;
static bool Inferred = false;
SkeletonInferred inferred = new SkeletonInferred(Inferred);
static Skeleton first1 = new Skeleton();
Skeleton foundSkeleton = skeletons.FirstOrDefault<Skeleton>(skeleton => skeleton.TrackingState == SkeletonTrackingState.Inferred);
Buena suerte, ¡espero que esto te ayude a avanzar en la dirección correcta o te ayude en todo!
Mi código
Aquí está mi código que pediste. Sí, es de los Fundamentos del seguimiento esquelético , pero este código estaba aquí y no quería comenzar un nuevo proyecto con la mayoría de las mismas cosas. ¡Disfrutar!
Código
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using Coding4Fun.Kinect.Wpf;
namespace SkeletalTracking
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
bool closing = false;
const int skeletonCount = 6;
Skeleton[] allSkeletons = new Skeleton[skeletonCount];
private void Window_Loaded(object sender, RoutedEventArgs e)
{
kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged);
}
void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
{
KinectSensor old = (KinectSensor)e.OldValue;
StopKinect(old);
KinectSensor sensor = (KinectSensor)e.NewValue;
if (sensor == null)
{
return;
}
var parameters = new TransformSmoothParameters
{
Smoothing = 0.3f,
Correction = 0.0f,
Prediction = 0.0f,
JitterRadius = 1.0f,
MaxDeviationRadius = 0.5f
};
sensor.SkeletonStream.Enable(parameters);
//sensor.SkeletonStream.Enable();
sensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(sensor_AllFramesReady);
sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
try
{
sensor.Start();
}
catch (System.IO.IOException)
{
kinectSensorChooser1.AppConflictOccurred();
}
}
void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
if (closing)
{
return;
}
//Get a skeleton
Skeleton first = GetFirstSkeleton(e);
if (first == null)
{
return;
}
//set scaled position
//ScalePosition(headImage, first.Joints[JointType.Head]);
ScalePosition(leftEllipse, first.Joints[JointType.HandLeft]);
ScalePosition(rightEllipse, first.Joints[JointType.HandRight]);
ScalePosition(leftknee, first.Joints[JointType.KneeLeft]);
ScalePosition(rightknee, first.Joints[JointType.KneeRight]);
GetCameraPoint(first, e);
}
void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
{
using (DepthImageFrame depth = e.OpenDepthImageFrame())
{
if (depth == null ||
kinectSensorChooser1.Kinect == null)
{
return;
}
//Map a joint location to a point on the depth map
//head
DepthImagePoint headDepthPoint =
depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position);
//left hand
DepthImagePoint leftDepthPoint =
depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position);
//right hand
DepthImagePoint rightDepthPoint =
depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position);
DepthImagePoint rightKnee =
depth.MapFromSkeletonPoint(first.Joints[JointType.KneeRight].Position);
DepthImagePoint leftKnee =
depth.MapFromSkeletonPoint(first.Joints[JointType.KneeLeft].Position);
//Map a depth point to a point on the color image
//head
ColorImagePoint headColorPoint =
depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y,
ColorImageFormat.RgbResolution640x480Fps30);
//left hand
ColorImagePoint leftColorPoint =
depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y,
ColorImageFormat.RgbResolution640x480Fps30);
//right hand
ColorImagePoint rightColorPoint =
depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y,
ColorImageFormat.RgbResolution640x480Fps30);
ColorImagePoint leftKneeColorPoint =
depth.MapToColorImagePoint(leftKnee.X, leftKnee.Y,
ColorImageFormat.RgbResolution640x480Fps30);
ColorImagePoint rightKneeColorPoint =
depth.MapToColorImagePoint(rightKnee.X, rightKnee.Y,
ColorImageFormat.RgbResolution640x480Fps30);
//Set location
CameraPosition(headImage, headColorPoint);
CameraPosition(leftEllipse, leftColorPoint);
CameraPosition(rightEllipse, rightColorPoint);
Joint LEFTKNEE = first.Joints[JointType.KneeLeft];
Joint RIGHTKNEE = first.Joints[JointType.KneeRight];
if ((LEFTKNEE.TrackingState == JointTrackingState.Inferred ||
LEFTKNEE.TrackingState == JointTrackingState.Tracked) &&
(RIGHTKNEE.TrackingState == JointTrackingState.Tracked ||
RIGHTKNEE.TrackingState == JointTrackingState.Inferred))
{
CameraPosition(rightknee, rightKneeColorPoint);
CameraPosition(leftknee, leftKneeColorPoint);
}
else if (LEFTKNEE.TrackingState == JointTrackingState.Inferred ||
LEFTKNEE.TrackingState == JointTrackingState.Tracked)
{
CameraPosition(leftknee, leftKneeColorPoint);
}
else if (RIGHTKNEE.TrackingState == JointTrackingState.Inferred ||
RIGHTKNEE.TrackingState == JointTrackingState.Tracked)
{
CameraPosition(rightknee, rightKneeColorPoint);
}
}
}
Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e)
{
using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
{
if (skeletonFrameData == null)
{
return null;
}
skeletonFrameData.CopySkeletonDataTo(allSkeletons);
//get the first tracked skeleton
Skeleton first = (from s in allSkeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s).FirstOrDefault();
return first;
}
}
private void StopKinect(KinectSensor sensor)
{
if (sensor != null)
{
if (sensor.IsRunning)
{
//stop sensor
sensor.Stop();
//stop audio if not null
if (sensor.AudioSource != null)
{
sensor.AudioSource.Stop();
}
}
}
}
private void CameraPosition(FrameworkElement element, ColorImagePoint point)
{
//Divide by 2 for width and height so point is right in the middle
// instead of in top/left corner
Canvas.SetLeft(element, point.X - element.Width / 2);
Canvas.SetTop(element, point.Y - element.Height / 2);
}
private void ScalePosition(FrameworkElement element, Joint joint)
{
//convert the value to X/Y
//Joint scaledJoint = joint.ScaleTo(1280, 720);
//convert & scale (.3 = means 1/3 of joint distance)
Joint scaledJoint = joint.ScaleTo(1280, 720, .3f, .3f);
Canvas.SetLeft(element, scaledJoint.Position.X);
Canvas.SetTop(element, scaledJoint.Position.Y);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
closing = true;
StopKinect(kinectSensorChooser1.Kinect);
}
private void kinectDepthViewer1_Loaded(object sender, RoutedEventArgs e)
{
}
}
}
XAML
<Window x:Class="SkeletalTracking.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded"
xmlns:my="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers"
Closing="Window_Closing" WindowState="Maximized">
<Canvas Name="MainCanvas">
<my:KinectColorViewer Canvas.Left="0" Canvas.Top="0" Width="640" Height="480" Name="kinectColorViewer1"
Kinect="{Binding ElementName=kinectSensorChooser1, Path=Kinect}" />
<Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="leftEllipse" Width="50" Fill="#FF4D298D" Opacity="1" Stroke="White" />
<Ellipse Canvas.Left="100" Canvas.Top="0" Fill="#FF2CACE3" Height="50" Name="rightEllipse" Width="50" Opacity="1" Stroke="White" />
<my:KinectSensorChooser Canvas.Left="250" Canvas.Top="380" Name="kinectSensorChooser1" Width="328" />
<Image Canvas.Left="66" Canvas.Top="90" Height="87" Name="headImage" Stretch="Fill" Width="84" Source="/SkeletalTracking;component/c4f-color.png" />
<Ellipse Canvas.Left="283" Canvas.Top="233" Height="23" Name="leftknee" Stroke="Black" Width="29" />
<Ellipse Canvas.Left="232" Canvas.Top="233" Height="23" Name="rightknee" Stroke="Black" Width="30" />
</Canvas>
Aquí hay una foto solo para mostrar cómo de a veces Kinect puede estar:
Sugerencia: observe cómo solo se detecta mi brazo y parte del fondo
El kinect no puede rastrear el esqueleto con precisión debido a las limitaciones en su propio SDK. Essentiall cada vez que el dispositivo intenta levantar un esqueleto, siempre asume que está de frente. Si guarda las uniones, tome una vista de arriba abajo y trace las coordenadas xyz, esto se ve con bastante facilidad.
También estoy trabajando con Kinect, puede obtener el valor de los ángulos de articulación para los ángulos de articulación de su rodilla, pero el problema que parece estar enfrentando se debe al propio Kinect ya que no se muestran los valores inferidos. Es mejor utilizar todo el cuerpo del esqueleto para rastrear su rodilla y, con suerte, obtendrá todos los valores para el movimiento de cada articulación.