/// <summary>
 /// Get the item in the specific index
 /// </summary>
 /// <param name="index">The index</param>
 /// <returns>The item in the specific index</returns>
 public Triangle2DF this[int index]
 {
     get
     {
         Triangle2DF result = new Triangle2DF();
         VectorOfTriangle2DFGetItem(_ptr, index, ref result);
         return(result);
     }
 }
示例#2
0
 private Mat DisplayTriangleOnInfrared(Mat infraredMat, Triangle2DF tri)
 {
     using (Mat convertMat = new Mat(infraredMat.Size, DepthType.Cv8U, 1)) {
         infraredMat.ConvertTo(convertMat, DepthType.Cv8U, 1 / 256d);
         Mat displayMat = new Mat(infraredMat.Size, DepthType.Cv8U, 3);
         CvInvoke.CvtColor(convertMat, displayMat, ColorConversion.Gray2Bgr);
         CvInvoke.Polylines(displayMat, Array.ConvertAll(tri.GetVertices(), System.Drawing.Point.Round), true, new Bgr(0, 0, 255).MCvScalar, 2);
         return(displayMat);
     }
 }
 /// <summary>
 /// Convert the standard vector to an array of Triangle2DF
 /// </summary>
 /// <returns>An array of Triangle2DF</returns>
 public Triangle2DF[] ToArray()
 {
     Triangle2DF[] res = new Triangle2DF[Size];
     if (res.Length > 0)
     {
         GCHandle handle = GCHandle.Alloc(res, GCHandleType.Pinned);
         VectorOfTriangle2DFCopyData(_ptr, handle.AddrOfPinnedObject());
         handle.Free();
     }
     return(res);
 }
示例#4
0
        /// <summary>
        /// Retruns the triangles subdivision of the current planar subdivision.
        /// </summary>
        /// <param name="includeVirtualPoints">Indicates if virtual points should be included or not</param>
        /// <remarks>The triangles might contains virtual points that do not belongs to the inserted points, if you do not want those points, set <paramref name="includeVirtualPoints"> to false</paramref></remarks>
        /// <returns>The triangles subdivision in the current plannar subdivision</returns>
        public Triangle2DF[] GetDelaunayTriangles(bool includeVirtualPoints)
        {
            int size = ((MCvSet)Marshal.PtrToStructure(MCvSubdiv2D.edges, typeof(MCvSet))).total * 2;

            Triangle2DF[] triangles = new Triangle2DF[size];
            GCHandle      handle    = GCHandle.Alloc(triangles, GCHandleType.Pinned);

            CvInvoke.PlanarSubdivisionGetTriangles(_ptr, handle.AddrOfPinnedObject(), ref size, includeVirtualPoints ? 1 : 0);
            handle.Free();
            Array.Resize(ref triangles, size);
            return(triangles);
        }
        public static int GetDiameter(Triangle2DF triangle2DF)
        {
            var listX = new List <float>();

            listX.Add(triangle2DF.V0.X);
            listX.Add(triangle2DF.V1.X);
            listX.Add(triangle2DF.V2.X);
            var min = listX.Min();
            var max = listX.Max();

            return((int)(max - min + 15));
        }
        public void ThreadedFunction()
        {
            while (true)
            {
                while (!FApply)
                {
                    Thread.Sleep(5);
                }

                int SliceCount;
                Spread <PointF[]>      points;
                Spread <Triangle2DF[]> triangles;

                lock (FLockPoints)
                {
                    SliceCount = FPoints.SliceCount;
                    points     = new Spread <PointF[]>(SliceCount);

                    for (int i = 0; i < SliceCount; i++)
                    {
                        points[i] = new PointF[FPoints[i].Length];
                        Array.Copy(FPoints[i], points[i], FPoints[i].Length);
                    }
                }

                triangles = new Spread <Triangle2DF[]>(SliceCount);

                for (int i = 0; i < SliceCount; i++)
                {
                    PlanarSubdivision subdivision = new PlanarSubdivision(points[i] as PointF[]);
                    triangles[i] = subdivision.GetDelaunayTriangles(false);
                }

                lock (FTriangles)
                {
                    FTriangles.SliceCount = SliceCount;

                    Triangle2DF t;
                    for (int i = 0; i < SliceCount; i++)
                    {
                        FTriangles[i] = new Triangle2DF[triangles[i].Length];
                        for (int j = 0; j < triangles[i].Length; j++)
                        {
                            t = triangles[i][j];
                            FTriangles[i][j] = new Triangle2DF(t.V0, t.V1, t.V2);
                        }
                    }
                }

                FResults = true;
            }
        }
示例#7
0
      /// <summary>
      /// Create planar subdivision for random points
      /// </summary>
      /// <param name="maxValue">The points contains values between [0, maxValue)</param>
      /// <param name="pointCount">The total number of points to create</param>
      public static void CreateSubdivision(float maxValue, int pointCount, out Triangle2DF[] delaunayTriangles, out VoronoiFacet[] voronoiFacets)
      {
         #region create random points in the range of [0, maxValue]
         PointF[] pts = new PointF[pointCount];
         Random r = new Random((int)(DateTime.Now.Ticks & 0x0000ffff));
         for (int i = 0; i < pts.Length; i++)
            pts[i] = new PointF((float)r.NextDouble() * maxValue, (float)r.NextDouble() * maxValue);
         #endregion

         using (Subdiv2D subdivision = new Subdiv2D(pts))
         {
            //Obtain the delaunay's triangulation from the set of points;
            delaunayTriangles = subdivision.GetDelaunayTriangles();

            //Obtain the voronoi facets from the set of points
            voronoiFacets = subdivision.GetVoronoiFacets();
         }
      }
