/*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); } }
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); }
/*矩形检测*/ 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; } } } } } } }
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; }
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()); }
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)); }
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); }