public ColoredIterativePointMatching(Frame frame, List<LocalCoordinateMapper> localCoordinateMappers, IList<CvMat> initialModelTransforms, Func<float, double> weightFromDistanceSq, double colorScale)
 {
     if (weightFromDistanceSq == null)
     {
         throw new ArgumentNullException("weightFromDistanceSq");
     }
     for (int i = 0; i < frame.recordNum; i++)
     {
         List<Tuple<CvPoint3D64f, CvColor>> modelPoints = localCoordinateMappers[i].GetUserColorPoints(frame.DepthMatList[i], frame.ColorMatList[i], frame.UserMatList[i]);
         FlannColoredModelPoints model = new FlannColoredModelPoints(modelPoints, new KDTreeIndexParams(), new SearchParams(), colorScale);
         _flannModels.Add(model);
     }
     if (_flannModels.Count != initialModelTransforms.Count)
     {
         throw new ArgumentException("transform list length must be same as model list length");
     }
     _modelTransforms = initialModelTransforms.ToList();
     _weightFromDistanceSq = weightFromDistanceSq;
 }
        /// <summary>
        /// あるフレームにおける座標変換行列を骨格情報から計算する
        /// </summary>
        /// <param name="frame"></param>
        /// <param name="convList"></param>
        /// <param name="bodies"></param>
        /// <returns></returns>
        public static List<CvMat> GetConvMatrixFromBoneFrame(Frame frame, List<CvMat> convList, List<SerializableBody> bodies)
        {
            if ( bodies.Count() != frame.recordNum )
            {
                System.Windows.MessageBox.Show("ユーザが選択されていないレコードがあります");
                return convList;
            }

            bool[] validFlags = frame.GetValidFlags();

            for (int j = 1; j < frame.recordNum; j++)
            {
                Dictionary<JointType, Joint> joint1 = Utility.GetValidJoints(bodies[0].Joints);
                Dictionary<JointType, Joint> joint2 = Utility.GetValidJoints(bodies[j].Joints);
                if (validFlags[0] && validFlags[j] == false)
                {
                    continue;
                }
                ICoordConversion3D crtc = new CoordRotTransConversion();
                foreach (JointType jointType in Enum.GetValues(typeof(JointType)))
                {
                    if (!joint1.ContainsKey(jointType))
                        continue;
                    if (!joint2.ContainsKey(jointType))
                        continue;
                    CvPoint3D64f from = joint2[jointType].Position.ToCvPoint3D();
                    CvPoint3D64f target = CvEx.ConvertPoint3D(joint1[jointType].Position.ToCvPoint3D(), convList[0]);
                    // IsOriginlJointValid相当の処理を入れるかどうか
                    crtc.PutPoint(from, target, 1);
                }
                convList[j] = crtc.Solve();
            }
            return convList;
        }
 /// <summary>
 /// あるフレームにおける座標変換行列を骨格情報から計算する
 /// </summary>
 /// <param name="frame"></param>
 /// <param name="convList"></param>
 /// <param name="selectedUserIdList"></param>
 /// <returns></returns>
 public static List<CvMat> GetConvMatrixFromBoneFrame(Frame frame, List<CvMat> convList, int[] integratedIs)
 {
     List<SerializableBody> bodies = frame.GetSelectedBodyList(integratedIds:integratedIs);
     return GetConvMatrixFromBoneFrame(frame, convList, bodies);
 }
 /// <summary>
 /// あるフレームにおける座標変換行列を骨格情報から計算する
 /// </summary>
 /// <param name="frame"></param>
 /// <param name="convList"></param>
 /// <param name="selectedUserIdList"></param>
 /// <returns></returns>
 public static List<CvMat> GetConvMatrixFromBoneFrame(Frame frame, List<CvMat> convList, ulong[] originalIds)
 {
     List<SerializableBody> bodies = frame.GetSelectedBodyList(originalIds:originalIds);
     return GetConvMatrixFromBoneFrame(frame, convList, bodies);
 }
 /// <summary>
 /// あるフレームにおける座標変換行列を深度情報から計算する
 /// </summary>
 /// <param name="frame"></param>
 public static List<CvMat> GetConvMatrixFromDepthFrame(Frame frame, List<CvMat> convList, List<LocalCoordinateMapper> localCoordinateMappers)
 {
     Func<float, double> distance2weight = x => 1.0 / (x * 0 + 400 / 1000f);
     using (ColoredIterativePointMatching sipm = new ColoredIterativePointMatching(frame, localCoordinateMappers, convList, distance2weight, 200))
     {
         List<CvMat> conversions = sipm.CalculateTransformSequntially(0.2, 3);
         return conversions;
     }
 }
        /// <summary>
        /// 時刻を少しずつ進めながらフレームを作っていく
        /// </summary>
        /// <param name="records"></param>
        /// <returns></returns>
        private List<Frame> GenerateFrames()
        {
            List<Frame> frames = new List<Frame>();
            List<Tuple<List<DateTime>, int[]>> timeInfos = new List<Tuple<List<DateTime>, int[]>>();
            foreach (List<MotionData> record in this.originalRecords)
            {
                DateTime[] dateTimes = record.Select(m => m.TimeStamp).ToArray();
                int[] indexes = record.Select((m, i) => i).ToArray();
                Array.Sort(dateTimes, indexes);
                timeInfos.Add(Tuple.Create(dateTimes.ToList(), indexes));
            }
            this.timeInfos = timeInfos;

            for (DateTime time = this.startTime; time <= this.endTime; time += this.timePeriod)

            {
                // 同時刻のフレーム集合. Kinectの数だけ入るはず.
                List<MotionData> currentRecords = new List<MotionData>();
                List<MotionData> nextRecords = new List<MotionData>();
                for (int i = 0; i < this.recordNum; i++)
                {
                    List<MotionData> record = this.originalRecords[i];
                    List<DateTime> dateTimes = timeInfos[i].Item1;
                    int[] indexes = timeInfos[i].Item2;
                    int frameIndex = ListEx.GetMaxLessEqualIndexFromBinarySearch(dateTimes.BinarySearch(time));
                    int nextIndex = ListEx.GetMinGreaterEqualIndexFromBinarySearch(dateTimes.BinarySearch(time));
                    if (frameIndex < 0)
                        frameIndex = 0;
                    if (frameIndex >= record.Count())
                        frameIndex = record.Count() - 1;
                    if (nextIndex < 0)
                        nextIndex = 0;
                    if (nextIndex >= record.Count())
                        nextIndex = record.Count() - 1;
                    currentRecords.Add(record[indexes[frameIndex]]);
                    nextRecords.Add(record[indexes[nextIndex]]);
                }
                Frame frame = new Frame(currentRecords, nextRecords);
                frame.Time = time;
                frames.Add(frame);
            }
            return frames;
        }