示例#8
0
        private void CalculateNormal(Mat depthMat, Triangle2DF tri)
        {
            if (depthMat == null || (tri.Centeroid.X == 0 && tri.Centeroid.Y == 0))
            {
                return;
            }

            var vertices    = Array.ConvertAll(tri.GetVertices(), System.Drawing.Point.Round);
            var point2dList = vertices;// Kolos.haromszog.belsopontok(vertices);

            #region Kolos normalvektor
            //var point3dList = new List<Kolos.pont3d>();

            //foreach (var point2d in point2dList) {
            //    var zcoord = GetMatElementU16(depthMat, point2d.X, point2d.Y);
            //    if(zcoord != 0)
            //        point3dList.Add(CalculateWorldPosition(point2d.X, point2d.Y, depthMat.Cols, zcoord));
            //}

            //var normal = Kolos.normalvektor.kiszamitas(point3dList);
            //Console.WriteLine($"Normálvektor X:{normal[0].ToString("F4")} Y:{normal[1].ToString("F4")}, Z: {normal[2].ToString("F4")}");
            #endregion


            MCvPoint3D32f[] vertices3d = new MCvPoint3D32f[3];
            for (int i = 0; i < 3; i++)
            {
                var point2d = point2dList[i];
                var zcoord  = GetMatElementU16(depthMat, point2d.X, point2d.Y);
                if (zcoord == 0)
                {
                    return;
                }
                var point3d = CalculateWorldPosition(point2d.X, point2d.Y, depthMat.Cols, zcoord);
                vertices3d[i] = new MCvPoint3D32f((float)point3d.x, (float)point3d.y, (float)point3d.z);
            }

            var tri3d  = new Triangle3DF(vertices3d[0], vertices3d[1], vertices3d[2]);
            var normal = tri3d.Normal;
            Console.WriteLine($"Normal: X:{normal.X} Y:{normal.Y} Z:{normal.Z}");
        }
示例#9
0
        /*
         * public void TestArrayChangeDimension()
         * {
         * float[] vec = new float[10];
         * for (int i = 0; i < vec.Length; i++)
         *    vec[i] = (float)i;
         *
         * float[,] vec2 = new float[vec.Length, 1];
         *
         * GCHandle hdl1 = GCHandle.Alloc(vec, GCHandleType.Pinned);
         * GCHandle hdl2 = GCHandle.Alloc(vec2, GCHandleType.Pinned);
         * Emgu.Util.Toolbox.memcpy(hdl1.AddrOfPinnedObject(), hdl2.AddrOfPinnedObject(), vec.Length * Marshal.SizeOf(typeof(float)));
         * hdl1.Free();
         * hdl2.Free();
         * //Array.Copy(vec, vec2, vec.Length);
         *
         * for (int i = 0; i < vec.Length; i++)
         * {
         *    Assert.AreEqual(vec[i], vec2[i, 0]);
         * }
         * }*/


        private void TestMap()
        {
            PointF center = new PointF(-110032, -110032);
            float  width = 10000, height = 12000;


            Map <Gray, Byte> map = new Map <Gray, byte>(new RectangleF(center.X - width / 2, center.Y - height / 2, width, height), new PointF(100, 100));

            PointF[] pts = new PointF[]
            {
                new PointF((float)center.X + 3120, (float)center.Y + 2310),
                new PointF((float)center.X - 220, (float)center.Y - 4120)
            };
            map.DrawPolyline(pts, false, new Gray(255.0), 1);
            Triangle2DF tri = new Triangle2DF(
                new PointF((float)center.X - 1000.0f, (float)center.Y + 200.0f),
                new PointF((float)center.X - 3000.0f, (float)center.Y + 200.0f),
                new PointF((float)center.X - 700f, (float)center.Y + 800.0f));

            map.Draw(tri, new Gray(80), 0);
            map.Draw(tri, new Gray(255), 1);
            ImageViewer.Show(map);
        }
示例#10
0
        /// <summary>
        /// Default constructor
        /// </summary>
    /*    public PolyFromTris(Triangle2DF[] t)
        {
            //tris = new Triangle2DF();
            innerPoints = new List<PointF>();
            this.tris = t;
        }*/

        /// <summary>
        /// Sets triangles structure
        /// </summary>
        public void setTris(Triangle2DF[] t)
        {
            this.tris = t;
        }
示例#11
0
 public void TestTriangle()
 {
     PointF p1 = new PointF(0, 0);
      PointF p2 = new PointF(1, 0);
      PointF p3 = new PointF(0, 1);
      Triangle2DF tri = new Triangle2DF(p1, p2, p3);
      double epsilon = 1e-12;
      //Trace.WriteLine(tri.Area);
      //Trace.WriteLine(((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X))*0.5);
      Assert.IsTrue(Math.Abs(tri.Area - 0.5) < epsilon);
 }
