/// <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); } } } } } } }
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)); }
/// <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); } } } } } } }
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); }