Exemple #1
0
 /*ROI检测*/
 void Region_Detection(int id)
 {
     using (MemStorage storage = new MemStorage()) //allocate storage for contour(轮廓) approximation
         for (
             Contour <Point> contours = slide_gray_img[id].FindContours(
                 Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                 Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST,
                 storage);
             contours != null;
             contours = contours.HNext)
         {
             Contour <Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); //逼近多边形曲线
             if (currentContour.Area < size_of_roi)                                                    //only consider contours with area greater than 250
             {
                 tempbox = currentContour.GetMinAreaRect();
                 //保证roi在中心位置
                 if (tempbox.size.Height >= 10 && tempbox.size.Width >= 10 &&
                     tempbox.center.X > slide[id].Width * 0.17 && tempbox.center.X < slide[id].Width * 0.83)
                 {
                     roi[id] = tempbox.MinAreaRect();
                     Rectangle         absRoi         = ConvertToAbsolute(roi[id], slide[id]);
                     Image <Bgr, Byte> RectangleImage = frame;
                     RectangleImage.Draw(absRoi, new Bgr(Color.Blue), 2);
                     imageBox3.Image = RectangleImage;
                     if (id == maxNum)
                     {
                         scanDone = true;
                     }
                     break;
                 }
             }
         }
 }
        private void DetectContours()
        {
            using (MemStorage stor = new MemStorage())
            {
                //Find contours with no holes try CV_RETR_EXTERNAL to find holes
                Contour <System.Drawing.Point> contours = binImage.FindContours(
                    Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_LINK_RUNS,
                    Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_CCOMP,
                    stor);

                int objectCount = 0;
                for (; contours != null; contours = contours.HNext)
                {
                    MCvBox2D box = contours.GetMinAreaRect();
                    if (contours.Area > 20)
                    {
                        float centerX = box.center.X;
                        float centerY = box.center.Y;
                        imageToDisplay.Draw(box.MinAreaRect(), new Gray(200), 2);
                        imageToDisplay.Draw(new CircleF(box.center, 2), new Gray(0), 2);
                        int    x     = (int)(centerX + 0.5) * 2;
                        int    y     = (int)(centerY + 0.5) * 2;
                        double depth = ExperimentalDepth(x, y);
                        double rx    = GetX(x, depth);
                        double ry    = GetY(y, depth);
                        string text  = String.Format("{0:F2}, {1:F2}, {2:F2}", rx, ry, depth);

                        //if (isWriting) dataContainer += depth.ToString() + "\n";
                        if (isWriting)
                        {
                            dataContainer += text + "\n";
                        }

                        DrawText(text, (int)(centerX - box.size.Width / 2), (int)(centerY - box.size.Height), coordFont);
                        objectCount++;
                    }
                }
                DrawText("Objects detected: " + objectCount.ToString(), 20, 20, textFont);
            }
        }
Exemple #3
0
 Rectangle FindBestBoundingBox(Rectangle initialRect)
 {
     if (!initialRect.IsEmpty)
     {
         CvInvoke.cvCamShift(SmoothedDepth.Ptr, initialRect, new MCvTermCriteria(CamShiftIter),
                             out connectedComp, out shiftedRect);
         Rectangle rect;
         if (useShiftedRect)
         {
             rect = shiftedRect.MinAreaRect();
         }
         else
         {
             rect = connectedComp.rect;
         }
         if (rect.Width > 0 && rect.Height > 0)
         {
             return(rect);
         }
     }
     return(Rectangle.Empty);
 }
Exemple #4
0
        /*矩形检测*/
        void Rectangle_Detection()
        {
            using (MemStorage storage = new MemStorage()) //allocate storage for contour(轮廓) approximation
                for (
                    Contour <Point> contours = canny_out.FindContours(
                        Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                        Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST,
                        storage);
                    contours != null;
                    contours = contours.HNext)
                {
                    Contour <Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage); //逼近多边形曲线
                    if (currentContour.Area > size_of_slide && isSlide == false)                              //only consider contours with area greater than 250
                    {
                        if (currentContour.Total == 4)                                                        //The contour has 4 vertices(顶点).
                        {
                            #region determine if all the angles in the contour are within [80, 100] degree
                            bool            isRectangle = false;
                            Point[]         pts         = currentContour.ToArray();
                            LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                            for (int i = 0; i < edges.Length; i++)
                            {
                                double angle = Math.Abs(
                                    edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
                                if (angle >= 60 || angle <= 120)
                                {
                                    isRectangle = true;
                                    break;
                                }
                            }
                            #endregion
                            if (isRectangle)
                            {
                                slideSize.Text = Convert.ToString(size_of_slide);
                                tempbox        = currentContour.GetMinAreaRect();
                                float tempboxp = tempbox.size.Width / tempbox.size.Height;
                                //从长宽比例判断轮廓是否为玻片
                                if (tempboxp > 2.7 && tempboxp < 3.3 ||
                                    tempboxp > 1 / 3.3 && tempboxp < 1 / 2.7)
                                {
                                    Image <Bgr, Byte> RectangleImage = frame;
                                    RectangleImage.Draw(tempbox, new Bgr(Color.DarkOrange), 2);
                                    imageBox3.Image          = RectangleImage;
                                    slide[slideNum]          = tempbox.MinAreaRect();//外接面积最小矩形
                                    slide_gray_img[slideNum] = canny_out.GetSubRect(slide[slideNum]);
                                    if (slideNum < maxNum)
                                    {
                                        slideNum++;
                                    }
                                    else
                                    {
                                        isSlide  = true;
                                        slideNum = 0;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
        }
Exemple #5
0
        private MCvBox2D SplitHand(MCvBox2D rect, HandEnum handEnum, PointF Elbow2HandVector)
        {

            if (handEnum == HandEnum.Both || handEnum == HandEnum.Intersect)
            {
                return new MCvBox2D(rect.center, rect.MinAreaRect().Size, 0);
            }
            PointF[] pl = rect.GetVertices();
            Point[] splittedHands = new Point[4];
            //find angle of long edge
            PointF startP = pl[1];
            PointF shortP = pl[0];
            PointF longP = pl[2];
            PointF ap1 = new PointF();
            PointF ap2 = new PointF();

          
            if (pl[0].DistanceTo(startP) > pl[2].DistanceTo(startP))
            {
                shortP = pl[2];
                longP = pl[0];
            }

            SizeF size = new SizeF();
            size.Width = shortP.DistanceTo(startP);
            size.Height = longP.DistanceTo(startP);
            PointF shortEdge = new PointF(shortP.X - startP.X, shortP.Y - startP.Y);
            float t_angle = (float)(Math.Atan(shortEdge.Tan())*180/Math.PI);
  
            MCvBox2D box = new MCvBox2D();
            box.size = size;
            box.center = pl.GetCenter();
       
            float longDis = longP.DistanceTo(startP);
            float shortDis = shortP.DistanceTo(startP);
            // x and long edge slope 
            float longslope = Math.Abs(longP.X - startP.X) / longDis;
            float min = float.MaxValue;

            float factor = Math.Max(Math.Abs(longP.Y - startP.Y) / longDis, Math.Abs(longP.X - startP.X) / longDis);
            int TransformEnd = Convert.ToInt32(factor * end);
            int TransformBegin = Convert.ToInt32(factor * begin);
            //Console.WriteLine(TransformBegin);
            //Console.WriteLine(TransformEnd);
            // > 45
            if (longslope < 0.707)//vert
            {
                // point up
                if (Elbow2HandVector.Y <= 0)
                {
                    box.angle = t_angle;
                    startP = pl.OrderBy((x => x.Y)).First();
                }
                else
                {
                    box.angle = t_angle + 180;
                    startP = pl.OrderByDescending((x => x.Y)).First();
                }


                if (longDis < minLength)
                {
                    return box;
                }

                pl = pl.OrderBy(x => x.DistanceTo(startP)).ToArray();
                shortP = pl[1];
                longP = pl[2];

                for (int y = TransformBegin; y < Convert.ToInt32(Math.Abs(longP.Y - startP.Y)) && Math.Abs(y) < TransformEnd; y++)
                {
                    PointF p1 = InterPolateP(startP, longP, y / Math.Abs(longP.Y - startP.Y));
                    PointF p2 = new PointF(p1.X + shortP.X - startP.X, p1.Y + shortP.Y - startP.Y);
                    float dis = GetHandWidthBetween(p1, p2);
                    if (dis < min)
                    {
                        min = dis;
                        ap1 = p1;
                        ap2 = p2;
                    }
                }
            }
            else // horizontal 
            {
                // point top for right hand
                if (t_angle <0)
                {
                    if (handEnum == HandEnum.Right)
                    {
                        box.angle = t_angle;
                    }
                    else
                    {
                        box.angle = t_angle + 180;
                    }
                }
                // point bottom for right hand
                else
                {
                    if (handEnum == HandEnum.Right)
                    {
                        box.angle = t_angle - 180;
                    }
                    else
                    {
                        box.angle = t_angle;
                    }
                }
                if (handEnum == HandEnum.Right)
                {
                    startP = pl.OrderBy((x => x.X)).ToArray()[0];

                }
                else if (handEnum == HandEnum.Left)
                {
                    startP = pl.OrderByDescending((x => x.X)).ToArray()[0];
                }


                if (longDis < minLength)
                {
                    return box;
                }
                pl = pl.OrderBy(x => x.DistanceTo(startP)).ToArray();
                shortP = pl[1];
                longP = pl[2];
                for (int X = TransformBegin; X < Convert.ToInt32(Math.Abs(longP.X - startP.X)) && Math.Abs(X) < TransformEnd; X++)
                {
                    PointF p1 = InterPolateP(startP, longP, X / Math.Abs(longP.X - startP.X));
                    PointF p2 = new PointF(p1.X + shortP.X - startP.X, p1.Y + shortP.Y - startP.Y);
                    float dis = GetHandWidthBetween(p1, p2);
                    if (dis < min)
                    {
                        min = dis;
                        ap1 = p1;
                        ap2 = p2;
                    }
                }
            }
            if (ap1 == null || ap1 == PointF.Empty)
            {
                return box;
            }
            splittedHands[0] = startP.ToPoint();
            splittedHands[1] = ap1.ToPoint();
            splittedHands[2] = ap2.ToPoint();
            splittedHands[3] = shortP.ToPoint();


            //Point lowP = p.OrderByDescending(x => x.Y).First();
            //Point highP = p.OrderByDescending(x => x.DistanceTo(lowP)).First();
            //Point widthP = p.OrderBy(x => x.TanWith(lowP)).First();
            box.center = splittedHands.GetCenter();
            box.size.Height = startP.DistanceTo(ap1);
            
            return box;
        }
Exemple #6
0
        private void FindContourAndConvexHull(Image<Gray, byte> skin, Image<Bgr, byte> imageFrame)
        {
            using (MemStorage cacheStorage = new MemStorage())
            {
                //getting the countours by simplest algorithm and list in retourn (tree isn't necessary)
                Contour<Point> contours = skin.FindContours(
                    Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                    Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST,
                    cacheStorage
                );

                //this variable will contain the biggest countour (if any avaiable)
                Contour<Point> largestContour = null;

                //searching for biggest countour
                Double CurrArea = 0, MaxArea = 0;
                while (contours != null)
                {
                    CurrArea = contours.Area;
                    if (CurrArea > MaxArea)
                    {
                        MaxArea = CurrArea;
                        largestContour = contours;
                    }
                    contours = contours.HNext;
                }

                if (largestContour != null)
                {
                    //drawing oryginal countour on image:
                    imageFrame.Draw(largestContour, new Bgr(Color.DarkViolet), 2);

                    //smoothing a bit the countour to make less amout of defects + draw:
                    Contour<Point> currentContour = largestContour.ApproxPoly(largestContour.Perimeter * 0.0025, cacheStorage);
                    imageFrame.Draw(currentContour, new Bgr(Color.LimeGreen), 2);
                    largestContour = currentContour;

                    //computing and drawing convex hull (smallest polygon that covers whole hand):
                    hull = largestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    imageFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2);

                    //computing smallest box (with angle), that covers the hull, and drawing without angle:
                    box = largestContour.GetMinAreaRect();
                    handRect = box.MinAreaRect();
                    imageFrame.Draw(handRect, new Bgr(200, 0, 0), 1);

                    //drawing the center of the box iwth hull:
                    imageFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2);

                    //drawing ellipse ("E") that containts most of the foun pixels:
                    if (largestContour.Count() >= 5)
                    {
                        ellip.MCvBox2D = CvInvoke.cvFitEllipse2(largestContour.Ptr);
                        imageFrame.Draw(new Ellipse(ellip.MCvBox2D), new Bgr(Color.LavenderBlush), 3);
                    }

                    //computing and drawing minimal enclosing circle, that contains whole contour:
                    PointF center;
                    float radius;
                    CvInvoke.cvMinEnclosingCircle(largestContour.Ptr, out  center, out  radius);
                    imageFrame.Draw(new CircleF(center, radius), new Bgr(Color.Gold), 2);

                    //drawing center of ellipse "E":
                    imageFrame.Draw(new CircleF(new PointF(ellip.MCvBox2D.center.X, ellip.MCvBox2D.center.Y), 3), new Bgr(100, 25, 55), 2);
                    imageFrame.Draw(ellip, new Bgr(Color.DeepPink), 2);

                    //computing and drawing ellipse ("F") that shows the direction of hand:
                    CvInvoke.cvEllipse(imageFrame,
                        new Point((int)ellip.MCvBox2D.center.X, (int)ellip.MCvBox2D.center.Y),
                        new Size((int)ellip.MCvBox2D.size.Width, (int)ellip.MCvBox2D.size.Height),
                        ellip.MCvBox2D.angle,
                        0,
                        360,
                        new MCvScalar(120, 233, 88),
                        1,
                        Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED,
                        0);

                    //drawing ellipse, that's small, but also shows the direction of hand:
                    imageFrame.Draw(
                        new Ellipse(
                            new PointF(box.center.X, box.center.Y),
                            new SizeF(box.size.Height, box.size.Width),
                            box.angle),
                        new Bgr(0, 0, 0), 2);

                    //algorithm that fiters convex hull. It saves only those points, that have distance
                    //between next point bigger than 1/10th of the box size. Small ones are removed.
                    filteredHull = new Seq<Point>(cacheStorage);
                    for (int i = 0; i < hull.Total; i++)
                    {
                        if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10)
                        {
                            filteredHull.Push(hull[i]);
                        }
                    }

                    //finding convex hull defects:
                    defects = largestContour.GetConvexityDefacts(cacheStorage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    defectsArr = defects.ToArray();
                }
            }
        }
        /// <summary>
        /// If no bounding box is found, returns the last bounding box.
        /// </summary>
        /// <returns></returns>
        List <Rectangle> FindBestBoundingBox(short[] depthFrame, Skeleton skeleton)
        {
            CvInvoke.cvConvert(SaliencyProb.Ptr, TempMask.Ptr);
            // Non-zero pixels are treated as 1s. Source image content is modifield.
            CvInvoke.cvFindContours(TempMask.Ptr, storage, ref contourPtr, StructSize.MCvContour,
                                    RETR_TYPE.CV_RETR_EXTERNAL, CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, new Point(0, 0));
            var contour = new Seq <Point>(contourPtr, null);

            SortedList <float, Seq <Point> > bestContours = new SortedList <float, Seq <Point> >();
            List <Rectangle> bestBoundingBoxes            = new List <Rectangle>();

            float z    = DefaultZDist;
            var   hand = SkeletonUtil.GetJoint(skeleton, JointType.HandRight);

            if (hand != null)
            {
                z = hand.Position.Z;
            }
            double perimThresh = DepthUtil.GetDepthImageLength(width, HandWidth, z) * 2;

            FaceModel = SkeletonUtil.GetFaceModel(skeleton, mapper);

            for (; contour != null && contour.Ptr.ToInt32() != 0; contour = contour.HNext)
            {
                var perim = CvInvoke.cvContourPerimeter(contour.Ptr);
                if (perim > perimThresh)
                {
                    var rect   = contour.BoundingRectangle;
                    var score  = ContourScore(rect);
                    var center = rect.Center();
                    int x      = (int)center.X;
                    int y      = (int)center.Y;
                    var depth  = DepthUtil.RawToDepth(depthFrame[y * width + x]);
                    if (!FaceModel.IsPartOfFace(x, y, depth) &&
                        (bestContours.Count < NumTrackedHands || score > bestContours.ElementAt(0).Key))
                    {
                        bestContours.Add(score, contour);
                        if (bestContours.Count > NumTrackedHands)
                        {
                            bestContours.RemoveAt(0);
                        }
                    }
                }
            }

            if (bestContours.Count > 0)
            {
                foreach (var c in bestContours.Values)
                {
                    var rect = c.BoundingRectangle;
                    CvInvoke.cvCamShift(TrackedDepthFrame.Ptr, rect, new MCvTermCriteria(CamShiftIter),
                                        out connectedComp, out shiftedBox);
                    var bestBoundingBox = shiftedBox.MinAreaRect();
                    bestBoundingBoxes.Add(bestBoundingBox);
                    //FloodFill(TrackedDepthFrame, bestBoundingBox);
                    //if (bestBoundingBox.Width > 0) {
                    //  TempMask.ROI = bestBoundingBox;
                    //  CvInvoke.cvFindContours(TempMask.Ptr, storage, ref contourPtr, StructSize.MCvContour,
                    //      RETR_TYPE.CV_RETR_EXTERNAL, CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                    //      new Point(0, 0));
                    //  contour = new Seq<Point>(contourPtr, null);

                    //  Seq<Point> largestContour = null;
                    //  var maxPerim = perimThresh;
                    //  for (; contour != null && contour.Ptr.ToInt32() != 0; contour = contour.HNext) {
                    //    var perim = CvInvoke.cvContourPerimeter(contour.Ptr);
                    //    if (perim > maxPerim) {
                    //      maxPerim = perim;
                    //      largestContour = contour;
                    //    }
                    //  }

                    //  CvInvoke.cvZero(TempMask.Ptr);
                    //  if (largestContour != null)
                    //    TempMask.Draw(largestContour, new Gray(255), -1);
                    //  FilterImage(TrackedDepthFrame, TempMask);
                    //  TempMask.ROI = Rectangle.Empty;
                    //}
                }
            }

            return(bestBoundingBoxes);
        }
        public static Rectangle SquareFitting(PointF[] points)
        {
            MCvBox2D box = PointCollection.MinAreaRect(points);

            return(box.MinAreaRect());
        }
Exemple #9
0
        private SkeletonPoint FindHand(short[] depthData, Rectangle rect)
        {
            CvInvoke.cvZero(HandImage.Ptr);
            var handImageData  = HandImage.Data;
            var handMaskData   = HandMask.Data;
            var playerMaskData = playerMask.Data;

            var maxDepth = 0;
            var minDepth = Int32.MaxValue;

            for (int y = rect.Top; y < rect.Top + rect.Height && y < height; y++)
            {
                for (int x = rect.Left; x < rect.Left + rect.Width && x < width; x++)
                {
                    if (y > 0 && x > 0 && handMaskData[y, x, 0] > 0 &&
                        playerMaskData[y, x, 0] > 0)
                    {
                        var depth = DepthUtil.RawToDepth(depthData[y * width + x]);
                        maxDepth = Math.Max(maxDepth, depth);
                        if (depth < minDepth)
                        {
                            minDepth = depth;
                        }
                    }
                }
            }

            var scale = (float)255 / (maxDepth - minDepth);

            for (int y = rect.Top; y < rect.Top + rect.Height && y < height; y++)
            {
                for (int x = rect.Left; x < rect.Left + rect.Width && x < width; x++)
                {
                    if (y > 0 && x > 0 && playerMaskData[y, x, 0] > 0 &&
                        handMaskData[y, x, 0] > 0)
                    {
                        var depth = DepthUtil.RawToDepth(depthData[y * width + x]);
                        handImageData[y, x, 0] = (byte)((maxDepth - depth) * scale);
                    }
                }
            }

            var connectedComp = new MCvConnectedComp();
            var shiftedBox    = new MCvBox2D();

            CvInvoke.cvCamShift(HandImage.Ptr, rect, new MCvTermCriteria(0.0), out connectedComp,
                                out shiftedBox);

            PrevHand = new windows.Point(HandBox.center.X, HandBox.center.Y);
            HandBox  = shiftedBox;
            var newRect  = shiftedBox.MinAreaRect();
            var aveDepth = 0.0;
            var count    = 0;

            for (int y = newRect.Top; y < newRect.Top + newRect.Height && y < height; y++)
            {
                for (int x = newRect.Left; x < newRect.Left + newRect.Width && x < width; x++)
                {
                    if (x > 0 && y > 0 && playerMaskData[y, x, 0] > 0 &&
                        handMaskData[y, x, 0] > 0)
                    {
                        var depth = DepthUtil.RawToDepth(depthData[y * width + x]);
                        aveDepth += depth;
                        count++;
                    }
                }
            }

            aveDepth /= count;
            var shiftedCenterX = Math.Max(0, shiftedBox.center.X);

            shiftedCenterX = Math.Min(shiftedCenterX, width);
            var shiftedCenterY = Math.Max(0, shiftedBox.center.Y);

            shiftedCenterY = Math.Min(shiftedCenterY, height);
            return(mapper.MapDepthPointToSkeletonPoint((int)shiftedCenterX,
                                                       (int)shiftedCenterY, (int)aveDepth));
        }
Exemple #10
0
        private void ExtractContourAndHull(Image <Gray, byte> skin)
        {
            using (MemStorage storage = new MemStorage())
            {
                Contour <Point> contours       = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage);
                Contour <Point> biggestContour = null;

                Double Result1 = 0;
                Double Result2 = 0;
                while (contours != null)
                {
                    Result1 = contours.Area;
                    if (Result1 > Result2)
                    {
                        Result2        = Result1;
                        biggestContour = contours;
                    }
                    contours = contours.HNext;
                }

                if (biggestContour != null)
                {
                    // currentFrame.Draw(biggestContour, new Bgr(Color.Black), 2);
                    Contour <Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage);
                    //currentFrame.Draw(currentContour, new Bgr(Color.Red), 2);
                    biggestContour = currentContour;


                    hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    box  = biggestContour.GetMinAreaRect();
                    PointF[] points = box.GetVertices();
                    handRect = box.MinAreaRect();
                    //int xx = (handRect.Width) / 2;
                    //int yy = (handRect.Height) / 2;
                    currentFrame.Draw(handRect, new Bgr(200, 0, 0), 1);

                    // currentFrame.Draw(new CircleF(new PointF(xx, yy), 3), new Bgr(200, 125, 75), 2);
                    Point[] ps = new Point[points.Length];
                    for (int i = 0; i < points.Length; i++)
                    {
                        ps[i] = new Point((int)points[i].X, (int)points[i].Y);
                    }

                    currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2);
                    currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2);
                    // currentFrame.Draw(new CircleF(new PointF(handRect.center.X, handRect.center.Y), 3), new Bgr(200, 125, 75), 2);


                    //ellip.MCvBox2D= CvInvoke.cvFitEllipse2(biggestContour.Ptr);
                    //currentFrame.Draw(new Ellipse(ellip.MCvBox2D), new Bgr(Color.LavenderBlush), 3);

                    // PointF center;
                    // float radius;
                    //CvInvoke.cvMinEnclosingCircle(biggestContour.Ptr, out  center, out  radius);
                    //currentFrame.Draw(new CircleF(center, radius), new Bgr(Color.Gold), 2);

                    //currentFrame.Draw(new CircleF(new PointF(ellip.MCvBox2D.center.X, ellip.MCvBox2D.center.Y), 3), new Bgr(100, 25, 55), 2);
                    //currentFrame.Draw(ellip, new Bgr(Color.DeepPink), 2);

                    //CvInvoke.cvEllipse(currentFrame, new Point((int)ellip.MCvBox2D.center.X, (int)ellip.MCvBox2D.center.Y), new System.Drawing.Size((int)ellip.MCvBox2D.size.Width, (int)ellip.MCvBox2D.size.Height), ellip.MCvBox2D.angle, 0, 360, new MCvScalar(120, 233, 88), 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);
                    //currentFrame.Draw(new Ellipse(new PointF(box.center.X, box.center.Y), new SizeF(box.size.Height, box.size.Width), box.angle), new Bgr(0, 0, 0), 2);


                    filteredHull = new Seq <Point>(storage);
                    for (int i = 0; i < hull.Total; i++)
                    {
                        if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10)
                        {
                            filteredHull.Push(hull[i]);
                        }
                    }

                    defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

                    defectArray = defects.ToArray();
                }
                MCvMoments moment = new MCvMoments();                           // a new MCvMoments object

                try
                {
                    moment = biggestContour.GetMoments();       // Moments of biggestContour
                }
                catch (NullReferenceException)
                {
                }
                int fingerNum = 0;
                CvInvoke.cvMoments(biggestContour, ref moment, 0);

                double m_00 = CvInvoke.cvGetSpatialMoment(ref moment, 0, 0);
                double m_10 = CvInvoke.cvGetSpatialMoment(ref moment, 1, 0);
                double m_01 = CvInvoke.cvGetSpatialMoment(ref moment, 0, 1);

                int current_X = Convert.ToInt32(m_10 / m_00) / 10;  // X location of centre of contour
                int current_Y = Convert.ToInt32(m_01 / m_00) / 10;  // Y location of center of contour


                if (fingerNum == 1 || fingerNum == 0 || blue == 6)
                {
                    Cursor.Position = new Point(current_X * 10, current_Y * 10);
                }
                //Leave the cursor where it was and Do mouse click, if finger count >= 3
            }
        }
        //-----------------------------------------------------------------------------------------
        private void Draw_Gesture_Features()
        {
            #region drawing PalmBoundingCircle
            try
            {
                // find bounding rec for PalmPointsCollection
                PalmBoundingCircle = PointCollection.MinEnclosingCircle(PalmPointsCollection);
            }
            catch
            {
                return;
            }

            // we treat center of the circle as the center of the palm
            imgMain.Draw(PalmBoundingCircle, new Bgr(Color.Violet), 2);
            imgMain.Draw(new CircleF(new PointF(PalmBoundingCircle.Center.X, PalmBoundingCircle.Center.Y), 2), new Bgr(Color.Violet), 5);
            #endregion

            #region drawing FingerBoundingBox
            // find bounding rec for FingerPointsCollection
            MCvBox2D box = PointCollection.MinAreaRect(FingerPointsCollection);
            FingerBoundingBox = box.MinAreaRect();
            // we treat center of the circle as the center of the palm
            imgMain.Draw(FingerBoundingBox, new Bgr(Color.Cyan), 2);
            imgMain.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 2), new Bgr(Color.Cyan), 5);
            #endregion

            #region drawing all finger points
            for (int i = 0; i < FingerPointsCollection.Count(); i++)
            {
                imgMain.Draw(new CircleF(FingerPointsCollection[i], 2), new Bgr(Color.Yellow), 5);
            }
            #endregion

            #region drawing all palm points
            for (int i = 0; i < PalmPointsCollection.Count(); i++)
            {
                imgMain.Draw(new CircleF(PalmPointsCollection[i], 2), new Bgr(Color.Red), 5);
            }
            #endregion

            //#region drawing lines from fingers to center
            //for (int i = 0; i < FingerPointsCollection.Count(); i++)
            //{
            //    imgMain.Draw(new LineSegment2DF(FingerPointsCollection[i], PalmBoundingCircle.Center), new Bgr(Color.Yellow), 1);
            //}
            //#endregion

            //#region drawing lines from palm to center
            //for (int i = 0; i < PalmPointsCollection.Count(); i++)
            //{
            //    imgMain.Draw(new LineSegment2DF(PalmPointsCollection[i], PalmBoundingCircle.Center), new Bgr(Color.Red), 1);
            //}
            //#endregion

            //#region Filtered drawing lines from fingers to center
            //for (int i = 0; i < FingerPointsCollection.Count(); i++)
            //{
            //    if (FingerPointsCollection[i].Y < PalmBoundingCircle.Center.Y)
            //    {
            //        imgMain.Draw(new LineSegment2DF(FingerPointsCollection[i], PalmBoundingCircle.Center), new Bgr(Color.Yellow), 1);
            //    }
            //}
            //#endregion

            //#region Filtered drawing lines from palm to center
            //for (int i = 0; i < PalmPointsCollection.Count(); i++)
            //{
            //    if (PalmPointsCollection[i].Y < PalmBoundingCircle.Center.Y)
            //    {
            //        imgMain.Draw(new LineSegment2DF(PalmPointsCollection[i], PalmBoundingCircle.Center), new Bgr(Color.Red), 1);
            //    }
            //}
            //#endregion
        }
        private void ExtractContourAndHull(Image<Gray, byte> skin)
        {
            using (MemStorage storage = new MemStorage())
            {

                Contour<Point> contours = skin.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage);
                Contour<Point> biggestContour = null;

                Double Result1 = 0;
                Double Result2 = 0;
                while (contours != null)
                {
                    Result1 = contours.Area;
                    if (Result1 > Result2)
                    {
                        Result2 = Result1;
                        biggestContour = contours;
                    }
                    contours = contours.HNext;
                }

                if (biggestContour != null)
                {
                   // currentFrame.Draw(biggestContour, new Bgr(Color.Black), 2);
                    Contour<Point> currentContour = biggestContour.ApproxPoly(biggestContour.Perimeter * 0.0025, storage);
                    //currentFrame.Draw(currentContour, new Bgr(Color.Red), 2);
                    biggestContour = currentContour;

                    hull = biggestContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                    box = biggestContour.GetMinAreaRect();
                    PointF[] points = box.GetVertices();
                    handRect = box.MinAreaRect();
                    //int xx = (handRect.Width) / 2;
                    //int yy = (handRect.Height) / 2;
                    currentFrame.Draw(handRect, new Bgr(200, 0, 0), 1);

                    // currentFrame.Draw(new CircleF(new PointF(xx, yy), 3), new Bgr(200, 125, 75), 2);
                    Point[] ps = new Point[points.Length];
                    for (int i = 0; i < points.Length; i++)
                        ps[i] = new Point((int)points[i].X, (int)points[i].Y);

                    currentFrame.DrawPolyline(hull.ToArray(), true, new Bgr(200, 125, 75), 2);
                    currentFrame.Draw(new CircleF(new PointF(box.center.X, box.center.Y), 3), new Bgr(200, 125, 75), 2);
                   // currentFrame.Draw(new CircleF(new PointF(handRect.center.X, handRect.center.Y), 3), new Bgr(200, 125, 75), 2);

                    //ellip.MCvBox2D= CvInvoke.cvFitEllipse2(biggestContour.Ptr);
                    //currentFrame.Draw(new Ellipse(ellip.MCvBox2D), new Bgr(Color.LavenderBlush), 3);

                   // PointF center;
                    // float radius;
                    //CvInvoke.cvMinEnclosingCircle(biggestContour.Ptr, out  center, out  radius);
                    //currentFrame.Draw(new CircleF(center, radius), new Bgr(Color.Gold), 2);

                    //currentFrame.Draw(new CircleF(new PointF(ellip.MCvBox2D.center.X, ellip.MCvBox2D.center.Y), 3), new Bgr(100, 25, 55), 2);
                    //currentFrame.Draw(ellip, new Bgr(Color.DeepPink), 2);

                    //CvInvoke.cvEllipse(currentFrame, new Point((int)ellip.MCvBox2D.center.X, (int)ellip.MCvBox2D.center.Y), new System.Drawing.Size((int)ellip.MCvBox2D.size.Width, (int)ellip.MCvBox2D.size.Height), ellip.MCvBox2D.angle, 0, 360, new MCvScalar(120, 233, 88), 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0);
                    //currentFrame.Draw(new Ellipse(new PointF(box.center.X, box.center.Y), new SizeF(box.size.Height, box.size.Width), box.angle), new Bgr(0, 0, 0), 2);

                    filteredHull = new Seq<Point>(storage);
                    for (int i = 0; i < hull.Total; i++)
                    {
                        if (Math.Sqrt(Math.Pow(hull[i].X - hull[i + 1].X, 2) + Math.Pow(hull[i].Y - hull[i + 1].Y, 2)) > box.size.Width / 10)
                        {
                            filteredHull.Push(hull[i]);
                        }
                    }

                    defects = biggestContour.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

                    defectArray = defects.ToArray();
                }
                            MCvMoments moment = new MCvMoments();               // a new MCvMoments object

            try
            {
                moment = biggestContour.GetMoments();           // Moments of biggestContour
            }
            catch (NullReferenceException)
            {

            }
            int fingerNum = 0;
            CvInvoke.cvMoments(biggestContour, ref moment, 0);

            double m_00 = CvInvoke.cvGetSpatialMoment(ref moment, 0, 0);
            double m_10 = CvInvoke.cvGetSpatialMoment(ref moment, 1, 0);
            double m_01 = CvInvoke.cvGetSpatialMoment(ref moment, 0, 1);

            int current_X = Convert.ToInt32(m_10 / m_00) / 10;      // X location of centre of contour
            int current_Y = Convert.ToInt32(m_01 / m_00) / 10;      // Y location of center of contour

             if (fingerNum == 1 || fingerNum == 0 || blue == 6)
             {
                 Cursor.Position = new Point(current_X * 10, current_Y * 10);
             }
             //Leave the cursor where it was and Do mouse click, if finger count >= 3

                }
        }
        private static bool isDashed(ContourNode inner)
        {
            Image<Bgr, Byte> im = inner.Image.Clone();
            Rectangle oldroi = inner.Image.ROI;

            #region calc ROI
            double scale = 0.33;
            Point center = new Point(oldroi.X + oldroi.Width / 2, oldroi.Y + oldroi.Height / 2);
            Size size = new Size((int)(oldroi.Size.Width * scale), (int)(oldroi.Size.Height * scale));
            MCvBox2D box = new MCvBox2D(center, size, 0);
            Rectangle newroi = box.MinAreaRect();
            #endregion
            im.ROI = newroi;

            Image<Bgr, float> laplace = im.Laplace(1);

            double[] mins, maxs;
            Point[] minlocs, maxlocs;
            laplace.MinMax(out mins, out maxs, out minlocs, out maxlocs);

            return (maxs[0] > 15);
        }