示例#12
0
        private void btnProcess_Click(object sender, EventArgs e)
        {
            if (original == null)
            {
                lblError.Text      = "Please browse the image";
                lblError.Visible   = true;
                btnProcess.Enabled = btnSaveImage.Enabled = false;
                return;
            }

            if (cbCircle.Checked == false && cbLine.Checked == false & cbRectangle.Checked == false && cbTriangle.Checked == false)
            {
                lblError.Text    = "Please choose the shape detection type";
                lblError.Visible = true;

                original            = temp = new Image <Bgr, byte>(openFileDialog.FileName);
                pbChosenImage.Image = original.ToBitmap();

                return;
            }

            lblError.Visible = false;

            temp = new Image <Bgr, byte>(openFileDialog.FileName);

            if (cbLine.Checked == true)
            {
                LineSegment2D[] lines = edge.HoughLinesBinary(2, Math.PI / 180, 50, 50, 10)[0];

                foreach (LineSegment2D line in lines)
                {
                    temp.Draw(line, new Bgr(Color.Yellow), 10);
                }

                pbChosenImage.Image = temp.Bitmap;
            }

            if (cbCircle.Checked == true)
            {
                CircleF[] circles = edge.HoughCircles(new Gray(150), new Gray(150), 2, 50, 10, 100)[0];

                foreach (CircleF circle in circles)
                {
                    temp.Draw(circle, new Bgr(Color.Red), 10);
                }

                pbChosenImage.Image = temp.Bitmap;
            }

            if (cbTriangle.Checked == true)
            {
                for (Contour <Point> contour = edge.FindContours();
                     contour != null; contour = contour.HNext
                     )
                {
                    if (contour.Area > 200)
                    {
                        MemStorage mem = new MemStorage();

                        Contour <Point> contourDalem = contour.ApproxPoly(contour.Perimeter * 0.16, mem);

                        if (contourDalem.Total == 3)
                        {
                            Point[]     points   = contourDalem.ToArray();
                            Triangle2DF triangle = new Triangle2DF(points[0], points[1], points[2]);

                            temp.Draw(triangle, new Bgr(Color.Green), 10);
                        }
                    }
                }

                pbChosenImage.Image = temp.Bitmap;
            }

            if (cbRectangle.Checked == true)
            {
                for (Contour <Point> contour = edge.FindContours();
                     contour != null; contour = contour.HNext
                     )
                {
                    if (contour.Area > 200)
                    {
                        MemStorage mem = new MemStorage();

                        Contour <Point> contourDalem = contour.ApproxPoly(contour.Perimeter * 0.16, mem);

                        if (contourDalem.Total == 4)
                        {
                            Point[] points = contourDalem.ToArray();

                            bool rectangle = true;

                            LineSegment2D[] lines = PointCollection.PolyLine(points, true);

                            for (int i = 0; i < lines.Length; i++)
                            {
                                double angle = Math.Abs(lines[(i + 1) % lines.Length].GetExteriorAngleDegree(lines[i]));

                                if (angle < 80 || angle > 100)
                                {
                                    rectangle = false;
                                    break;
                                }
                            }

                            if (rectangle == true)
                            {
                                temp.Draw(contourDalem.GetMinAreaRect(), new Bgr(Color.Gold), 10);
                            }
                        }
                    }
                }

                pbChosenImage.Image = temp.Bitmap;
            }
        }
        /// <summary>
        /// Draws trangulated poly to colored Bgr image in green
        /// </summary>
        /// <param name="img">Image we're drawing to</param>
        /// <param name="trisList">Triangles list</param>
        /// <param name="imgBox">Box we're inserting image to</param>
        public void drawTris(Image<Bgr, Byte> img, Triangle2DF[] trisList, ref Emgu.CV.UI.ImageBox imgBox)
        {
            //Draw the Delaunay triangulation
            foreach (Triangle2DF tri in trisList)
            {
                img.Draw(tri, new Bgr(Color.DarkOliveGreen), 1);
            }

            imgBox.Image = img;
        }
示例#14
0
      /*
      public static void TestCodeBook()
      {
         int learningFrames = 40;
         using (BlobDetector detector = new BlobDetector(CvEnum.BlobDetectorType.Simple))
         using (BlobSeq blobs = new BlobSeq())
         using (Capture capture = new Capture("tree.avi"))
         using (BGCodeBookModel<Ycc> bgmodel = new BGCodeBookModel<Ycc>())
         {
            
            #region Set color thresholds values
            //bgmodel.MCvBGCodeBookModel.ModMin0 = bgmodel.MCvBGCodeBookModel.ModMin1 = bgmodel.MCvBGCodeBookModel.ModMin2 = 3;
            //bgmodel.MCvBGCodeBookModel.ModMax0 = bgmodel.MCvBGCodeBookModel.ModMax1 = bgmodel.MCvBGCodeBookModel.ModMax2 = 10;
            //bgmodel.MCvBGCodeBookModel.CbBounds0 = bgmodel.MCvBGCodeBookModel.CbBounds1 = bgmodel.MCvBGCodeBookModel.CbBounds2 = 10;
            #endregion
            

            ImageViewer viewer = new ImageViewer();
            int count = 0;
            EventHandler processFrame = delegate(Object sender, EventArgs e)
            {
               Image<Bgr, Byte> img = capture.RetrieveBgrFrame();
               if (img == null)
               {
                  return;
               }

               viewer.Text = String.Format("Processing {0}th image. {1}", count++, learningFrames > 0 ? "(Learning)" : String.Empty);

               using (Image<Ycc, Byte> ycc = img.Convert<Ycc, Byte>()) //using YCC color space for BGCodeBook
               {
                  if (learningFrames == 0) //training is completed
                     bgmodel.ClearStale(bgmodel.MCvBGCodeBookModel.T / 2, Rectangle.Empty, null);

                  if (learningFrames > 0)
                     bgmodel.Apply(ycc); 
                  else if (learningFrames <= 0)
                  {
                     bgmodel.Diff(ycc, Rectangle.Empty);
                     Image<Gray, Byte> m = bgmodel.ForegroundMask.Clone();
                     blobs.Clear();
                     if (detector.DetectNewBlob(m, blobs, null))
                     {
                        foreach (MCvBlob b in blobs)
                           m.Draw((Rectangle) b, new Gray(100), 2);
                     }
                     viewer.Image = m;
                  }
                  learningFrames--;
                  System.Threading.Thread.Sleep(100);
               }

               img.Dispose();
            };
            capture.ImageGrabbed += processFrame;
            capture.Start();

            viewer.ShowDialog();
         }
      }

      public void TestArrayChangeDimension()
      {
         float[] vec = new float[10];
         for (int i = 0; i < vec.Length; i++)
            vec[i] = (float)i;

         float[,] vec2 = new float[vec.Length, 1];

         GCHandle hdl1 = GCHandle.Alloc(vec, GCHandleType.Pinned);
         GCHandle hdl2 = GCHandle.Alloc(vec2, GCHandleType.Pinned);
         Emgu.Util.Toolbox.memcpy(hdl1.AddrOfPinnedObject(), hdl2.AddrOfPinnedObject(), vec.Length * Marshal.SizeOf(typeof(float)));
         hdl1.Free();
         hdl2.Free();
         //Array.Copy(vec, vec2, vec.Length);

         for (int i = 0; i < vec.Length; i++)
         {
            Assert.AreEqual(vec[i], vec2[i, 0]);
         }
      }*/

      
      private void TestMap()
      {
         PointF center = new PointF(-110032, -110032);
         float width = 10000, height = 12000;


         Map<Gray, Byte> map = new Map<Gray, byte>(new RectangleF(center.X - width/2, center.Y - height/2, width, height), new PointF(100, 100));
         PointF[] pts = new PointF[]
            {
                new PointF( (float)center.X + 3120,(float) center.Y + 2310),
                new PointF((float)center.X -220, (float) center.Y-4120)
            };
         map.DrawPolyline(pts, false, new Gray(255.0), 1);
         Triangle2DF tri = new Triangle2DF(
             new PointF((float)center.X - 1000.0f, (float)center.Y + 200.0f),
             new PointF((float)center.X - 3000.0f, (float)center.Y + 200.0f),
             new PointF((float)center.X - 700f, (float)center.Y + 800.0f));
         map.Draw(tri, new Gray(80), 0);
         map.Draw(tri, new Gray(255), 1);
         ImageViewer.Show(map);
      }
