public static float DTW(List <Frame> fsA, List <Frame> fsB, out float[,] dtwTable)
        {
            List <HandFeatures> hfsA = new List <HandFeatures>();
            List <HandFeatures> hfsB = new List <HandFeatures>();

            foreach (Frame frame in fsA)
            {
                if (frame.Hands.Count != 1)
                {
                    continue;
                }
                hfsA.Add(HandFeatures.ExtractFeatures(frame.Hands[0]));
            }
            foreach (Frame frame in fsB)
            {
                if (frame.Hands.Count != 1)
                {
                    continue;
                }
                hfsB.Add(HandFeatures.ExtractFeatures(frame.Hands[0]));
            }
            float[,] table = DTW(hfsA, hfsB);
            dtwTable       = table;
            return(table[table.GetLength(0) - 1, table.GetLength(1) - 1]);
        }
Пример #2
0
 public bool Detect(Frame frame, HandFeatures hf)
 {
     // 檢查 time out
     if (IsTimeOut(frame))
     {
         Reset();
     }
     // 檢查 key frame
     if (hf.StateCode == _currentHF.StateCode)
     {
         float sim = HandFeatures.CosSimilarity(hf, _currentHF);
         if (sim < MotionMatching.T2 * T1)
         {
             Debug.WriteLine(String.Format("[{0}] [{1}] 第{2}個 key frame 完成", Class, Name, _step));
             _timeStamp = frame.Timestamp;
             _step++;
             if (_step == _keys.Count)
             {
                 return(true);
             }
             else
             {
                 _currentHF = _keyHFs[_step];
             }
         }
     }
     return(false);
 }
        public float CosSimilarity(HandFeatures hf)
        {
            float sum = 0;

            for (int i = 0; i < LENGTH_0; i++)
            {
                for (int j = 0; j < LENGTH_1; j++)
                {
                    sum += _fs[i][j].AngleTo(hf._fs[i][j]);
                }
            }
            return(sum);
        }
 public void Detect(Frame frame)
 {
     HandFeatures hf = HandFeatures.ExtractFeatures(frame);
     if (hf == null)
         return;
     foreach (string className in _classMDs.Keys.ToArray())
         foreach (MotionDetector md in _classMDs[className])
             if (md.Detect(frame, hf))
             {
                 Reset(md.Class);
                 if (OnMotionDetect != null)
                     OnMotionDetect(this, md.Class, md.Name);
                 break;
             }
 }
        public static HandFeatures ExtractFeatures(Hand hand)
        {
            Vector[][] fs = new Vector[LENGTH_0][];
            Matrix     m  = hand.GetAlignAxisRotationMatrix();

            fs[0] = ExtractFeatures(hand.Thumb, m);
            fs[1] = ExtractFeatures(hand.Index, m);
            fs[2] = ExtractFeatures(hand.Middle, m);
            fs[3] = ExtractFeatures(hand.Ring, m);
            fs[4] = ExtractFeatures(hand.Middle, m);
            HandFeatures hf = new HandFeatures();

            hf._fs       = fs;
            hf.StateCode = ExtractHandStateCode(hand);
            return(hf);
        }
        // 只有兩個都為0才不比對
        public static float CosSimilarity(HandFeatures a, HandFeatures b)
        {
            string code = Convert.ToString(a.StateCode | b.StateCode, 2).PadLeft(LENGTH_0, '0');

            code = new string(code.ToCharArray().Reverse().ToArray());
            float sum   = 0;
            int   count = 0;

            for (int i = 0; i < LENGTH_0; i++)
            {
                if (code[i] == '1')
                {
                    sum += CosSimilarity(a._fs[i], b._fs[i]);
                    count++;
                }
            }
            return(count == 0 ? sum : sum / count / LENGTH_1);
        }
        public static float T2 = (15f).DegreeToRadian(); // 餘弦相似度閥值

        public static List <int> ExtractKeyFrame(List <Frame> frames, out List <HandFeatures> keyFrameHFs)
        {
            keyFrameHFs = new List <HandFeatures>();
            List <int>   keys = new List <int>();
            int          lastKey;
            Hand         currentHand;
            Hand         lastKeyHand;
            HandFeatures currentHF;
            HandFeatures lastKeyHF;

            if (frames.Count < 1)
            {
                return(keys);
            }
            // 第一張一定是key frame
            lastKey     = 0;
            lastKeyHF   = HandFeatures.ExtractFeatures(frames[lastKey]);
            lastKeyHand = frames[lastKey].Hands[0];
            keys.Add(lastKey);
            keyFrameHFs.Add(lastKeyHF);
            //
            for (int i = 1; i < frames.Count; i++)
            {
                currentHand = frames[i].Hands[0];
                currentHF   = HandFeatures.ExtractFeatures(frames[i]);

                //// 檢查手指數目 (state code)
                //if (lastKeyHF.StateCode != currentHF.StateCode)
                //{
                //    // 往後檢查
                //    int count = 0;
                //    for (int j = i; j < i + T1 && j < frames.Count; j++)
                //    {
                //        HandFeatures hf = HandFeatures.ExtractFeatures(frames[j]);
                //        if (currentHF.StateCode != hf.StateCode)
                //            break;
                //        count++;
                //    }
                //    if (count == T1)
                //    {
                //        // 確定是 key frame
                //        lastKey = i;
                //        lastKeyHF = currentHF;
                //        lastKeyHand = currentHand;
                //        keys.Add(lastKey);
                //        keyFrameHFs.Add(lastKeyHF);
                //        continue;
                //    }
                //}

                // 檢查變異量
                // ↓↓↓↓↓↓↓↓ S和T其中一邊有伸直手指就比較變異輛的方法
                float sim = HandFeatures.CosSimilarity(currentHF, lastKeyHF);
                if (sim > T2)
                {
                    Console.WriteLine("差異度 " + sim.RadianToDegree());
                    lastKey     = i;
                    lastKeyHF   = currentHF;
                    lastKeyHand = currentHand;
                    keys.Add(lastKey);
                    keyFrameHFs.Add(lastKeyHF);
                    continue;
                }
                //// 檢查變異量
                //// ↓↓↓↓↓↓↓↓ 伸直手指的變異量方法
                //if (currentHF.StateCode == lastKeyHF.StateCode)
                //{
                //    //float sim = HandFeatures.CosSimilarity(currentHand, lastKeyHand, currentHF.StateCode);
                //    float sim = HandFeatures.CosSimilarity(currentHand, lastKeyHand);
                //    if (sim > T2)
                //    {
                //        Console.WriteLine("差異度 " + sim.RadianToDegree());
                //        lastKey = i;
                //        lastKeyHF = currentHF;
                //        lastKeyHand = currentHand;
                //        keys.Add(lastKey);
                //        keyFrameHFs.Add(lastKeyHF);
                //        continue;
                //    }
                //}
                // ↓↓↓↓↓↓↓↓ 全部手指的變異量方法
                //if (currentFHF.CosSimilarity(lastKFHF) > T2)
                //{
                //    lastKeyFrame = i;
                //    lastKFHF = currentFHF;
                //    keyFrames.Add(lastKeyFrame);
                //    continue;
                //}
            }
            return(keys);
        }
        public static List <int> ExtractKeyFrame_B(List <Frame> frames, out List <HandFeatures> keyFrameHFs)
        {
            keyFrameHFs = new List <HandFeatures>();
            List <int>   keys = new List <int>();
            int          lastKey;
            Hand         currentHand;
            Hand         lastKeyHand;
            HandFeatures currentHF;
            HandFeatures lastKeyHF;

            if (frames.Count < 1)
            {
                return(keys);
            }
            // 第一張一定是key frame
            lastKey     = 0;
            lastKeyHF   = HandFeatures.ExtractFeatures(frames[lastKey]);
            lastKeyHand = frames[lastKey].Hands[0];
            keys.Add(lastKey);
            keyFrameHFs.Add(lastKeyHF);
            //
            for (int i = 1; i < frames.Count; i++)
            {
                currentHand = frames[i].Hands[0];
                currentHF   = HandFeatures.ExtractFeatures(frames[i]);

                // 檢查手指數目 (state code)
                if (lastKeyHF.StateCode != currentHF.StateCode)
                {
                    // 往後檢查
                    int count = 0;
                    for (int j = i; j < i + T1 && j < frames.Count; j++)
                    {
                        HandFeatures hf = HandFeatures.ExtractFeatures(frames[j]);
                        if (currentHF.StateCode != hf.StateCode)
                        {
                            break;
                        }
                        count++;
                    }
                    if (count == T1)
                    {
                        // 確定是 key frame
                        lastKey     = i;
                        lastKeyHF   = currentHF;
                        lastKeyHand = currentHand;
                        keys.Add(lastKey);
                        keyFrameHFs.Add(lastKeyHF);
                        continue;
                    }
                }

                // 檢查變異量
                // ↓↓↓↓↓↓↓↓ 伸直手指的變異量方法
                if (currentHF.StateCode == lastKeyHF.StateCode)
                {
                    float sim = HandFeatures.CosSimilarity(currentHand, lastKeyHand, currentHF.StateCode);
                    if (sim > T2)
                    {
                        Console.WriteLine("差異度 " + sim.RadianToDegree());
                        lastKey     = i;
                        lastKeyHF   = currentHF;
                        lastKeyHand = currentHand;
                        keys.Add(lastKey);
                        keyFrameHFs.Add(lastKeyHF);
                        continue;
                    }
                }
            }
            return(keys);
        }
Пример #9
0
 public void Reset()
 {
     _step      = 0;
     _currentHF = _keyHFs[_step];
 }