예제 #1
0
        private void button1_Click_2(object sender, RoutedEventArgs e)
        {
            //以下修正
            MotionDataHandler handler;
            string            path;

            if (openMotionData(out handler, out path))
            {
                CvMat resultMat = null;
                int   length    = handler.FrameCount;

                IEnumerable <CvMat> depthImages;
                Utility.LoadImages(handler.GetDepthImagePaths(), out depthImages);

                foreach (CvMat depthMat in depthImages)
                {
                    CvSize depthUserSize = new CvSize(depthMat.Cols, depthMat.Rows);
                    CvEx.InitCvMat(ref resultMat, depthMat, MatrixType.U8C3);
                    resultMat.Zero();
                    double          avgDepth = depthMat.Select(v => v.Val0).Where(v => v != 0).Average();
                    double          pDepth   = CvEx.Get2DSubPixel(depthMat, new CvPoint2D32f(_undistortion.CameraStruct.PrincipalX, _undistortion.CameraStruct.PrincipalY), 0) ?? 0;
                    List <double>[] diffs    = Enumerable.Range(0, depthUserSize.Width).Select(x => new List <double>()).ToArray();
                    unsafe
                    {
                        short *depthArr = depthMat.DataInt16;
                        for (int y = 0; y < depthUserSize.Height; y++)
                        {
                            int offset = y * depthUserSize.Width;
                            for (int x = 0; x < depthUserSize.Width - 1; x++)
                            {
                                short l = depthArr[offset + x];
                                short r = depthArr[offset + x + 1];
                                if (l != 0 && r != 0)
                                {
                                    double ll = Math.Log(l);
                                    double rl = Math.Log(r);
                                    diffs[x].Add(ll - rl);
                                }
                            }
                        }
                    }
                    double[] median = diffs.Select(x => x.Count > 0 ? CalcEx.GetMedian(x) : 0).ToArray();
                    double   max    = median.Select(x => Math.Abs(x)).Max();
                    for (int x = 0; x < depthUserSize.Width; x++)
                    {
                        resultMat.DrawLine(new CvPoint(x, 0), new CvPoint(x, resultMat.Rows), new CvScalar(Math.Max(median[x] / max * 255, 0), Math.Max(-median[x] / max * 255, 0), 0));
                    }
                    resultMat.PutText(avgDepth.ToString("0.00000"), new CvPoint(0, 20), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));
                    resultMat.PutText(pDepth.ToString("0.00000"), new CvPoint(0, 40), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));

                    putImage(resultMat, PixelFormats.Rgb24);
                }
            }
        }
        /// <summary>
        /// Jointから絶対座標を引くDictionary二つの間の距離を求めます
        /// </summary>
        /// <param name="jointWithAbsPosition1">骨格ごとの絶対座標1</param>
        /// <param name="jointWithAbsPosition2">骨格ごとの絶対座標2</param>
        /// <param name="mirrored">一方の骨格を左右反転した結果で距離を求めるかどうか</param>
        /// <returns></returns>
        static double getDistance(IDictionary <JointType, CvPoint3D64f> jointWithAbsPosition1, IDictionary <JointType, CvPoint3D64f> jointWithAbsPosition2, bool mirrored)
        {
            IEnumerable <JointType> joints2Alt     = jointWithAbsPosition2.Keys.Select(j => mirrored ? CalcEx.GetMirroredJoint(j) : j);
            List <JointType>        intersect      = jointWithAbsPosition1.Keys.Intersect(joints2Alt).ToList();
            List <double>           distanceSqList = new List <double>();

            foreach (JointType joint in intersect)
            {
                JointType jointAlt = mirrored ? CalcEx.GetMirroredJoint(joint) : joint;
                distanceSqList.Add(CvEx.GetDistanceSq(jointWithAbsPosition1[joint], jointWithAbsPosition2[jointAlt]));
            }
            // 中央値の平方根
            return(Math.Sqrt(CalcEx.GetMedian(distanceSqList)));
        }
