コード例 #1
0
        // Initialize the filter with a set of SmoothParameters.
        public void Init(SmoothParameters smoothParameters)
        {
            this.smoothingType    = SmoothingType.Default;
            this.smoothParameters = smoothParameters;

            Reset();
            init = true;
        }
コード例 #2
0
        /// <summary>
        /// Initialize the filter with a set of manually specified TransformSmoothParameters.
        /// </summary>
        /// <param name="smoothingValue">Smoothing = [0..1], lower values is closer to the raw data and more noisy.</param>
        /// <param name="correctionValue">Correction = [0..1], higher values correct faster and feel more responsive.</param>
        /// <param name="predictionValue">Prediction = [0..n], how many frames into the future we want to predict.</param>
        /// <param name="jitterRadiusValue">JitterRadius = The deviation distance in m that defines jitter.</param>
        /// <param name="maxDeviationRadiusValue">MaxDeviation = The maximum distance in m that filtered positions are allowed to deviate from raw data.</param>
        public void Init(float smoothingValue, float correctionValue, float predictionValue, float jitterRadiusValue, float maxDeviationRadiusValue)
        {
            this.smoothingType = SmoothingType.Default;
            smoothParameters   = new SmoothParameters();

            smoothParameters.smoothing          = smoothingValue;          // How much soothing will occur.  Will lag when too high
            smoothParameters.correction         = correctionValue;         // How much to correct back from prediction.  Can make things springy
            smoothParameters.prediction         = predictionValue;         // Amount of prediction into the future to use. Can over shoot when too high
            smoothParameters.jitterRadius       = jitterRadiusValue;       // Size of the radius where jitter is removed. Can do too much smoothing when too high
            smoothParameters.maxDeviationRadius = maxDeviationRadiusValue; // Size of the max prediction radius Can snap back to noisy data when too high

            // Check for divide by zero. Use an epsilon of a 10th of a millimeter
            smoothParameters.jitterRadius = Math.Max(0.0001f, this.smoothParameters.jitterRadius);

            Reset();
            init = true;
        }
コード例 #3
0
        // Initialize the filter with a set of SmoothParameters.
        public void Init(SmoothingType smoothingType)
        {
            this.smoothingType = smoothingType;
            smoothParameters   = new SmoothParameters();

            switch (smoothingType)
            {
            case SmoothingType.Light:
                smoothParameters.smoothing          = 0.3f;
                smoothParameters.correction         = 0.35f;
                smoothParameters.prediction         = 0.35f;
                smoothParameters.jitterRadius       = 0.15f;
                smoothParameters.maxDeviationRadius = 0.15f;
                break;

            case SmoothingType.Medium:
                smoothParameters.smoothing          = 0.5f;
                smoothParameters.correction         = 0.1f;
                smoothParameters.prediction         = 0.5f;
                smoothParameters.jitterRadius       = 0.1f;
                smoothParameters.maxDeviationRadius = 0.1f;
                break;

            case SmoothingType.Aggressive:
                smoothParameters.smoothing          = 0.7f;
                smoothParameters.correction         = 0.3f;
                smoothParameters.prediction         = 1.0f;
                smoothParameters.jitterRadius       = 1.0f;
                smoothParameters.maxDeviationRadius = 1.0f;
                break;

            //case SmoothingType.Default:
            default:
                smoothParameters.smoothing          = 0.5f;
                smoothParameters.correction         = 0.5f;
                smoothParameters.prediction         = 0.5f;
                smoothParameters.jitterRadius       = 0.05f;
                smoothParameters.maxDeviationRadius = 0.04f;
                break;
            }

            Reset();
            init = true;
        }
コード例 #4
0
        //// Update the filter with a new frame of data and smooth.
        //public void UpdateFilter(ref KinectInterop.BodyData[] alTrackedBodies)
        //{
        //    if (!init)
        //    {
        //        // initialize with by-default parameters
        //        Init();
        //    }

        //    if (smoothingType == SmoothingType.None)
        //        return;

        //    SmoothParameters tempSmoothingParams = new SmoothParameters();
        //    tempSmoothingParams.smoothing = this.smoothParameters.smoothing;
        //    tempSmoothingParams.correction = this.smoothParameters.correction;
        //    tempSmoothingParams.prediction = this.smoothParameters.prediction;

        //    int bodyCount = alTrackedBodies != null ? alTrackedBodies.Length : 0;
        //    for (int bodyIndex = 0; bodyIndex < bodyCount; bodyIndex++)
        //    {
        //        if (alTrackedBodies[bodyIndex].bIsTracked)
        //        {
        //            FilterBodyJoints(ref alTrackedBodies[bodyIndex], /**bodyIndex*/ alTrackedBodies[bodyIndex].iBodyIndex, tempSmoothingParams);
        //        }
        //    }
        //}

        // Update the filter with a new frame of data and smooth.
        public void UpdateFilter(ref KinectInterop.BodyData bodyData)
        {
            if (!init)
            {
                // initialize with by-default parameters
                Init();
            }

            if (smoothingType == SmoothingType.None)
            {
                return;
            }

            SmoothParameters tempSmoothingParams = new SmoothParameters();

            tempSmoothingParams.smoothing  = smoothParameters.smoothing;
            tempSmoothingParams.correction = smoothParameters.correction;
            tempSmoothingParams.prediction = smoothParameters.prediction;

            if (bodyData.bIsTracked)
            {
                // get body index
                int bodyIndex = GetUserIndex(bodyData.liTrackingID);
                if (bodyIndex < 0)
                {
                    bodyIndex = GetFreeIndex();
                    if (bodyIndex >= 0)
                    {
                        history[bodyIndex].userId = bodyData.liTrackingID;
                    }
                    //Debug.Log("Created history for userId: " + history[bodyIndex].userId + ", index: " + bodyIndex + ", time: " + DateTime.UtcNow);
                }

                // filter
                if (bodyIndex >= 0)
                {
                    FilterBodyJoints(ref bodyData, bodyIndex, tempSmoothingParams);
                }
            }

            // free unused history
            //CleanUpUserHistory();
        }
コード例 #5
0
        // Update the filter for one joint
        private Vector3 FilterJoint(Vector3 rawPosition, int bodyIndex, int jointIndex, SmoothParameters smoothingParameters)
        {
            Vector3 filteredPosition;
            Vector3 diffVec;
            Vector3 trend;
            float   diffVal;

            Vector3 prevFilteredPosition = history[bodyIndex].jointHistory[jointIndex].filteredPosition;
            Vector3 prevTrend            = history[bodyIndex].jointHistory[jointIndex].trend;
            Vector3 prevRawPosition      = history[bodyIndex].jointHistory[jointIndex].rawPosition;
            bool    jointIsValid         = (rawPosition != Vector3.zero);

            // If joint is invalid, reset the filter
            if (!jointIsValid)
            {
                history[bodyIndex].jointHistory[jointIndex].frameCount = 0;
            }

            // Initial start values
            if (history[bodyIndex].jointHistory[jointIndex].frameCount == 0)
            {
                filteredPosition = rawPosition;
                trend            = Vector3.zero;
            }
            else if (history[bodyIndex].jointHistory[jointIndex].frameCount == 1)
            {
                filteredPosition = (rawPosition + prevRawPosition) * 0.5f;
                diffVec          = filteredPosition - prevFilteredPosition;
                trend            = (diffVec * smoothingParameters.correction) + (prevTrend * (1.0f - smoothingParameters.correction));
            }
            else
            {
                // First apply jitter filter
                diffVec = rawPosition - prevFilteredPosition;
                diffVal = Math.Abs(diffVec.magnitude);

                if (diffVal <= smoothingParameters.jitterRadius)
                {
                    filteredPosition = (rawPosition * (diffVal / smoothingParameters.jitterRadius)) + (prevFilteredPosition * (1.0f - (diffVal / smoothingParameters.jitterRadius)));
                }
                else
                {
                    filteredPosition = rawPosition;
                }

                // Now the double exponential smoothing filter
                filteredPosition = (filteredPosition * (1.0f - smoothingParameters.smoothing)) + ((prevFilteredPosition + prevTrend) * smoothingParameters.smoothing);

                diffVec = filteredPosition - prevFilteredPosition;
                trend   = (diffVec * smoothingParameters.correction) + (prevTrend * (1.0f - smoothingParameters.correction));
            }

            // Predict into the future to reduce latency
            Vector3 predictedPosition = filteredPosition + (trend * smoothingParameters.prediction);

            // Check that we are not too far away from raw data
            diffVec = predictedPosition - rawPosition;
            diffVal = Mathf.Abs(diffVec.magnitude);

            if (diffVal > smoothingParameters.maxDeviationRadius)
            {
                predictedPosition = (predictedPosition * (smoothingParameters.maxDeviationRadius / diffVal)) + (rawPosition * (1.0f - (smoothingParameters.maxDeviationRadius / diffVal)));
            }

            // Save the data from this frame
            history[bodyIndex].jointHistory[jointIndex].rawPosition      = rawPosition;
            history[bodyIndex].jointHistory[jointIndex].filteredPosition = filteredPosition;
            history[bodyIndex].jointHistory[jointIndex].trend            = trend;
            history[bodyIndex].jointHistory[jointIndex].frameCount++;

            DateTime dtNow = DateTime.UtcNow;

            history[bodyIndex].lastUpdateTime = dtNow.Ticks;

            //Debug.Log("Updated history for userId: " + history[bodyIndex].userId + ", index: " + bodyIndex + ", time: " + dtNow + " (" + history[bodyIndex].lastUpdateTime + ")");
            return(predictedPosition);
        }
コード例 #6
0
        // Update the filter for all body joints
        private void FilterBodyJoints(ref KinectInterop.BodyData bodyData, int bodyIndex, SmoothParameters tempSmoothingParams)
        {
            KinectManager manager    = KinectManager.Instance;
            int           jointCount = manager.GetJointCount();

            for (int jointIndex = 0; jointIndex < jointCount; jointIndex++)
            {
                // If not tracked, we smooth a bit more by using a bigger jitter radius
                // Always filter end joints highly as they are more noisy
                if (bodyData.joint[jointIndex].trackingState != KinectInterop.TrackingState.Tracked ||
                    jointIndex == (int)KinectInterop.JointType.FootLeft || jointIndex == (int)KinectInterop.JointType.FootRight ||
                    jointIndex == (int)KinectInterop.JointType.HandLeft || jointIndex == (int)KinectInterop.JointType.HandRight ||
                    jointIndex == (int)KinectInterop.JointType.HandtipLeft || jointIndex == (int)KinectInterop.JointType.HandtipRight ||
                    jointIndex == (int)KinectInterop.JointType.ThumbLeft || jointIndex == (int)KinectInterop.JointType.ThumbRight)
                //|| jointIndex == (int)KinectInterop.JointType.Head)
                {
                    tempSmoothingParams.jitterRadius       = smoothParameters.jitterRadius * 2.0f;
                    tempSmoothingParams.maxDeviationRadius = smoothParameters.maxDeviationRadius * 2.0f;
                }
                else
                {
                    tempSmoothingParams.jitterRadius       = smoothParameters.jitterRadius;
                    tempSmoothingParams.maxDeviationRadius = smoothParameters.maxDeviationRadius;
                }

                Vector3 jPosition = bodyData.joint[jointIndex].trackingState != KinectInterop.TrackingState.NotTracked ? bodyData.joint[jointIndex].position : Vector3.zero;
                bodyData.joint[jointIndex].position = FilterJoint(jPosition, bodyIndex, jointIndex, tempSmoothingParams);
            }

            bodyData.position = bodyData.joint[0].position;
        }