예제 #1
0
        /// <summary>
        /// Finds the contours with minimum perimeters.
        /// </summary>
        /// <param name="image"></param>
        /// <param name="hand">Can be null.</param>
        private void FindContours(Joint hand)
        {
            // Non-zero pixels are treated as 1s. Source image content is modifield.
            CvInvoke.cvFindContours(HandMask.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);

            float z = DefaultZDist;

            if (hand != null)
            {
                z = hand.Position.Z;
            }

            HandCandidates.Clear();
            double perimThresh = DepthUtil.GetDepthImageLength(width, HandWidth, z) * 2;

            for (; contour != null && contour.Ptr.ToInt32() != 0; contour = contour.HNext)
            {
                var perim = CvInvoke.cvContourPerimeter(contour.Ptr);
                if (perim > perimThresh)
                {
                    HandMask.Draw(contour, new Gray(255), -1);
                    HandCandidates.Add(contour.BoundingRectangle);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// </summary>
        /// <returns></returns>
        Rectangle ComputeInitialRect(float z)
        {
            if (InterestPoints.Count > 0)
            {
                int x = 0, y = 0;
                foreach (Point ip in InterestPoints)
                {
                    x += ip.X;
                    y += ip.Y;
                }
                x /= InterestPoints.Count;
                y /= InterestPoints.Count;

                double xx = 0, yy = 0;
                foreach (Point ip in InterestPoints)
                {
                    xx += (ip.X - x) * (ip.X - x);
                    yy += (ip.Y - y) * (ip.Y - y);
                }
                xx /= InterestPoints.Count;
                yy /= InterestPoints.Count;
                xx  = Math.Sqrt(xx);
                yy  = Math.Sqrt(yy);
                var scaledHandWidth = DepthUtil.GetDepthImageLength(width, HandWidth, z);
                var rectWidth       = (int)Math.Max(xx, scaledHandWidth);
                var rectHeight      = (int)Math.Max(yy, scaledHandWidth);
                return(new Rectangle(x - rectWidth / 2, y - rectHeight / 2, rectWidth, rectHeight));
            }
            return(HandRect);
        }
예제 #3
0
        /// <summary>
        /// Computes initial hand searching rectangle in the depth image. If the point is out side of
        /// the frame boundary, an empty rectangle will be returned.
        /// </summary>
        /// <returns></returns>
        Rectangle ComputeInitialRect(DepthImagePoint point, float z)
        {
            var scaledHandWidth = DepthUtil.GetDepthImageLength(width, HandWidth, z) * 2;
            var left            = Math.Max(0, (int)(point.X - scaledHandWidth / 2));

            left = Math.Min(left, width);
            var top = Math.Max(0, (int)(point.Y - scaledHandWidth / 2));

            top = Math.Min(top, height);
            // right and bottom are exclusive.
            var right      = Math.Min(width, (int)(left + scaledHandWidth));
            var bottom     = Math.Min(height, (int)(top + scaledHandWidth));
            var rectWidth  = right - left;
            var rectHeight = bottom - top;

            if (rectWidth <= 0 || rectHeight <= 0)
            {
                return(Rectangle.Empty);
            }
            return(new Rectangle(left, top, right - left, bottom - top));
        }
예제 #4
0
        /// <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);
        }