示例#15
0
        private void altProcess(Bitmap bm, int level)
        {
            var img = new Image <Bgr, byte>(bm);

            if (level == 1)
            {
                var resImage = new Image <Bgr, byte>(img.Bitmap);
                CvInvoke.BilateralFilter(resImage, img, 30, 80, 80);
                CvInvoke.MedianBlur(img, img, 5);
                resImage = img;
            }
            else if (level == 2)
            {
                CvInvoke.MedianBlur(img, img, 5);
                var resImage = new Image <Bgr, byte>(img.Bitmap);
                CvInvoke.BilateralFilter(resImage, img, 25, 75, 75);
                CvInvoke.Blur(img, img, new Size(5, 5), new Point(0, 0));
            }

            var grayimage = new Image <Gray, byte>(bm);

            CvInvoke.CvtColor(img, grayimage, ColorConversion.Bgr2Gray);

            BlackBG(grayimage);

            Console.WriteLine("Filtering done");

            var cannyThreshold = GetKMeansThreshold(grayimage);

            label2.Text = cannyThreshold.ToString();

            Thresholding(grayimage, cannyThreshold);

            Console.WriteLine("Canny threshold using KMEANS found " + cannyThreshold);

            //Convert the image to grayscale and filter out the noise

            var cannyEdges = new UMat();

            Console.WriteLine("Canny threshold using KMEANS found " + cannyThreshold);

            var uimage = new UMat();

            CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);

            CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThreshold);

            BlobCounter blobCounter = new BlobCounter( );

            if (level == 1)
            {
                blobCounter.FilterBlobs = true;
                blobCounter.MinHeight   = 25;
                blobCounter.MinWidth    = 25;
                blobCounter.ProcessImage(cannyEdges.Bitmap);
            }
            else
            {
                blobCounter.ProcessImage(grayimage.ToBitmap());
            }
            //blobCounter.ProcessImage(grayimage.ToBitmap());

            Blob[] blobs = blobCounter.GetObjectsInformation( );

            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();


            var      triangleList = new List <Triangle2DF>();
            var      boxList      = new List <RotatedRect>();
            var      circleList   = new List <CircleF>();
            Bitmap   newBM        = new Bitmap(img.Bitmap);
            Graphics g            = Graphics.FromImage(newBM);
            Pen      redPen       = new Pen(Color.Red, 2);


            Pen yellowPen = new Pen(Color.Yellow, 2);
            Pen greenPen  = new Pen(Color.Green, 2);
            Pen bluePen   = new Pen(Color.Blue, 2);

            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List <IntPoint> edgePoints =
                    blobCounter.GetBlobsEdgePoints(blobs[i]);

                AForge.Point center;
                float        radius;

                if (shapeChecker.IsCircle(edgePoints, out center, out radius))
                {
                    //g.DrawEllipse(bluePen,
                    //    (float)(center.X - radius), (float)(center.Y - radius),
                    //    (float)(radius * 2), (float)(radius * 2));
                    circleList.Add(new CircleF(new PointF(center.X, center.Y), radius));
                }
                else
                {
                    List <IntPoint> corners;
                    if (edgePoints.Count > 1)
                    {
                        if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                        {
                            System.Console.WriteLine(corners.Count);
                            if (shapeChecker.CheckPolygonSubType(corners) ==
                                PolygonSubType.Square || shapeChecker.CheckPolygonSubType(corners) ==
                                PolygonSubType.Rectangle)
                            {
                                IntPoint minXY, maxXY;

                                PointsCloud.GetBoundingRectangle(corners, out minXY, out maxXY);
                                AForge.Point c = PointsCloud.GetCenterOfGravity(corners);
                                //g.DrawPolygon(greenPen, ToPointsArray(corners));
                                boxList.Add(new RotatedRect(new PointF(c.X, c.Y), new SizeF(maxXY.X - minXY.X, maxXY.Y - minXY.Y), 0));
                            }
                        }
                        else
                        {
                            corners = PointsCloud.FindQuadrilateralCorners(edgePoints);
                            if (corners.Count == 3)
                            {
                                Triangle2DF tri = new Triangle2DF(new PointF(corners[0].X, corners[0].Y), new PointF(corners[1].X, corners[1].Y), new PointF(corners[2].X, corners[2].Y));
                                triangleList.Add(tri);
                                //g.DrawPolygon(yellowPen, ToPointsArray(corners));
                            }
                            //g.DrawPolygon(redPen, ToPointsArray(corners));
                        }
                    }
                }
            }
            Console.WriteLine("boxes " + boxList.Count);
            Console.WriteLine("triangles " + triangleList.Count);
            Console.WriteLine("circles " + circleList.Count);

            redPen.Dispose();
            greenPen.Dispose();
            bluePen.Dispose();
            yellowPen.Dispose();
            //g.Dispose();
            resPicBox.Image = newBM;
            CircleF[] circles = circleList.ToArray();
            var       cList   = circles.ToList();

            FilterSame(boxList, triangleList, cList, img.Width * img.Height);
            circles = cList.ToArray();
            var points = new List <PointF>();

            var Image = img.CopyBlank();

            foreach (var triangle in triangleList)
            {
                Image.Draw(triangle, new Bgr(Color.Red), 3);
                points.Add(triangle.Centeroid);
            }

            foreach (var box in boxList)
            {
                Image.Draw(box, new Bgr(Color.Blue), 3);
                points.Add(box.Center);
            }

            foreach (var circle in circles)
            {
                Image.Draw(circle, new Bgr(Color.DarkCyan), 3);
                points.Add(circle.Center);
            }

            var listPoints = SortPoints(points, img);

            for (var i = 0; i < listPoints.Length; i++)
            {
                Console.WriteLine(listPoints[i].X.ToString() + " " + listPoints[i].Y.ToString());
            }

            System.Console.WriteLine("Points sorted, num of objects " + listPoints.Length.ToString());
            resPicBox.Image = (Image + img).ToBitmap();
            if (listPoints.Length > 3)
            {
                var bezSegList = InterpolatePointWithBeizerCurves(listPoints.ToList <PointF>());
                var gr         = Graphics.FromImage(resPicBox.Image);
                var p          = new Pen(Color.Red);

                foreach (BeizerCurveSegment seg in bezSegList)
                {
                    var bezierList = GetBez(new PointF[]
                                            { seg.StartPoint, seg.FirstControlPoint, seg.SecondControlPoint, seg.EndPoint });
                    for (var i = 0; i < bezierList.Length - 1; i++)
                    {
                        gr.DrawLine(p, bezierList[i], bezierList[i + 1]);
                    }
                }
            }
            else
            {
                var gr = Graphics.FromImage(resPicBox.Image);
                var p  = new Pen(Color.Red);

                for (var i = 0; i < listPoints.Length - 1; i++)
                {
                    gr.DrawLine(p, listPoints[i], listPoints[i + 1]);
                }
            }

            //var bezierList = GetBezierCurve1(listPoints);
        }
