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]); }
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); }
public void Reset() { _step = 0; _currentHF = _keyHFs[_step]; }