예제 #3
0
 /// <summary>
 /// 統計情報を計算し格納する
 /// z = 0.904をデフォルトとする、このとき中央値から65%を網羅できる
 /// </summary>
 /// <param name="z">標準正規分布表のZ</param>
 public void CalcMedianBoneRange(double z = 0.904)
 {
     foreach (Bone bone in this.bones)
     {
         List <double> data = this.boneLengthSqLog[bone];
         int           skip = (int)(data.Count() * 0.3);
         int           take = data.Count() - skip * 2;
         data.Sort();
         // 上下30%を削除
         data = data.Skip(skip).Take(take).ToList();
         double         median    = CalcEx.GetMedian(data);
         double         average   = data.Average();
         double         std       = Math.Abs(Math.Sqrt(data.Select(d => Math.Pow(d - average, 2)).Sum() / (data.Count() - 1)));
         double         minLength = median - std * z;
         double         maxLength = median + std * z;
         BoneStatistics bs        = new BoneStatistics(minLength, maxLength, median, average, std);
         this.boneLengthSqStatistics.Add(bone, bs);
     }
 }
        public static UserSegmentation[] Identification(FrameSequence frameseq, double maxDistance)
        {
            if (frameseq.Segmentations.Any(seg => seg == null))
            {
                throw new InvalidOperationException("ユーザトラッキングデータがセグメンテーションされていません");
            }

            HashSet <Tuple <RecordAndUser, RecordAndUser> > contemporaryList = new HashSet <Tuple <RecordAndUser, RecordAndUser> >();


            for (int recordNo = 0; recordNo < frameseq.recordNum; recordNo++)
            {
                IEnumerable <MotionData> record = frameseq.GetMotionDataSequence(recordNo);
                int frameIndex = 0;
                foreach (MotionData motionData in record)
                {
                    IList <ulong> users = motionData.bodies.ToList().Select(b => b.TrackingId).ToList();
                    foreach (var tuple in users.SelectMany(u => users.Select(v => new Tuple <RecordAndUser, RecordAndUser>(new RecordAndUser(recordNo, u), new RecordAndUser(recordNo, v)))))
                    {
                        contemporaryList.Add(tuple);
                    }
                    frameIndex++;
                }
            }
            DateTime beginTime  = frameseq.startTime;
            DateTime endTime    = frameseq.endTime;
            double   frequency  = frameseq.frameRate;
            TimeSpan increment  = new TimeSpan((long)(10000000 / frequency));
            long     totalCount = (endTime.Ticks - beginTime.Ticks) / increment.Ticks;
            long     totalIndex = 0;
            Dictionary <Tuple <RecordAndUser, RecordAndUser>, List <double> > distanceListMatrix = new Dictionary <Tuple <RecordAndUser, RecordAndUser>, List <double> >();

            foreach (Frame frame in frameseq.Frames)
            {
                // 現在の時刻での各レコードの各ユーザの各骨格の絶対座標を求める
                Dictionary <ulong, Dictionary <JointType, CvPoint3D64f> >[] absPositions = new Dictionary <ulong, Dictionary <JointType, CvPoint3D64f> > [frameseq.recordNum];
                for (int recordNo = 0; recordNo < frameseq.recordNum; recordNo++)
                {
                    Dictionary <ulong, Dictionary <JointType, CvPoint3D64f> > recordUserPositions = new Dictionary <ulong, Dictionary <JointType, CvPoint3D64f> >();
                    foreach (SerializableBody body in frame.GetBodyList(recordNo))
                    {
                        Dictionary <JointType, CvPoint3D64f> userPositions = new Dictionary <JointType, CvPoint3D64f>();
                        if (body.Joints == null)
                        {
                            continue;
                        }
                        foreach (var jointPair in body.Joints)
                        {
                            CvPoint3D64f posInCamera = jointPair.Value.Position.ToCvPoint3D();
                            CvPoint3D64f posInWorld  = CvEx.ConvertPoint3D(posInCamera, frameseq.ToWorldConversions[recordNo]);
                            userPositions[jointPair.Key] = posInWorld;
                        }
                        recordUserPositions[body.TrackingId] = userPositions;
                    }
                    absPositions[recordNo] = recordUserPositions;
                }
                // 現在の時刻で各レコード間のユーザ間の距離を求める
                for (int i = 0; i < frameseq.recordNum; i++)
                {
                    if (absPositions[i] == null)
                    {
                        continue;
                    }
                    for (int j = i + 1; j < frameseq.recordNum; j++)
                    {
                        if (absPositions[j] == null)
                        {
                            continue;
                        }
                        foreach (var userJoint1 in absPositions[i])
                        {
                            RecordAndUser recordUser1 = new RecordAndUser(i, userJoint1.Key);
                            foreach (var userJoint2 in absPositions[j])
                            {
                                RecordAndUser recordUser2                = new RecordAndUser(j, userJoint2.Key);
                                double        distanceNormal             = getDistance(userJoint1.Value, userJoint2.Value, false);
                                double        distanceMirrored           = getDistance(userJoint1.Value, userJoint2.Value, true);
                                double        distance                   = Math.Min(distanceNormal, distanceMirrored);
                                Tuple <RecordAndUser, RecordAndUser> key = new Tuple <RecordAndUser, RecordAndUser>(recordUser1, recordUser2);
                                List <double> distanceList;
                                if (!distanceListMatrix.TryGetValue(key, out distanceList))
                                {
                                    distanceListMatrix[key] = distanceList = new List <double>();
                                }
                                distanceList.Add(distance);
                            }
                        }
                    }
                }
                totalIndex++;
            }
            // 中央値で集計して小さい順に並べる
            Dictionary <Tuple <RecordAndUser, RecordAndUser>, double> distanceMatrix = distanceListMatrix.ToDictionary(p => p.Key, p => CalcEx.GetMedian(p.Value));
            List <Tuple <RecordAndUser, RecordAndUser, double> >      neighborList   = (
                from x in distanceMatrix
                orderby x.Value
                select new Tuple <RecordAndUser, RecordAndUser, double>(x.Key.Item1, x.Key.Item2, x.Value)
                ).ToList();
            IdentificationSet <RecordAndUser> identificationSet = new IdentificationSet <RecordAndUser>();

            // 同一判定をする
            foreach (var neighbor in neighborList)
            {
                if (neighbor.Item3 > maxDistance)
                {
                    identificationSet.Add(neighbor.Item1);
                    identificationSet.Add(neighbor.Item2);
                    continue;
                }
                IList <RecordAndUser> recordUsers1 = identificationSet.GetEquivalentElements(neighbor.Item1);
                IList <RecordAndUser> recordUsers2 = identificationSet.GetEquivalentElements(neighbor.Item2);
                // 同フレーム内にいるか判定
                bool contemporary = (
                    from ru1 in recordUsers1
                    from ru2 in recordUsers2
                    select new Tuple <RecordAndUser, RecordAndUser>(ru1, ru2)).Any(pair => contemporaryList.Contains(pair));
                if (!contemporary)
                {
                    // 同フレーム内にいなければ同一視
                    identificationSet.MakeEquivalent(neighbor.Item1, neighbor.Item2);
                }
            }
            // 番号を圧縮
            identificationSet.CompactIdentificationNumber();
            // 新しいセグメンテーション番号を与える
            UserSegmentation[] ret = Enumerable.Range(0, frameseq.recordNum).Select(i => new UserSegmentation()).ToArray();
            for (int recordNo = 0; recordNo < frameseq.recordNum; recordNo++)
            {
                foreach (var pair in frameseq.Segmentations[recordNo].Conversions)
                {
                    int frameIndex = pair.Key;
                    Dictionary <ulong, int> newConversions = new Dictionary <ulong, int>();
                    foreach (var conv in pair.Value)
                    {
                        int ident = identificationSet.ConvertToIdentificationNumber(new RecordAndUser(recordNo, conv.Key));
                        newConversions[conv.Key] = ident;
                    }
                    ret[recordNo].Conversions[frameIndex] = newConversions;
                }
                ret[recordNo].fixNumUsers();
            }
            return(ret);
        }
