public FARResult Recognize(GroupOfFingers[][] arrGOF, 
            int[][][] Prev,
            int n,
            int currentIdx, int fingerIndx, int nthGroup)
        {
            FARResult rsl = new FARResult();
            rsl.Name = "NULL";

            if (n < MIN_FRAME)
                return rsl;

            int prevIdx = currentIdx - 1;
            if (prevIdx < 0)
                prevIdx = arrGOF.Length - 1;

            if (Prev[currentIdx][nthGroup][fingerIndx] != -1)
            {
                // 2 frame lien tuc deu cham. mat. ban`
                if (arrGOF[currentIdx][nthGroup].Fingertips[fingerIndx].Status == true
                    && arrGOF[prevIdx][nthGroup].Fingertips[Prev[currentIdx][nthGroup][fingerIndx]].Status == true)
                {
                    rsl.Name = GetName();
                    rsl.Params = new object[2];
                    rsl.Params[0] = arrGOF[currentIdx][nthGroup].Fingertips[fingerIndx].Point2D1.X;
                        //- arrGOF[prevIdx][nthGroup].Fingertips[Prev[currentIdx][nthGroup][fingerIndx]].Point2D1.X;
                    rsl.Params[1] = arrGOF[currentIdx][nthGroup].Fingertips[fingerIndx].Point2D1.Y;
                        //- arrGOF[prevIdx][nthGroup].Fingertips[Prev[currentIdx][nthGroup][fingerIndx]].Point2D1.Y;
                }
            }

            return rsl;
        }
        public FARResult Recognize(GroupOfFingers[][] arrGOF, int[][][] Prev, int n, int currentIdx, int fingerIndx, int nthGroup)
        {
            // kiem tra hanh dong cho ngon tay fingerIndx
            FARResult rsl = new FARResult();
            rsl.Name = "NULL";

            if (n < MIN_FRAME)
                return rsl;

            int prevIdx = currentIdx - 1;
            if (prevIdx < 0)
                prevIdx = arrGOF.Length - 1;

            if (Prev[currentIdx][nthGroup][fingerIndx] != -1)
            {
                if (arrGOF[currentIdx][nthGroup].Fingertips[fingerIndx].Status == true
                    && arrGOF[prevIdx][nthGroup].Fingertips[Prev[currentIdx][nthGroup][fingerIndx]].Status == false)       // neu vua cham mat ban
                {
                    // kiem tra xem o tren khong du lau chua
                    int i = prevIdx;
                    int curr = currentIdx;
                    int currFingerIndx = fingerIndx;
                    int cnt = 0;
                    bool isOK = false;

                    while (i != currentIdx)
                    {
                        if (arrGOF[i][nthGroup].Fingertips[Prev[curr][nthGroup][currFingerIndx]].Status == true)
                        {
                            isOK = true;
                            break;
                        }

                        currFingerIndx = Prev[curr][nthGroup][currFingerIndx];
                        curr = i;
                        // giam i
                        i--;
                        if (i < 0)
                            i = arrGOF.Length - 1;

                        cnt++;
                        if (cnt > n
                            || Prev[curr][nthGroup][currFingerIndx] < 0)
                        {
                            isOK = false;
                            break;
                        }
                    }

                    if (isOK && cnt > MIN_FRAME_UNTOUCH && cnt <= n)
                    {
                        rsl.Name = GetName();
                        rsl.Params = new object[2];
                        rsl.Params[0] = 100;
                        rsl.Params[1] = 200;
                    }
                }
            }

            return rsl;
        }
        /// <summary>
        /// Insert new groups of fingers
        /// </summary>
        /// <param name="GOF">groups of fingers</param>
        public void InsertGOF(GroupOfFingers[] GOF)
        {
            int lastIdx = CurrentIdx;
            int nextIdx = (CurrentIdx + 1) % MAX_GOF;
            _arrGOF[nextIdx] = GOF;
            CurrentIdx = nextIdx;
            if (maxIdx < CurrentIdx)
            {
                maxIdx = CurrentIdx;
            }
            Count++;

            // xac dinh previous match
            // prev[i][k][j] = previous index of jth finger of kth GOF of ith step
            _Prev[CurrentIdx] = new int[GOF.Length][];

            // duyet qua danh sach GOF

            // cach naive
            for (int i = 0; i < GOF.Length; i++)
            {
                _Prev[CurrentIdx][i] = new int[GOF[i].N];
                for (int j = 0; j < GOF[i].N; j++)
                {
                    if (lastIdx  <= maxIdx &&
                        _Prev[lastIdx].Length > i &&
                        j < _Prev[lastIdx][i].Length)
                        _Prev[CurrentIdx][i][j] = j;
                    else
                        _Prev[CurrentIdx][i][j] = -1;
                }
            }

            RecognizeActionForEachFinger();
        }
        void timer_Tick(object sender, EventArgs e)
        {
            Emgu.CV.Image<Bgr, byte> nextFrame1 = capture1.QueryFrame();
            Emgu.CV.Image<Bgr, byte> nextFrame2 = capture2.QueryFrame();
            //Emgu.CV.Image<Bgr, byte> nextFrame1 = new Image<Bgr, Byte>(
                //"D:\\Thesis\\3D Recontruction\\ThucNghiem\\Get_Frames\\Get_Frames\\Set 4\\Cam1_" + iFrameCount.ToString()+".png");
            //Emgu.CV.Image<Bgr, byte> nextFrame2 = new Image<Bgr, Byte>(
                //"D:\\Thesis\\3D Recontruction\\ThucNghiem\\Get_Frames\\Get_Frames\\Set 4\\Cam2_" + iFrameCount.ToString()+".png");

            if (iFrameCount == 395)
            {
                int trap = 0;
            }

            getHandFrom2Cam(nextFrame1.Ptr,
                bin_img1.Ptr,
                nextFrame2.Ptr,
                bin_img2.Ptr,
                nGOF,
                nFinger,
                p2D1x,
                p2D1y,
                p2D2x,
                p2D2y,
                p3Dx,
                p3Dy,
                p3Dz,
                0.1,
                0.1);

            Bitmap bmp1 = new Bitmap( bin_img1.ToBitmap());
            Bitmap bmp2 = new Bitmap( bin_img2.ToBitmap());

            //draw fingertips
            Graphics g1 = Graphics.FromImage(bmp1);
            Graphics g2 = Graphics.FromImage(bmp2);

            int temp = 0;

            POINT3D p3Dtemp;
            if (isPlaneTrained)
            {
                temp = 0;
                for (int i = 0; i < nGOF; i++)
                {
                    for (int j = 0; j < nFinger[i]; j++)
                    {
                        p3Dtemp.X = p3Dx[temp];
                        p3Dtemp.Y = p3Dy[temp];
                        p3Dtemp.Z = p3Dz[temp];

                        height[temp] = currentPlane.DistanceFromPointToPlane(
                            p3Dtemp
                            );
                        status[temp] = currentPlane.isTouchedPlane(height[temp]);
                        temp++;
                    }
                }
            }

            temp = 0;
            for (int i = 0; i < nGOF; i++)
            {
                for (int j = 0; j < nFinger[i]; j++)
                {
                    Pen pen = new Pen(Color.Blue);
                    if (status[temp])
                    {
                        pen = new Pen(Color.Red);
                    }
                    //Pen pen = new Pen(Color.Blue);
                    //if (j == 0)
                    //{
                    //    pen = new Pen(Color.Red);
                    //}
                    //if (j == 1)
                    //{
                    //    pen = new Pen(Color.Green);
                    //}
                    //if (j == 2)
                    //{
                    //    pen = new Pen(Color.Yellow);
                    //}
                    //if (j == 3)
                    //{
                    //    pen = new Pen(Color.Pink);
                    //}

                    DrawCentralCircle(g1,
                        (int)(p2D1x[temp]),
                        (int)(p2D1y[temp]),
                        5, pen);

                    DrawCentralCircle(g2,
                        (int)(p2D2x[temp]),
                        (int)(p2D2y[temp]), 5, pen);

                    temp++;
                }
            }

            // ve ra man hinh
            pbCam1.Image = bmp1;
            pbCam2.Image = bmp2;

            GroupOfFingers[] GOF = new GroupOfFingers[nGOF];
            temp = 0;
            for (int i = 0; i < nGOF; i++)
            {
                Fingertip[] fingers = Fingertip.FromArray(
                    p2D1x,
                    p2D1y,
                    p2D2x,
                    p2D2y,
                    p3Dx,
                    p3Dy,
                    p3Dz,
                    status,
                    height,
                    nFinger[i],
                    temp
                    );
                temp += nFinger[i];
                GOF[i] = new GroupOfFingers(fingers, nFinger[i]);
            }
            mEngine.Process(GOF);

            lvEventLog.Items.Clear();
            lvEventLog.Items.Add(iFrameCount.ToString());
            string[] rsl = aRecog.getState();
            for (int i = 0; i < rsl.Length; i++)
            {
                lvEventLog.Items.Add(rsl[i]);
                //lvEventLog.Items.Add(height[i].ToString());
            }
            iFrameCount++;

            //if (iFrameCount == 45)
            //{
            //    trainPlane();
            //    nGOF = 2;
            //    iFrameCount = 370;
            //}
        }
        public void Process(GroupOfFingers[] GOF)
        {
            _ActionRecoginizer.InsertGOF(GOF);
            ARResult[] rsl = _ActionRecoginizer.Recognize();

            string action = "";
            string evnt = "";
            int iAction = -1;
            int highestPri = 99999999;

            // duyet danh sach action
            evnt = "";
            for (int i = 0; i < rsl.Length; i++)
            {
                action = rsl[i].Name;
                //if (action == "LEFT CLICK ACTION")
                //{
                //    int t = 0;
                //}
                if (action.ToLower().Trim().CompareTo("null") != 0)
                {
                    // find event with highest priority
                    foreach (SEVENT sevnt in _ActionEventRelation[action])
                    {
                        if (highestPri > sevnt.Priority)
                        {
                            highestPri = sevnt.Priority;
                            evnt = sevnt.Name;
                            iAction = i;
                        }
                    }
                }
            }

            if (iAction >= 0)
            {
                // raise event
                _EventGenerator.RaiseEvent(evnt, rsl[iAction].Params);
            }
        }
 public static GroupOfFingers[] FromArray()
 {
     GroupOfFingers[] rsl = new GroupOfFingers[10];
     return rsl;
 }