示例#16
0
        public void DetectFingers(Image<Gray, Byte> image)
        {
            /*
            Point3D ptHandProjective = this.depth.ConvertRealWorldToProjective(ptHand);
            Size offset = new Size((int)ptHandProjective.X, (int)ptHandProjective.Y);
            //get the hand
            Image<Gray, Byte> image = detector.DetectHand(this.depth, ptHand);
            */

            //image = image.PyrDown().PyrUp();
            //image._SmoothGaussian(5);
            //image._ThresholdBinary(new Gray(149), new Gray(255));

            Graphics g = Graphics.FromImage(this.bitmap);

            MemStorage storage1 = new MemStorage();

            Contour<Point> contours = new Contour<Point>(storage1);

            // Find the biggest contour
            for (Contour<Point> tempContours = image.FindContours(); tempContours != null; tempContours = tempContours.HNext)
            {
                if (tempContours.Area > contours.Area)
                    contours = tempContours;
            }

            //Console.WriteLine(contours.Area);
            if (contours.Area != 0)
            {
                List<KeyValuePair<Point, bool>> significantPts = new List<KeyValuePair<Point, bool>>();
                Rectangle contourRectangle = contours.BoundingRectangle;
                g.DrawRectangle(new Pen(Brushes.Green), contourRectangle);

                //Seq<Point> contoursHull = contours.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

                // Convert the set of contour points to a polygon for graphical representation

                Seq<Point> poly = contours.ApproxPoly(20);
                Point[] polygon = poly.ToArray();

                PointF[] contourF = Array.ConvertAll(contours.ToArray(), new Converter<Point, PointF>(PointToPointF));
                //CircleF palmCircle = PointCollection.MinEnclosingCircle(contourF);
                //CircleF palmCircle = PointCollection.EllipseLeastSquareFitting(contourF);
                //MCvBox2D box = PointCollection.MinAreaRect(contourF);
                //g.DrawRectangle(new Pen(Brushes.Aquamarine),(Rectangle) box.MinAreaRect());
                //drawCircle(g, new Pen(Brushes.Green), PointFToPoint(palmCircle.Center), (int) Math.Round(palmCircle.Radius));

                // Get the convex hull based on the contour polygon
                Seq<Point> convexHull = poly.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);

                /*
                 * Handle opening and closing of the fist each frame.
                 * Fisting gesture controls the left mouse button.
                 * Based on the ratio of area between the convex and the hull.
                 * (See calculation above) Threshold currently set to 0.8
                 *
                 * NEED TO HAND COORDINATES
                 */
                double hullArea = convexHull.Area;
                double contourArea = contours.Area;
                double currentHullRatio = contourArea / hullArea;

                // newest ratio is in front of array
                hullRatios[2] = hullRatios[1];
                hullRatios[1] = hullRatios[0];
                hullRatios[0] = currentHullRatio;

                this.fixedHullRatio = hullRatios[2];

                if (smoothHullRatios && this.frame > 3)
                {
                    this.hullRatios = smoothHullRatioArray(this.hullRatios);
                }

                bool fistClosed = true;
                stopTracking = true;

                if (shouldHandClose())
                {
                    stopTracking = true;
                    fistClosed = false;
                }
                if (shouldControlMouse)
                {
                    //clickMouse(fistClosed);
                }

                // Get the convexity defects from the contour
                stopwatch.Restart();
                Seq<Emgu.CV.Structure.MCvConvexityDefect> contourDefects = contours.GetConvexityDefacts(storage1, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
                stopwatch.Stop();
                //Console.WriteLine(Math.Round(1000.0 * (double)stopwatch.ElapsedTicks / Stopwatch.Frequency, 4) + ", GetConvexityDefacts()");

                // Draw the polygon that was converted from the contour
                /*
                for (int i = 0; i < polygon.Length; i++)
                {
                    if (i == polygon.Length - 1)
                        g.DrawLine((new Pen(Brushes.Blue))), polygon[i], polygon[0]);
                    else
                        g.DrawLine((new Pen(Brushes.Blue))), polygon[i], polygon[i + 1]);
                }
                */
                // Draw more polygon stuff ??
                foreach (Point p in poly)
                {
                    significantPts.Add(new KeyValuePair<Point, bool>(p, false));
                    //g.DrawLine((new Pen(Brushes.Blue))), p.X, p.Y, p.X + 10, p.Y + 10);
                }

                int fingertips = 0;

                Point[] defectPoints = new Point[contourDefects.Count()];
                Point[] fingerPoints = new Point[contourDefects.Count()];
                Point[] endPoints = new Point[contourDefects.Count()];
                int count = 0;
                int fingerCount = 0;

                ///--- DEFECTS
                foreach (MCvConvexityDefect defect in contourDefects)
                {

                    // Construct a triangle from the defect
                    Triangle2DF defectTriangle = new Triangle2DF(defect.DepthPoint, defect.StartPoint, defect.EndPoint);

                    // Check that the area of the defect triangle is between 1% and 33% of the contour area
                    if (defectTriangle.Area > contours.Area / 100 && defectTriangle.Area < contours.Area / 3)
                    {
                        ///---
                        endPoints[count] = defect.EndPoint;
                        defectPoints[count] = defect.DepthPoint;
                        count++;
                        // Get the angle of the defect
                        double defectAngle = getVertexAngle(defect.DepthPoint, defect.StartPoint, defect.EndPoint);
                        if (defectAngle < 100 && !defect.EndPoint.Equals(Point.Empty))
                            fingerPoints[fingerCount++] = defect.EndPoint;
                        ///---

                        //g.DrawPolygon(new Pen(Brushes.Pink), defectTriangle.GetVertices());
                        significantPts.Add(new KeyValuePair<Point, bool>(defect.DepthPoint, true));

                        g.DrawLine((new Pen(Brushes.Green)), defect.StartPoint, defect.EndPoint);
                        g.DrawLine((new Pen(Brushes.Red)), defect.DepthPoint, defect.StartPoint);
                        g.DrawLine((new Pen(Brushes.Blue)), defect.DepthPoint, defect.EndPoint);
                        // Draw the depth point of the defects (hull point)
                        g.DrawRectangle(new Pen(Brushes.Green),
                                        new Rectangle(Point.Subtract(defect.DepthPoint, new Size(5, 5)),
                                                      new Size(10, 10)));
                        // Check if angle is obtuse or acute
                        g.DrawString(defectAngle.ToString(), new Font(FontFamily.GenericSerif,5), Brushes.Blue, defect.DepthPoint.X + 5, defect.DepthPoint.Y + 5);
                        /*
                        if (defectAngle < 70)
                            drawCircle(g,new Pen(Brushes.White, 2), defect.StartPoint, 5);
                        else if (defectAngle < 100)
                        {
                            drawCircle(g, new Pen(Brushes.White, 2), defect.StartPoint, 5);
                            drawCircle(g, new Pen(Brushes.White, 2), defect.EndPoint, 5);
                        }
                        else
                            drawCircle(g, new Pen(Brushes.Gray, 2), defect.StartPoint, 5);
                        */
                    }
                }
                ///---

                ///--- K-CURVATURE
                stopwatch.Restart();
                //Point[] curvePoints = endPoints.ToArray();
                Point[] curvePoints = convexHull.ToArray();
                //int[] indexArray = getContourCurvatureIndices(contours, curvePoints);
                int[] indexArray = KCurvature.getContourCurvatureIndices(contours, curvePoints);
                //KCurve1(contours, indexArray, g);
                //KCurve2(contours, indexArray, g);
                Accord.Math.Geometry.KCurvature kcurve = new Accord.Math.Geometry.KCurvature(16, new AForge.DoubleRange(30, 90));
                List<AForge.IntPoint> intPointContour = convertToIntPoint(contours.ToArray());
                List<AForge.IntPoint> contourPeaks = kcurve.FindPeaks(intPointContour);

                this.minFingerDistance = getMinDistance(contourPeaks.ToArray());

                ///---
                /// Trying to find the forearm

                stopwatch.Restart();

                ///
                /// method 1
                ///
                Point[] forearmPoints = new Point[convexHull.Count()];
                int k = 0;
                foreach (Point p in convexHull.ToArray())
                {
                    double error = 15;
                    if (Math.Abs(p.Y - contours.BoundingRectangle.Bottom) < error)
                    {
                        //g.DrawRectangle(new Pen(Brushes.Aquamarine), p.X, p.Y, 5, 5);
                        forearmPoints[k] = p;
                        //Console.WriteLine("point {1}: {0}",p.ToString(), k);
                        k++;
                    }
                }
                Point p0;
                //Console.WriteLine("forearm points: {0}", forearmPoints.Count());
                if (forearmPoints.Count() == 1)
                    p0 = forearmPoints[0];
                else
                    p0 = getMidPoint(forearmPoints[0], forearmPoints[1]);

                //Console.WriteLine("midpoint : {0}", p0.ToString());
                g.DrawRectangle(new Pen(Brushes.Aquamarine), p0.X, p0.Y, 5, 5);
                g.DrawLine(new Pen(Brushes.Aquamarine),p0 ,convertPoint3D(lastPoint));

                ///
                ///
                ///

                /*
                //Point[] possibleWristPoints = convexHull.Intersect(contours).ToArray();
                Point[] possibleWristPoints = convexHull.ToArray();
                for (int i = 0; i < possibleWristPoints.Count(); i++)
                {
                    Point p = possibleWristPoints[i];
                    double error = 10;
                    if (Math.Abs(p.Y - contours.BoundingRectangle.Bottom) < error)
                        g.DrawRectangle(new Pen(Brushes.Aquamarine), p.X, p.Y, 10, 10);

                    double minDistance = 1000000;
                    for (int j = 0; j < contourPeaks.Count(); j++)
                    {
                        AForge.IntPoint p2 = contourPeaks[j];
                        double pointDistance = getPointDistance(p, new Point(p2.X, p2.Y));
                        if (pointDistance < minDistance)
                            minDistance = pointDistance;
                    }
                    //if (minDistance > 50)

                    //g.DrawRectangle(new Pen(Brushes.Aquamarine), p.X, p.Y, 10, 10);

                    //LineSegment2D line = new LineSegment2D(possibleWristPoints[i], possibleWristPoints[i + 1]);
                    //Point midPoint = getMidPoint(possibleWristPoints[i], possibleWristPoints[i + 1]);
                    //if (contourRectangle.Bottom == midPoint.X)
                    //if (contours.Contains(line.P1) && contours.Contains(line.P2))
                    //g.DrawLine(new Pen(Brushes.Aquamarine), possibleWristPoints[i], possibleWristPoints[i + 1]);
                    //g.DrawString(i.ToString(), DefaultFont, Brushes.Red, p.X, p.Y);
                    //Console.WriteLine("Possible wrist point: {0}, {1}", p.X, p.Y);
                    //i++;
                }
                */
                stopwatch.Stop();
                //Console.WriteLine("polygon/contour intersect time: {0}", Math.Round(1000.0 * (double)stopwatch.ElapsedTicks / Stopwatch.Frequency, 4));
                ///---
                ///

                // Count the finger tips found if we've processed 3 frames already
                if (frame > fingersDetectedHistorySize)
                {
                    for (int i = 0; i < fingersDetectedHistorySize - 1; i++)
                    {
                        //Console.WriteLine("finger history {0}: {1}", i, fingersDetectedHistory[i]);
                        fingersDetectedHistory[i] = fingersDetectedHistory[i + 1];
                    }
                    fingersDetectedHistory[fingersDetectedHistorySize - 1]  = contourPeaks.Count() - 1;

                    if (fingersDetectedHistory[fingersDetectedHistorySize-1] == fingersDetectedHistory[fingersDetectedHistorySize-3] &&
                        fingersDetectedHistory[fingersDetectedHistorySize-3] != fingersDetectedHistory[fingersDetectedHistorySize-2])
                        fingersDetectedHistory[fingersDetectedHistorySize-2] = fingersDetectedHistory[fingersDetectedHistorySize-3];
                    //Console.WriteLine("Fingers: {0}", fingersDetectedHistory[0]);
                }

                if (this.startClickLag)
                    this.clickLag++;

                double perimeterMultiplier = (this.lastPoint.Z / 800);
                double contourPerimeter = contours.Perimeter * perimeterMultiplier;

                int fingers = contourPeaks.Count - 1;
                // contourPerimeter > 700 is an experiemental value obtained my analyzing my own
                // hand contour. this must be changed for other users.
                //if ((contourPerimeter > 600 || fingers > 3) && !this.leftButtonDown)
                if ((fingers > 3) && !this.leftButtonDown)
                {
                    if (this.clickLag < 7)
                        this.clickLag++;
                    else
                    {
                        stopTracking = false;
                        this.clickLag = 0;
                    }
                    /*
                    if (this.startClickLag && !mouseActionReset)
                    {
                        if (this.clickLag < 20)
                        {
                            stopTracking = true;
                            this.clickLag++;
                        }
                        else
                        {
                            this.clickLag = 0;
                            this.startClickLag = false;
                        }
                    }
                    else
                        stopTracking = true;
                     * */
                }

                // this doesnt account for releasing the left mouse button
                if (this.frame > 5 && shouldControlMouse &&
                    fingersDetectedHistory[0] == fingersDetectedHistory[1] &&
                    fingersDetectedHistory[1] == fingersDetectedHistory[2])
                {
                    if (!leftButtonDown)
                        stopTracking = true;
                    if (fingersDetectedHistory[0] == 1)
                    {
                        this.frameCount++;
                        if (this.frameCount > 25)
                            sendMouseEvent(11);
                    }
                    else
                    {
                        if (this.frameCount > 3 && this.frameCount < 25)
                            sendMouseEvent(1);
                        else if (this.frameCount > 25)
                            sendMouseEvent(11);
                        else
                            sendMouseEvent(fingersDetectedHistory[0]);
                        this.frameCount = 0;
                    }
                }

                // Highlight the finger tip positions
                int peakIndex = 1;
                foreach (AForge.IntPoint p in contourPeaks)
                {
                    g.DrawRectangle(new Pen(Brushes.White), p.X - 2, p.Y - 2, 4, 4);
                    g.DrawString(peakIndex.ToString(), DefaultFont, Brushes.White, p.X + 4, p.Y - 4);
                    peakIndex++;
                }
                stopwatch.Stop();
                //Console.WriteLine("KCurve time {0} ms", Math.Round(1000.0 * (double)stopwatch.ElapsedTicks / Stopwatch.Frequency, 4));
                ///---
                ///

                // to build a circle just start with a square and filter by radius distance

                //Point polygonCenter = getCentroid(polygon);
                //Point contourCenter = getCentroid(contours.ToArray());

                //updatePalm(g, contours);
                updatePalmNite();

                /*
                drawCircle(g, new Pen(Brushes.BlueViolet), contourRectangleCenter, 10);
                drawCircle(g, new Pen(Brushes.BlueViolet), contourRectangleCenter, 25);
                drawCircle(g, new Pen(Brushes.BlueViolet), contourRectangleCenter, 50);
                */

                //Console.WriteLine(this.lastPoint.X + ", " + this.lastPoint.Y + ": " + depth.GetMetaData()[(int)this.lastPoint.X, (int)this.lastPoint.Y]);
                g.DrawString("now " + (contourPeaks.Count() - 1).ToString(), DefaultFont, Brushes.White, 50, 130);
                g.DrawString("filtered " + fingersDetectedHistory[0].ToString(), DefaultFont, Brushes.White, 50, 150);
                g.DrawString(Math.Round(this.hullRatios[2], 4).ToString(), DefaultFont, Brushes.White, 50, 170);
                g.DrawString("handOpen:"+fistClosed.ToString(), DefaultFont, Brushes.White, 50, 190);
                g.DrawString("Frames: "+this.frame, DefaultFont, Brushes.White, 50, 210);
                if (shouldControlMouse && !stopTracking)
                    g.DrawString("Cursor: " + lastScaledMousePoint.X+", "+lastScaledMousePoint.Y, DefaultFont, Brushes.White, 50, 230);
                g.DrawString(depth.GetMetaData().FPS.ToString(), DefaultFont, Brushes.White, 50, 250);
                g.DrawString(this.minFingerDistance.ToString(), DefaultFont, Brushes.White, 50, 270);
                //g.DrawClosedCurve(new Pen(Brushes.Purple), fingerPoints);

                //Save the frame to disk (if specified)
                if (this.captureFrames)
                    this.bitmap.Save(System.IO.Path.Combine(this.frameDir,this.frame + ".png"), ImageFormat.Png);
                this.frame++;
            }
        }