예제 #5
0
        private void buttonScalingScore_Click(object sender, RoutedEventArgs e)
        {
            int    cols, rows;
            double horizLength, vertLength;

            if (!parseChessboardParameters(out cols, out rows, out horizLength, out vertLength))
            {
                return;
            }

            // 以下改造
            MotionDataHandler handler;
            string            path;

            if (openMotionData(out handler, out path))
            {
                CvMat displayMat1 = null;
                CvMat displayMat3 = null;
                CvMat displayMat4 = null;
                CvMat gray        = null;

                int length = handler.FrameCount;
                if (length == 0)
                {
                    return;
                }

                CvSize boardSize = new CvSize(cols, rows);
                CvSize imageSize = new CvSize();
                List <Tuple <double, double> > pairs = new List <Tuple <double, double> >();
                CvPoint2D32f[] lastCorners           = null;

                IEnumerable <CvMat> colorImages, depthImages;
                Utility.LoadImages(handler.GetColorImagePaths(), out colorImages);
                Utility.LoadImages(handler.GetDepthImagePaths(), out depthImages);
                var images = colorImages.Zip(depthImages, (first, second) => Tuple.Create(first, second));

                foreach (Tuple <CvMat, CvMat> imagePair in images)
                {
                    CvMat imageMat = imagePair.Item1;
                    CvMat depthMat = imagePair.Item2;

                    if (displayMat4 == null)
                    {
                        displayMat4 = CvEx.InitCvMat(imageMat);
                    }

                    imageSize = new CvSize(imageMat.Cols, imageMat.Rows);
                    CvPoint2D32f[] corners;
                    int            count;
                    CvEx.InitCvMat(ref gray, imageMat, MatrixType.U8C1);
                    imageMat.CvtColor(gray, ColorConversion.RgbToGray);
                    if (gray.FindChessboardCorners(boardSize, out corners, out count, ChessboardFlag.AdaptiveThresh))
                    {
                        CvEx.CloneCvMat(ref displayMat1, imageMat);
                        CvTermCriteria criteria = new CvTermCriteria(50, 0.01);
                        gray.FindCornerSubPix(corners, count, new CvSize(3, 3), new CvSize(-1, -1), criteria);
                        CvPoint3D32f?[] cornerPoints = new CvPoint3D32f?[corners.Length];
                        for (int j = 0; j < corners.Length; j++)
                        {
                            CvPoint2D32f corner = corners[j];
                            double?      value  = CalcEx.BilateralFilterDepthMatSinglePixel(corner, depthMat, 100, 4, 9);
                            if (value.HasValue)
                            {
                                cornerPoints[j] = new CvPoint3D32f(corner.X, corner.Y, value.Value);
                            }
                        }
                        for (int x = 0; x < cols; x++)
                        {
                            for (int y = 0; y < rows; y++)
                            {
                                if (!cornerPoints[x + y * cols].HasValue)
                                {
                                    continue;
                                }
                                CvPoint3D32f point1          = cornerPoints[x + y * cols].Value;
                                CvPoint3D64f undistortPoint1 = this.UndistortionData.GetRealFromScreenPos(point1, imageSize);
                                foreach (var offset in new[] { new { X = 1, Y = 0, D = horizLength }, new { X = 0, Y = 1, D = vertLength } })
                                {
                                    int dx = x + offset.X;
                                    int dy = y + offset.Y;
                                    if (dx >= cols || dy >= rows)
                                    {
                                        continue;
                                    }
                                    if (!cornerPoints[dx + dy * cols].HasValue)
                                    {
                                        continue;
                                    }

                                    CvPoint3D32f point2          = cornerPoints[dx + dy * cols].Value;
                                    CvPoint3D64f undistortPoint2 = this.UndistortionData.GetRealFromScreenPos(point2, imageSize);
                                    double       distance        = Math.Sqrt(CvEx.GetDistanceSq(undistortPoint1, undistortPoint2));
                                    double       scale           = distance / offset.D;
                                    CvColor      color           = CalcEx.HSVtoRGB(Math.Max(0, Math.Min(300, scale * 600 - 450)), scale, 2 - scale);
                                    displayMat4.DrawLine((int)point1.X, (int)point1.Y, (int)point2.X, (int)point2.Y, new CvScalar(color.R, color.G, color.B), 1, LineType.AntiAlias);
                                    pairs.Add(new Tuple <double, double>(distance, offset.D));
                                }
                            }
                        }
                        CvEx.DrawChessboardCornerFrame(displayMat1, boardSize, corners, new CvScalar(64, 128, 64));
                        displayMat1.DrawChessboardCorners(boardSize, corners, true);
                        lastCorners = corners;
                        putImage(displayMat1, PixelFormats.Rgb24);
                    }
                    else
                    {
                        CvEx.CloneCvMat(ref displayMat3, imageMat);
                        putImage(displayMat3, PixelFormats.Rgb24);
                    }
                }

                CvMat displayMat2 = CvEx.InitCvMat(displayMat1);
                displayMat1.Undistort2(displayMat2, this.UndistortionData.CameraStruct.CreateCvMat(), this.UndistortionData.DistortStruct.CreateCvMat(true));
                if (lastCorners != null)
                {
                    drawUndistortedCornerFrame(displayMat2, lastCorners, boardSize);
                }
                displayMat2.PutText(string.Format("Min: {0}", pairs.Min(x => x.Item1 / x.Item2)), new CvPoint(20, 20), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));
                displayMat2.PutText(string.Format("Max: {0}", pairs.Max(x => x.Item1 / x.Item2)), new CvPoint(20, 40), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));
                displayMat2.PutText(string.Format("Avg: {0}", pairs.Average(x => x.Item1 / x.Item2)), new CvPoint(20, 60), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));
                displayMat2.PutText(string.Format("Med: {0}", CalcEx.GetMedian(pairs.Select(x => x.Item1 / x.Item2).ToList())), new CvPoint(20, 80), new CvFont(FontFace.HersheyPlain, 1, 1), new CvScalar(255, 255, 255));
                putImage(displayMat4, PixelFormats.Rgb24);
                displayLabels();
            }
        }