简体   繁体   中英

How to track only one person/body with Kinect v2 in C#

I would like to track the first person, and use only the body of this person.

So basically when one person is tracked, and there are people walking behind him or are looking with this guy, if they move, the kinect shouldn't recognise anyone else.

I am using the sample code form the SDK 2.0 "Body Basics-WPF" in C#. My goal is to recognize only a few joints(successfully done) form only one person. I've found a thread how you can make it for Kinect v1, but nothing for Kinect v2. Here the code:

private void Reader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
    {
        bool dataReceived = false;

        using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
        {
            if (bodyFrame != null)
            {
                if (this.bodies == null)
                {
                   this.bodies = new Body[bodyFrame.BodyCount];   
                }

                bodyFrame.GetAndRefreshBodyData(this.bodies);
                dataReceived = true;
            }
        }

        if (dataReceived)
        {
            using (DrawingContext dc = this.drawingGroup.Open())
            {
                dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, this.displayWidth, this.displayHeight));

                int penIndex = 0;

                foreach (Body body in this.bodies) 
                {

                    Pen drawPen = this.bodyColors[penIndex++];

                    if (body.IsTracked)
                    {
                        this.DrawClippedEdges(body, dc);

                        IReadOnlyDictionary<JointType, Joint> joints = body.Joints;
                        Dictionary<JointType, Point> jointPoints = new Dictionary<JointType, Point>(); 

                        foreach (JointType jointType in joints.Keys)
                        {
                            if (jointType == JointType.ShoulderRight || jointType == JointType.ElbowRight || jointType == JointType.WristRight || jointType == JointType.HandRight ||
                                jointType == JointType.ShoulderLeft || jointType == JointType.ElbowLeft || jointType == JointType.WristLeft || jointType == JointType.HandLeft)
                            {

                                CameraSpacePoint position = joints[jointType].Position;
                                if (position.Z < 0)
                                {
                                    position.Z = InferredZPositionClamp;
                                }

                                DepthSpacePoint depthSpacePoint = this.coordinateMapper.MapCameraPointToDepthSpace(position);
                                jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y);     
                            }
                        }

                        this.DrawBody(joints, jointPoints, dc, drawPen);
                    }
                }

                this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, this.displayWidth, this.displayHeight));
            }
        }
    }

Quiet a time ago but I manage this Problem with a own Function to Keep one Person tracked. If the tracked Person leave the next top Body in the Body Array get the "Tracked Person".

private ulong currTrackingId = 0;
private Body GetActiveBody()
{
    if (currTrackingId <= 0)
    {
        foreach (Body body in this.bodies)
        {
            if (body.IsTracked)
            {
                currTrackingId = body.TrackingId;
                return body;
            }
        }

        return null;
    }
    else
    {
        foreach (Body body in this.bodies)
        {
            if (body.IsTracked && body.TrackingId == currTrackingId)
            {
                return body;
            }
        }
    }

    currTrackingId = 0;
    return GetActiveBody();
}

I worked with the older Kinect and still haven't got the new one so this might or might not work: if bodyFrame.BodyCount will just give you the number of people facing the Kinect then replace it with a 1 so your code becomes:

this.bodies = new Body[1];

I think usually the kinect will pick the closest person. Try it and tell me what you get.

Instead of using a foreach to iterate the bodies array, just use the first body in the list.

Replace:

foreach (Body body in this.bodies) 
{
   if (body.IsTracked) 
   {
      ...

With:

var body = this.bodies[0];
if (body.tracked)
{
    ...

UPDATE:

I just tried this using Kinect Studio and I found that even when there is only one tracked body, it is not guaranteed to be in the first slot of the array. In my app, for now I'm using LINQ to get the first body where IsTracked == true. I don't have a good answer on how to do this for production ready code. If I solve this problem I'll update this post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM