/// <summary>
 /// 現在のフレームのレコード・ユーザを信頼できるデータとしてタグ付けする
 /// TODO : UI上で特別なデータは色とかで反映する
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void CheckTrustDataFrame_Click(object sender, RoutedEventArgs e)
 {
     // record, userを選択中のやつ
     for (int recordNo = 0; recordNo < frameSequence.recordNum; recordNo++)
     {
         if (this.isRecordSelected[recordNo])
         {
             int       record = recordNo;
             int       user   = this.frameSequence.selecteedIntegretedIdList[recordNo];
             int       frame  = this.playingIndex;
             TrustData td     = new TrustData(frame, record, user);
             // こいつをUI上で反映する手がかりにする
             SerializableBody body = td.GetBody(this.frameSequence.Frames);
             body.trustData = true;
             this.frameSequence.trustData.Add(td);
         }
     }
 }
예제 #2
0
        public void DeleteBody(int recordNo, int integratedId = -1, ulong originalId = 0)
        {
            MotionData md = this.records[recordNo];

            for (int i = 0; i < md.bodies.Length; i++)
            {
                SerializableBody body = md.bodies[i];
                if (integratedId != -1 && body.integratedId == integratedId)
                {
                    Array.Clear(md.bodies, i, 1);
                }
                else if (originalId != 0 && body.TrackingId == originalId)
                {
                    Array.Clear(md.bodies, i, 1);
                }
            }
            md.bodies = md.bodies.Where(b => b != null).ToArray();
        }
예제 #3
0
        /// <summary>
        /// idの一致するBodyを返す
        /// </summary>
        /// <param name="recordNo"></param>
        /// <param name="integratedId"></param>
        /// <param name="originalId"></param>
        /// <returns></returns>
        public SerializableBody GetSelectedBody(int recordNo, int integratedId = -1, ulong originalId = 0)
        {
            SerializableBody body = null;

            if (integratedId != -1)
            {
                body = this.records[recordNo].bodies.Where((b) => b.integratedId == integratedId).FirstOrDefault();
            }
            else if (originalId != 0)
            {
                body = this.records[recordNo].bodies.Where((b) => b.TrackingId == originalId).FirstOrDefault();
            }
            /// idが違うときの場合. 本来はセグメンテーションすべき.
            if (body == null || body.Equals(default(SerializableBody)))
            {
                return(null);
            }
            return(body);
        }
예제 #4
0
        /// <summary>
        /// idの一致するBody[]を返す
        /// </summary>
        /// <param name="selectedUserIdList"></param>
        /// <returns></returns>
        public List <SerializableBody> GetSelectedBodyList(int[] integratedIds = null, ulong[] originalIds = null)
        {
            List <SerializableBody> bodies = new List <SerializableBody>();

            for (int recordNo = 0; recordNo < this.recordNum; recordNo++)
            {
                SerializableBody body = null;
                if (integratedIds != null && integratedIds.Count() == this.recordNum)
                {
                    body = this.GetSelectedBody(recordNo, integratedId: integratedIds[recordNo]);
                }
                else if (originalIds != null && originalIds.Count() == this.recordNum)
                {
                    body = this.GetSelectedBody(recordNo, originalId: originalIds[recordNo]);
                }
                if (body == null)
                {
                    return(new List <SerializableBody>());
                }
                bodies.Add(body);
            }
            return(bodies);
        }
        /// <summary>
        /// 修正してくれるやつ
        /// </summary>
        /// <param name="frameSeq"></param>
        public static void Correct(FrameSequence frameSeq)
        {
            List <OrderTuple> orders = new List <OrderTuple>();

            foreach (var pair in frameSeq.Frames.Select((frame, index) => Tuple.Create(frame, index)))
            {
                for (int recordNo = 0; recordNo < pair.Item1.recordNum; recordNo++)
                {
                    orders.Add(new OrderTuple(pair.Item1.Time, recordNo, pair.Item2));
                }
            }
            // 前フレームのユーザと対応するBodyを保持する
            Dictionary <int, SerializableBody>[] prevUserBodyMapArray = new Dictionary <int, SerializableBody> [frameSeq.recordNum];
            for (int i = 0; i < frameSeq.recordNum; i++)
            {
                prevUserBodyMapArray[i] = new Dictionary <int, SerializableBody>();
            }
            SerializableBody prevUserBody;

            orders = orders.OrderBy(x => x.Timestamp.Ticks).ToList();
            SkeletonInterpolator interp = new SkeletonInterpolator(0.5, true);

            foreach (OrderTuple tuple in orders)
            {
                Frame             currFrame   = frameSeq.Frames[tuple.FrameIndex];
                const long        maxInterval = (long)(10000000 * 0.1);
                DateTime          prev        = new DateTime(tuple.Timestamp.Ticks - maxInterval);
                IEnumerable <int> users       = currFrame.GetBodyList(tuple.RecordIndex).Select(b => b.integratedId);
                foreach (int user in users)
                {
                    SerializableBody currBody = currFrame.GetSelectedBody(tuple.RecordIndex, integratedId: user);
                    // 前のBodyと比較して同じ場合は処理をスキップする
                    if (prevUserBodyMapArray[tuple.RecordIndex].TryGetValue(user, out prevUserBody) && prevUserBody.Joints != null && currBody.Joints != null)
                    {
                        double avgDistanceSq = CalcBodyDistanceSq(prevUserBody.Joints, currBody.Joints).Values.Average();
                        if (avgDistanceSq == 0.0)
                        {
                            //currFrame.DeleteBody(tuple.RecordIndex, integratedId: user);
                            continue;
                        }
                    }
                    prevUserBodyMapArray[tuple.RecordIndex][user] = currBody;

                    Dictionary <JointType, CvPoint3D64f> prevJoints = interp.IntegrateSkeleton(prev, user, frameSeq);
                    if (prevJoints != null && currBody.Joints != null)
                    {
                        Dictionary <JointType, CvPoint3D64f> currJoints = currBody.Joints.ToDictionary(p => p.Key, p => (CvPoint3D64f)p.Value.Position.ToCvPoint3D());
                        HashSet <JointType> mirroredPrevKeys            = new HashSet <JointType>(prevJoints.Keys.Select(j => CalcEx.GetMirroredJoint(j)));
                        if (currJoints != null && prevJoints != null)
                        {
                            var absJoints         = currJoints.ToDictionary(p => p.Key, p => CvEx.ConvertPoint3D(p.Value, frameSeq.ToWorldConversions[tuple.RecordIndex]));
                            var absMirroredJoints = absJoints.ToDictionary(p => CalcEx.GetMirroredJoint(p.Key), p => p.Value);
                            var availableKeys     = prevJoints.Keys.Where(j => mirroredPrevKeys.Contains(j)).ToList();
                            var keysNormal        = availableKeys.Intersect(absJoints.Keys).ToList();
                            var keysMirrored      = availableKeys.Intersect(absMirroredJoints.Keys).ToList();

                            if (keysNormal.Count > 0 && keysMirrored.Count > 0)
                            {
                                double avg1 = keysNormal.Select(j => CvEx.GetDistanceSq(prevJoints[j], absJoints[j])).Average();
                                double avg2 = keysMirrored.Select(j => CvEx.GetDistanceSq(prevJoints[j], absMirroredJoints[j])).Average();
                                if (avg2 < avg1)
                                {
                                    currFrame.InverseBody(tuple.RecordIndex, integratedId: user);
                                }
                            }
                        }
                    }
                }
            }
        }
        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            // select
            if (e.Key == Key.S)
            {
                var focusedElement = FocusManager.GetFocusedElement(this);
                // 上のスライダー
                if (IsSeeking == true && focusedElement == this.PlaySlider)
                {
                    this.endIndex = (int)this.PlaySlider.Value;
                    this.PlaySlider.SelectionEnd = this.endIndex;

                    foreach (Slider slider in this.recordSliders)
                    {
                        slider.Maximum = this.endIndex;
                    }
                    IsSeeking = false;
                }
                // レコードスライダー
                else if (IsSeeking == true && focusedElement is Slider)
                {
                    rect = null;
                    Slider slider = (Slider)focusedElement;
                    int    index  = slider.Name[slider.Name.Length - 1] - '0' - 1;
                    // フレーム範囲を無効に
                    IEnumerable <Frame> frames = frameSequence.Slice(this.recordInvalidStart, (int)slider.Value);
                    foreach (Frame frame in frames)
                    {
                        frame.SetDataNotValid(index);
                    }
                    // 初期化
                    this.recordInvalidStart = this.frameSequence.Frames.Count;
                    IsSeeking = false;
                }
            }
            // reverse
            else if (e.Key == Key.R)
            {
                IEnumerable <int> range = Enumerable.Range(frameInverseList.Min(), (frameInverseList.Max() - frameInverseList.Min() + 1));
                foreach (int frameIndex in range)
                {
                    Frame frame = this.frameSequence.Frames[frameIndex];
                    this.InverseRecordUser(frame);
                }
                frameInverseList.Clear();
            }
            // delete upper body or legs
            else if (e.Key == Key.U || e.Key == Key.D)
            {
                IEnumerable <int> range = Enumerable.Range(frameRemoveList.Min(), (frameRemoveList.Max() - frameRemoveList.Min() + 1));
                foreach (int frameIndex in range)
                {
                    for (int recordNo = 0; recordNo < frameSequence.recordNum; recordNo++)
                    {
                        if (this.isRecordSelected[recordNo])
                        {
                            SerializableBody body = this.frameSequence.Frames[frameIndex].GetSelectedBody(recordNo, frameSequence.selecteedIntegretedIdList[recordNo]);
                            if (body != null)
                            {
                                if (e.Key == Key.U)
                                {
                                    body.RemoveJoints(Utility.UpperBody);
                                }
                                else if (e.Key == Key.D)
                                {
                                    body.RemoveJoints(Utility.Legs);
                                }
                            }
                        }
                    }
                }
                frameRemoveList.Clear();
            }
        }
예제 #7
0
        public static Tuple <Dictionary <int, List <Dictionary <JointType, CvPoint3D64f> > >, Dictionary <int, List <DateTime> > > ExportFromProject(FrameSequence frameseq, int startIndex, int endIndex)
        {
            TimeSpan        period     = new TimeSpan((long)(10000000 / frameseq.frameRate));
            List <DateTime> timestamps = new List <DateTime>();

            for (DateTime time = frameseq.Frames[startIndex].Time; time < frameseq.Frames[endIndex].Time; time += period)
            {
                timestamps.Add(time);
            }

            HashSet <Tuple <int, JointType> > uniqueUserJoint = new HashSet <Tuple <int, JointType> >();
            List <Frame> frames = frameseq.Slice(startIndex, endIndex);

            foreach (Frame frame in frames)
            {
                for (int i = 0; i < frameseq.recordNum; i++)
                {
                    foreach (SerializableBody body in frame.GetBodyList(i))
                    {
                        foreach (JointType jointType in Utility.GetValidJoints(body.Joints).Keys)
                        {
                            // TrackingIdと勝手に作ったuser idの対応辞書が必要. 以下の処理はとりあえず
                            Tuple <int, JointType> userJoint = new Tuple <int, JointType>(body.integratedId, jointType);
                            if (!uniqueUserJoint.Contains(userJoint))
                            {
                                uniqueUserJoint.Add(userJoint);
                            }
                        }
                    }
                }
            }

            List <Tuple <int, JointType> > userJointPairs = (
                from pair in uniqueUserJoint
                orderby pair.Item1, pair.Item2
                select pair
                ).ToList();

            Dictionary <int, List <Dictionary <JointType, CvPoint3D64f> > > allBodies = new Dictionary <int, List <Dictionary <JointType, CvPoint3D64f> > >();
            Dictionary <int, List <DateTime> > allTimes = new Dictionary <int, List <DateTime> >();
            SkeletonInterpolator skeletonInterpolator   = new SkeletonInterpolator(0.5, true);

            foreach (int user in userJointPairs.Select(p => p.Item1).Distinct())
            {
                skeletonInterpolator.pivot = new Dictionary <JointType, CvPoint3D64f>();
                // pivot初期化処理
                Dictionary <JointType, Joint>[] firstJoints = new Dictionary <JointType, Joint> [frameseq.recordNum];
                for (int no = 0; no < frameseq.recordNum; no++)
                {
                    var bodies = frameseq.GetNextData(no, timestamps[0]).bodies;
                    if (bodies.Count() > 0)
                    {
                        SerializableBody body = bodies.Where(b => b.integratedId == user).FirstOrDefault();
                        if (body != null)
                        {
                            var validJoints = Utility.GetValidJoints(body.Joints).ToDictionary(p => p.Key, p => (CvPoint3D64f)p.Value.Position.ToCvPoint3D());
                            if (skeletonInterpolator.pivot.Count < validJoints.Count)
                            {
                                skeletonInterpolator.pivot = validJoints;
                            }
                        }
                    }
                }

                List <Dictionary <JointType, CvPoint3D64f> > jointsSeq = new List <Dictionary <JointType, CvPoint3D64f> >();
                List <DateTime> times = new List <DateTime>();
                foreach (DateTime time in timestamps)
                {
                    Dictionary <JointType, CvPoint3D64f> joints = skeletonInterpolator.IntegrateSkeleton(time, user, frameseq);
                    // jointsがnullの場合にはダミーデータを突っ込んで長さを稼ぐ
                    if (joints == null)
                    {
                        jointsSeq.Add(new Dictionary <JointType, CvPoint3D64f>()
                        {
                            { JointType.SpineBase, new CvPoint3D64f(float.MaxValue, float.MaxValue, float.MaxValue) }
                        });
                    }
                    else
                    {
                        jointsSeq.Add(joints);
                    }
                    times.Add(time);
                }
                allBodies[user] = jointsSeq;
                allTimes[user]  = times;
            }
            return(Tuple.Create(allBodies, allTimes));
        }
예제 #8
0
        public Dictionary <JointType, CvPoint3D64f> IntegrateSkeleton(DateTime time, int userInt, FrameSequence frameSeq)
        {
            List <CvMat>            ToWorldConversions = frameSeq.ToWorldConversions;
            List <CameraIntrinsics> cameraInfo         = frameSeq.CameraInfo;
            List <UserSegmentation> segm = frameSeq.Segmentations;

            Dictionary <JointType, CvPoint3D64f>[] jointsArr      = new Dictionary <JointType, CvPoint3D64f> [frameSeq.recordNum];
            Dictionary <JointType, CvPoint3D64f>[] pivotCandidate = new Dictionary <JointType, CvPoint3D64f> [frameSeq.recordNum];

            double[] reliabilityArr = new double[frameSeq.recordNum];
            double[] weightArr      = new double[frameSeq.recordNum];

            for (int recordNo = 0; recordNo < frameSeq.recordNum; recordNo++)
            {
                MotionData prevData = frameSeq.GetPrevData(recordNo, time);
                MotionData nextData = frameSeq.GetNextData(recordNo, time);

                if (prevData == null || nextData == null || prevData.bodies.Length * nextData.bodies.Length == 0 || !prevData.isValid || !nextData.isValid)
                {
                    jointsArr[recordNo]      = null;
                    reliabilityArr[recordNo] = 0;
                    weightArr[recordNo]      = 0;
                    continue;
                }

                SerializableBody prevBody = prevData.bodies.Where(b => b.integratedId == userInt).FirstOrDefault();
                SerializableBody nextBody = nextData.bodies.Where(b => b.integratedId == userInt).FirstOrDefault();
                if (prevBody == null || nextBody == null || prevBody.Equals(default(SerializableBody)) || nextBody.Equals(default(SerializableBody)))
                {
                    jointsArr[recordNo]      = null;
                    reliabilityArr[recordNo] = 0;
                    weightArr[recordNo]      = 0;
                    continue;
                }
                // 統計情報によるフィルタリング
                Dictionary <JointType, Joint> prevJoints;
                Dictionary <JointType, Joint> nextJoints;
                if (prevBody.Joints == null || nextBody.Joints == null)
                {
                    continue;
                }

                // pivotが設定されてるとき、つまり、本番統合のとき
                if (pivot != null)
                {
                    // mirror矯正
                    prevJoints = this.CorrectMirrorJoint(prevBody.Joints, ToWorldConversions[recordNo]);
                    nextJoints = this.CorrectMirrorJoint(nextBody.Joints, ToWorldConversions[recordNo]);
                    // next pivot候補つめつめ
                    pivotCandidate[recordNo] = Utility.GetValidJoints(nextJoints).ToDictionary(p => p.Key, p => (CvPoint3D64f)p.Value.Position.ToCvPoint3D());
                }
                else
                {
                    prevJoints = prevBody.Joints;
                    nextJoints = nextBody.Joints;
                }

                // 統計情報があるとき
                if (frameSeq.BodyStat != null)
                {
                    prevJoints = frameSeq.BodyStat.FilterBonesByStatistics(prevJoints);
                    nextJoints = frameSeq.BodyStat.FilterBonesByStatistics(nextJoints);
                }
                else
                {
                    prevJoints = Utility.GetValidJoints(prevBody.Joints);
                    nextJoints = Utility.GetValidJoints(nextBody.Joints);
                }

                jointsArr[recordNo]      = this.InterpolateSkeleton(prevData, nextData, prevJoints, nextJoints, time, ToWorldConversions[recordNo]);
                reliabilityArr[recordNo] = this.GetSkeletonReliability(prevData, nextData, prevJoints, nextJoints, time, cameraInfo[recordNo]);
                weightArr[recordNo]      = this.GetVarianceWeight(prevData, nextData, prevJoints, nextJoints, time);
            }

            // pivot更新
            pivot = new Dictionary <JointType, CvPoint3D64f>();
            foreach (var candidate in pivotCandidate)
            {
                if (candidate != null && pivot.Count <= candidate.Count)
                {
                    pivot = candidate;
                }
            }

            double maxWeight = weightArr.Max();

            double[] modifiedReliabilityList = weightArr.Select(w => Math.Max(0, (w / maxWeight) - _weightBase)).Zip(reliabilityArr, (a, b) => a * b).ToArray();
            var      keys = jointsArr.Where(j => j != null).SelectMany(j => j.Keys).Distinct().ToList();

            if (maxWeight == 0)
            {
                return(null);
            }

            return(CalcEx.LinearMedianSkeletons(jointsArr, modifiedReliabilityList));
        }
예제 #9
0
        public void Correct(FrameSequence frameSeq)
        {
            // 選択中の統合IDをチェック
            List <TrustData> trustDatas = frameSeq.trustData.Where(t => t.integratedBodyId == frameSeq.selecteedIntegretedIdList[0]).ToList();
            // generate iteration
            List <Tuple <TrustData, int> > iterations = this.GenerateIterationRanges(frameSeq.Frames.Count(), frameSeq.trustData);

            foreach (Tuple <TrustData, int> iterationRange in iterations)
            {
                // set and calcurate pivot
                TrustData        trustData = iterationRange.Item1;
                SerializableBody pivotBody = trustData.GetBody(frameSeq.Frames);
                // translate to world coordinate
                Dictionary <JointType, CvPoint3D64f> pivotJoints = pivotBody.Joints.ToDictionary(p => p.Key,
                                                                                                 p => CvEx.ConvertPoint3D(p.Value.Position.ToCvPoint3D(), frameSeq.ToWorldConversions[trustData.recordIndex]));
                CvPoint3D64f pivotBodyRightVector = this.CalcRightChestCrossVector(pivotJoints);
                CvPoint3D64f pivotBodyLeftVector  = this.CalcLeftChestCrossVector(pivotJoints);
                CvPoint3D64f pivotBodyCrossVector = CvEx.Normalize(pivotBodyRightVector + pivotBodyLeftVector);
                // z軸との角度 +だったらあっち向いてる
                double pivotCrossZCos = CvEx.Cos(pivotBodyCrossVector, new CvPoint3D64f(0, 0, 1));
                // ので、反転してたら修正する
                if (pivotCrossZCos > 0)
                {
                    pivotBody.InverseJoints();
                    pivotJoints = pivotBody.Joints.ToDictionary(p => p.Key,
                                                                p => CvEx.ConvertPoint3D(p.Value.Position.ToCvPoint3D(), frameSeq.ToWorldConversions[trustData.recordIndex]));
                    pivotBodyRightVector = this.CalcRightChestCrossVector(pivotJoints);
                    pivotBodyLeftVector  = this.CalcLeftChestCrossVector(pivotJoints);
                    pivotBodyCrossVector = CvEx.Normalize(pivotBodyRightVector + pivotBodyLeftVector);
                }

                // 繰り返し範囲の連続indexを生成して回す
                IEnumerable <int> continuousRange = this.GenerateContinuousRange(trustData.frameIndex, iterationRange.Item2);
                foreach (int frameIndex in continuousRange)
                {
                    // 前のpivotとのベクトルの差が小さいやつを選んでいく投票空間
                    double[]       bodyCos     = new double[frameSeq.recordNum];
                    CvPoint3D64f[] bodyCrosses = new CvPoint3D64f[frameSeq.recordNum];
                    bool[]         validFlags  = frameSeq.Frames[frameIndex].GetValidFlags();
                    for (int recordNo = 0; recordNo < frameSeq.recordNum; recordNo++)
                    {
                        // pivotと一致した場合
                        if (trustData.recordIndex == recordNo && trustData.frameIndex == frameIndex)
                        {
                            bodyCos[recordNo]     = 1;
                            bodyCrosses[recordNo] = pivotBodyCrossVector;
                            continue;
                        }
                        SerializableBody body = frameSeq.Frames[frameIndex].GetSelectedBody(recordNo, integratedId: trustData.integratedBodyId);
                        if (body == null || body == default(SerializableBody) || body.Joints.Count == 0 || validFlags[recordNo] == false)
                        {
                            bodyCos[recordNo] = -1;
                            continue;
                        }
                        Dictionary <JointType, CvPoint3D64f> joints = body.Joints.ToDictionary(p => p.Key,
                                                                                               p => CvEx.ConvertPoint3D(p.Value.Position.ToCvPoint3D(), frameSeq.ToWorldConversions[recordNo]));
                        // 右胸、左胸の外積ベクトル(正規化済み)
                        CvPoint3D64f rightVector = this.CalcRightChestCrossVector(joints);
                        CvPoint3D64f leftVector  = this.CalcLeftChestCrossVector(joints);
                        // 前フレームの基準ベクトルとの角度(cos)
                        double bothCrossAngle  = CvEx.Cos(rightVector, leftVector);
                        double rightPivotAngle = CvEx.Cos(rightVector, pivotBodyCrossVector);
                        double leftPivotAngle  = CvEx.Cos(leftVector, pivotBodyCrossVector);
                        bool   removedFlag     = false;
                        // そもそも骨がなかった場合
                        if (rightVector == default(CvPoint3D64f))
                        {
                            body.RemoveJoints(Utility.RightBody);
                            removedFlag = true;
                        }
                        if (leftVector == default(CvPoint3D64f))
                        {
                            body.RemoveJoints(Utility.LeftBody);
                            removedFlag = true;
                        }
                        // 右と左のベクトルが離れすぎてる場合
                        if (bothCrossAngle <= 0)
                        {
                            body.RemoveJoints(Utility.UpperBody);
                            removedFlag = true;
                        }
                        if (removedFlag)
                        {
                            bodyCos[recordNo] = -1;
                            continue;
                        }

                        CvPoint3D64f bodyCrossVector = CvEx.Normalize(rightVector + leftVector);
                        double       bodyCrossdiff   = CvEx.Cos(bodyCrossVector, pivotBodyCrossVector);
                        // reverse check
                        if (bodyCrossdiff <= -0.8)
                        {
                            // reverse and update
                            body.InverseJoints();
                            joints = body.Joints.ToDictionary(p => p.Key,
                                                              p => CvEx.ConvertPoint3D(p.Value.Position.ToCvPoint3D(), frameSeq.ToWorldConversions[recordNo]));
                            rightVector     = this.CalcRightChestCrossVector(joints);
                            leftVector      = this.CalcLeftChestCrossVector(joints);
                            bodyCrossVector = CvEx.Normalize(rightVector + leftVector);
                            bodyCrossdiff   = CvEx.Cos(bodyCrossVector, pivotBodyCrossVector);
                        }
                        // update body angle
                        bodyCos[recordNo]     = bodyCrossdiff;
                        bodyCrosses[recordNo] = bodyCrossVector;
                    }
                    // 前のpivotVectorと似ているほどよい. つまり1に近いほど
                    int pivotRecordNo = bodyCos.ToList().IndexOf(bodyCos.Max());
                    // update pivot body vector
                    pivotBodyCrossVector = bodyCrosses[pivotRecordNo];
                }
            }
        }