示例#17
0
        private void CreateDelaunay(ref Mat img, ref Subdiv2D subdiv, ref VectorOfPointF points,
                                    bool drawAnimated, ref VectorOfVectorOfInt triangleIndexes)
        {
            PointF[] pointsArr = points.ToArray();
            foreach (PointF p in pointsArr)
            {
                subdiv.Insert(p);
                if (drawAnimated)
                {
                    Mat imgCopy = img.Clone();
                    DrawDelaunay(ref imgCopy, ref subdiv, new MCvScalar(255, 255, 255));
                    CvInvoke.Imshow("Delaunay Triangulation", imgCopy);
                }
            }

            // Unfortunately we don't get the triangles by there original point indexes.
            // We only get them with their vertex coordinates.
            // So we have to map them again to get the triangles with their point indexes.

            Size      size = img.Size;
            Rectangle rect = new Rectangle(0, 0, size.Width, size.Height);

            VectorOfInt ind = new VectorOfInt();

            int[]         indArr       = new int[3];
            Triangle2DF[] triangleList = subdiv.GetDelaunayTriangles();
            for (int i = 0; i < triangleList.Length; i++)
            {
                Triangle2DF t = triangleList[i];

                PointF ptzero = new PointF {
                    X = t.V0.X, Y = t.V0.Y
                };
                PointF[] PZero = new PointF[] { ptzero };

                PointF ptone = new PointF {
                    X = t.V1.X, Y = t.V1.Y
                };
                PointF[] POne = new PointF[] { ptone };

                PointF pttwo = new PointF {
                    X = t.V2.X, Y = t.V2.Y
                };
                PointF[] PTwo = new PointF[] { pttwo };

                VectorOfPointF pt = new VectorOfPointF();

                pt.Push(PZero);

                pt.Push(POne);
                pt.Push(PTwo);

                if (rect.Contains(new Point((int)pt[0].X, (int)pt[0].Y)) &&
                    rect.Contains(new Point((int)pt[1].X, (int)pt[1].Y)) &&
                    rect.Contains(new Point((int)pt[2].X, (int)pt[2].Y)))
                {
                    for (int j = 0; j < 3; j++)
                    {
                        for (int k = 0; k < points.Size; k++)
                        {
                            if (Math.Abs(pt[j].X - points[k].X) < 1.0 &&
                                Math.Abs(pt[j].Y - points[k].Y) < 1)
                            {
                                indArr[j] = k;
                            }
                        }
                    }
                }
                ind = new VectorOfInt(indArr);
                triangleIndexes.Push(ind);
            }
        }
示例#18
0
        public void TriangleRectangleImage(ref VectorOfVectorOfPoint contours, double epsilonFact = 0.05, double minArea = 10)
        {
            Stopwatch watch = Stopwatch.StartNew();

            triangleList = new List <Triangle2DF>();
            boxList      = new List <RotatedRect>(); //a box is a rotated rectangle



            int count = contours.Size;

            for (int i = 0; i < count; i++)
            {
                VectorOfPoint contour       = contours[i];
                VectorOfPoint approxContour = new VectorOfPoint();
                double        epsilon       = CvInvoke.ArcLength(contour, true) * epsilonFact;

                CvInvoke.ApproxPolyDP(contour, approxContour, epsilon, true);

                //sign of area gives orientation
                double area = CvInvoke.ContourArea(approxContour, true);
                area = Math.Abs(area);

                if (area > minArea)              //only consider contours with area greater than 250
                {
                    if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle
                    {
                        Point[]     pts      = approxContour.ToArray();
                        Triangle2DF triangle = new Triangle2DF(pts[0], pts[1], pts[2]);
                        triangleList.Add(triangle);
                    }
                    else if (approxContour.Size == 4) //The contour has 4 vertices.
                    {
                        //determine if all the angles in the contour are within [80, 100] degree
                        bool            isRectangle = true;
                        Point[]         pts         = approxContour.ToArray();
                        LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                        for (int j = 0; j < edges.Length; j++)
                        {
                            int    index = (j + 1) % edges.Length;
                            double angle = edges[index].GetExteriorAngleDegree(edges[j]);
                            angle = Math.Abs(angle);
                            if (angle < 80 || angle > 100)
                            {
                                isRectangle = false;
                                break;
                            }
                        }
                        //
                        RotatedRect rotatedRect = CvInvoke.MinAreaRect(approxContour);
                        if (isRectangle)
                        {
                            boxList.Add(rotatedRect);
                        }
                    }
                }
            }

            //   }

            watch.Stop();
            msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds));
        }
		public void ThreadedFunction()
		{
			while (true)
			{
				while (!FApply)
					Thread.Sleep(5);

				int SliceCount;
				Spread<PointF[]> points;
				Spread<Triangle2DF[]> triangles;

				lock (FLockPoints)
				{
					SliceCount = FPoints.SliceCount;
					points = new Spread<PointF[]>(SliceCount);

					for (int i = 0; i < SliceCount; i++)
					{
						points[i] = new PointF[FPoints[i].Length];
						Array.Copy(FPoints[i], points[i], FPoints[i].Length);
					}
	
				}

				triangles = new Spread<Triangle2DF[]>(SliceCount);

				for (int i = 0; i < SliceCount; i++)
				{
					PlanarSubdivision subdivision = new PlanarSubdivision(points[i] as PointF[]);
					triangles[i] = subdivision.GetDelaunayTriangles(false);
				}

				lock (FTriangles)
				{
					FTriangles.SliceCount = SliceCount;

					Triangle2DF t;
					for (int i = 0; i < SliceCount; i++)
					{
						FTriangles[i] = new Triangle2DF[triangles[i].Length];
						for (int j = 0; j < triangles[i].Length; j++ )
						{
							t = triangles[i][j];
							FTriangles[i][j] = new Triangle2DF(t.V0, t.V1, t.V2);
						}
					}
				}

				FResults = true;
			}
		}
示例#20
0
 internal static extern void VectorOfTriangle2DFGetItem(IntPtr vec, int index, ref Triangle2DF element);
        /// <summary>
        /// Draws trangulated poly
        /// </summary>
        /// <param name="img">Image we're drawing to</param>
        /// <param name="trisList">Triangles list</param>
        /// <param name="imgBox">Box we're inserting image to</param>
        public void drawTris(Image<Gray, Byte> img, Triangle2DF[] trisList, ref Emgu.CV.UI.ImageBox imgBox)
        {
            //Draw the Delaunay triangulation
            foreach (Triangle2DF tri in trisList)
            {
                img.Draw(tri, new Gray(128.0f), 2);
            }

            imgBox.Image = img;
        }