/// <summary>
        /// Perform Delaunay triangulation on a given set of landmark points.
        /// </summary>
        /// <param name="points">The landmark points to use for triangulation.</param>
        /// <returns>A list of Triangle structures that each refer to a single triangle of landmark points.</returns>
        public static IEnumerable <Triangle> GetDelaunayTriangles(IEnumerable <Point> points)
        {
            var result = new List <Triangle>();

            // calculate the bounding box around the points
            var rect = Cv2.BoundingRect(points);

            rect.Inflate(10, 10);

            // the Subdiv2D class handles Delaunay triangulation
            // first we add all points, and then start triangulation
            Vec6f[] triangles;
            using (var subdiv = new Subdiv2D(rect))
            {
                foreach (var p in points)
                {
                    var cv_p = new OpenCvSharp.Point2f(p.X, p.Y);
                    subdiv.Insert(cv_p);
                }
                triangles = subdiv.GetTriangleList();
            }

            // return result as an enumeration of triangle structs
            return(from t in triangles
                   let p1 = new Point(t[0], t[1])
                            let p2 = new Point(t[2], t[3])
                                     let p3 = new Point(t[4], t[5])
                                              where rect.Contains(p1) && rect.Contains(p2) && rect.Contains(p3)
                                              select new Triangle(p1, p2, p3));
        }
Exemple #2
0
        public void GetTriangleList()
        {
            using var subdiv = new Subdiv2D(new Rect(0, 0, 500, 500));

            var points = new[] { new Point2f(300, 100), new Point2f(200, 300), new Point2f(400, 300) };

            subdiv.Insert(points[0]);
            subdiv.Insert(points[1]);
            subdiv.Insert(points[2]);

            var triangles = subdiv.GetTriangleList();

            Assert.Single(triangles);

            var triangleVertices = new[]
            {
                triangles[0].Item0, triangles[0].Item1, triangles[0].Item2, triangles[0].Item3, triangles[0].Item4, triangles[0].Item5,
            };

            foreach (var point in points)
            {
                Assert.Contains(point.X, triangleVertices);
                Assert.Contains(point.Y, triangleVertices);
            }
        }
    private static void Add8PointBorder(Subdiv2D s, int width, int height)
    {
        var list = Get8PointBorder(width, height);

        foreach (var p in list)
        {
            s.insert(p);
        }
    }
        /// <summary>
        /// Raises the web cam texture to mat helper inited event.
        /// </summary>
        public void OnWebCamTextureToMatHelperInited()
        {
            Debug.Log("OnWebCamTextureToMatHelperInited");

            Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();

            texture = new Texture2D(webCamTextureMat.cols(), webCamTextureMat.rows(), TextureFormat.RGBA32, false);

            gameObject.GetComponent <Renderer> ().material.mainTexture = texture;

            gameObject.transform.localScale = new Vector3(webCamTextureMat.cols(), webCamTextureMat.rows(), 1);
            Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);


            float width  = webCamTextureMat.width();
            float height = webCamTextureMat.height();

            float widthScale  = (float)Screen.width / width;
            float heightScale = (float)Screen.height / height;

            if (widthScale < heightScale)
            {
                Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
            }
            else
            {
                Camera.main.orthographicSize = height / 2;
            }


            Mat downScaleMat = webCamTextureToMatHelper.GetDownScaleMat(webCamTextureMat);

            gray1Mat = new Mat(downScaleMat.rows(), downScaleMat.cols(), CvType.CV_8UC1);
            gray2Mat = new Mat(downScaleMat.rows(), downScaleMat.cols(), CvType.CV_8UC1);

            int ksize = 7;

            float[] kernelData = new float[ksize * ksize];
            for (int i = 0; i < kernelData.Length; i++)
            {
                if (i == kernelData.Length / 2)
                {
                    kernelData [i] = (-(kernelData.Length - 1));
                }
                else
                {
                    kernelData [i] = 1;
                }
            }
            kernel = new Mat(ksize, ksize, CvType.CV_32F);
            kernel.put(0, 0, kernelData);

            byteArray = new byte[downScaleMat.width() * downScaleMat.height()];

            subdiv = new Subdiv2D();
        }
        public void Run()
        {
            const int Size = 600;

            // Creates random point list
            var rand   = new Random();
            var points = Enumerable.Range(0, 100).Select(_ =>
                                                         new Point2f(rand.Next(0, Size), rand.Next(0, Size))).ToArray();

            Mat img = Mat.Zeros(Size, Size, MatType.CV_8UC3);

            foreach (var p in points)
            {
                img.Circle(p, 4, Scalar.Red, -1);
            }

            // Initializes Subdiv2D
            var subdiv = new Subdiv2D();

            subdiv.InitDelaunay(new Rect(0, 0, Size, Size));
            subdiv.Insert(points);

            // Draws voronoi diagram
            Point2f[][] facetList;
            Point2f[]   facetCenters;
            subdiv.GetVoronoiFacetList(null, out facetList, out facetCenters);

            var vonoroi = img.Clone();

            foreach (var list in facetList)
            {
                var before = list.Last();
                foreach (var p in list)
                {
                    vonoroi.Line(before, p, new Scalar(64, 255, 128), 1);
                    before = p;
                }
            }

            // Draws delaunay diagram
            Vec4f[] edgeList = subdiv.GetEdgeList();
            var     delaunay = img.Clone();

            foreach (var edge in edgeList)
            {
                var p1 = new Point(edge.Item0, edge.Item1);
                var p2 = new Point(edge.Item2, edge.Item3);
                delaunay.Line(p1, p2, new Scalar(64, 255, 128), 1);
            }

            Cv2.ImShow("voronoi", vonoroi);
            Cv2.ImShow("delaunay", delaunay);
            Cv2.WaitKey();
            Cv2.DestroyAllWindows();
        }
Exemple #6
0
        public static void CreateSubdivision(int rows, int cols, int pointCount, out Triangle2DF[] delaunayTriangles, out VoronoiFacet[] voronoiFacets)
        {
            var rand = new Random();
            var pts  = Enumerable.Range(0, pointCount).Select(_ => new PointF(rand.Next(0, cols), rand.Next(0, rows))).ToArray();

            using (Subdiv2D subdivision = new Subdiv2D(pts))
            {
                delaunayTriangles = subdivision.GetDelaunayTriangles();
                voronoiFacets     = subdivision.GetVoronoiFacets();
            }
        }
Exemple #7
0
        public void GetVoronoiFacetList()
        {
            using var subdiv = new Subdiv2D(new Rect(0, 0, 500, 500));

            var points = new[] { new Point2f(300, 100), new Point2f(200, 300), new Point2f(400, 300) };

            subdiv.Insert(points);

            subdiv.GetVoronoiFacetList(null, out var facetList, out var facetCenters);
            Assert.Equal(3, facetList.Length);
            Assert.Equal(3, facetCenters.Length);
            Assert.Equal(4, facetList[0].Length);
        }
Exemple #8
0
        public void Run()
        {
            const int Size = 600;

            // Creates random point list
            var rand = new Random();
            var points = Enumerable.Range(0, 100).Select(_ =>
                new Point2f(rand.Next(0, Size), rand.Next(0, Size))).ToArray();

            Mat img = Mat.Zeros(Size, Size, MatType.CV_8UC3);
            foreach (var p in points)
            {
                img.Circle(p, 4, CvColor.Red, -1);
            }

            // Initializes Subdiv2D
            var subdiv = new Subdiv2D();
            subdiv.InitDelaunay(new Rect(0, 0, Size, Size));
            subdiv.Insert(points);

            // Draws voronoi diagram
            Point2f[][] facetList;
            Point2f[] facetCenters;
            subdiv.GetVoronoiFacetList(null, out facetList, out facetCenters);

            var vonoroi = img.Clone();
            foreach (var list in facetList)
            {
                var before = list.Last();
                foreach (var p in list)
                {
                    vonoroi.Line(before, p, new CvColor(64, 255, 128), 1);
                    before = p;
                }
            }

            // Draws delaunay diagram
            Vec4f[] edgeList = subdiv.GetEdgeList();
            var delaunay = img.Clone();
            foreach (var edge in edgeList)
            {
                var p1 = new Point(edge.Item0, edge.Item1);
                var p2 = new Point(edge.Item2, edge.Item3);
                delaunay.Line(p1, p2, new CvColor(64, 255, 128), 1);
            }

            Cv2.ImShow("voronoi", vonoroi);
            Cv2.ImShow("delaunay", delaunay);
            Cv2.WaitKey();
            Cv2.DestroyAllWindows();
        }
Exemple #9
0
 // Draws the Delaunay triangualtion into an image using the Subdiv2D
 private void DrawDelaunay(ref Mat img1D, ref Subdiv2D subdiv, MCvScalar mCvScalar)
 {
     Triangle2DF[] delaunayTriangles = subdiv.GetDelaunayTriangles();
     foreach (Triangle2DF triangle in delaunayTriangles)
     {
         System.Drawing.Point[] vertices = Array.ConvertAll <PointF, System.Drawing.Point>(triangle.GetVertices(), System.Drawing.Point.Round);
         using (VectorOfPoint vp = new VectorOfPoint(vertices))
         {
             CvInvoke.Polylines(img1D, vp, true, new Bgr(255, 255, 255).MCvScalar);
         }
     }
     img1D.ConvertTo(img1D, Emgu.CV.CvEnum.DepthType.Cv8U);
     CvInvoke.Imshow("Delaunay Triangulation", img1D);
 }
Exemple #10
0
 private void CreateSubdivision(float maxValue, int pointCount, out Triangle2DF[] delaunayTriangles, out VoronoiFacet[] voronoiFacets)
 {
     #region 在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))
     {
         delaunayTriangles = subDivision.GetDelaunayTriangles();
         voronoiFacets     = subDivision.GetVoronoiFacets();
     }
 }
Exemple #11
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();
            }
        }
Exemple #12
0
        private void CreateDelaunay()
        {
            // Delaunay
            if (facesArrNext != null && facesArrCurr != null)
            {
                using (VectorOfPointF vpfCurr = ffpCurr)
                    using (VectorOfPointF vpfNext = ffpNext)
                    {
                        ptsCurr = vpfCurr.ToArray();
                        ptsNext = vpfNext.ToArray();

                        using (Subdiv2D subdivisionLeft = new Subdiv2D(ptsCurr))
                            using (Subdiv2D subdivisionRight = new Subdiv2D(ptsNext))
                            {
                                //Obtain the delaunay's triangulation from the set of points;
                                delaunayTrianglesCurr = subdivisionLeft.GetDelaunayTriangles();
                                delaunayTrianglesNext = subdivisionRight.GetDelaunayTriangles();
                            }
                    }
            }
        }
Exemple #13
0
 private static IEnumerable <int[]> GetDelaunayTriangulationIndexes(Rect rect, List <Point2f> points)
 {
     rect = Cv2.BoundingRect(points).Union(rect);
     using (var subdivision = new Subdiv2D(rect))
     {
         subdivision.Insert(points);
         var triangulation = subdivision.GetTriangleList();
         foreach (var cell in triangulation)
         {
             var p1 = new Point2f(cell.Item0, cell.Item1);
             var p2 = new Point2f(cell.Item2, cell.Item3);
             var p3 = new Point2f(cell.Item4, cell.Item5);
             if (rect.Contains(p1) && rect.Contains(p2) && rect.Contains(p3))
             {
                 var indexA  = points.IndexOf(p1);
                 var indexB  = points.IndexOf(p2);
                 var indexC  = points.IndexOf(p3);
                 var indexes = new[] { indexA, indexB, indexC };
                 yield return(indexes);
             }
         }
     }
 }
Exemple #14
0
 public void Create()
 {
     using var subdiv = new Subdiv2D();
 }
Exemple #15
0
 public void CreateWithRect()
 {
     using var subdiv = new Subdiv2D(new Rect(0, 0, 500, 500));
 }
        /// <summary>
        /// Raises the web cam texture to mat helper inited event.
        /// </summary>
        public void OnWebCamTextureToMatHelperInited()
        {
            Debug.Log ("OnWebCamTextureToMatHelperInited");

            Mat webCamTextureMat = webCamTextureToMatHelper.GetMat ();

            texture = new Texture2D (webCamTextureMat.cols (), webCamTextureMat.rows (), TextureFormat.RGBA32, false);

            gameObject.GetComponent<Renderer> ().material.mainTexture = texture;

            gameObject.transform.localScale = new Vector3 (webCamTextureMat.cols (), webCamTextureMat.rows (), 1);
            Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);

            float width = webCamTextureMat.width ();
            float height = webCamTextureMat.height ();

            float widthScale = (float)Screen.width / width;
            float heightScale = (float)Screen.height / height;
            if (widthScale < heightScale) {
                Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
            } else {
                Camera.main.orthographicSize = height / 2;
            }

            Mat downScaleMat = webCamTextureToMatHelper.GetDownScaleMat (webCamTextureMat);

            gray1Mat = new Mat (downScaleMat.rows (), downScaleMat.cols (), CvType.CV_8UC1);
            gray2Mat = new Mat (downScaleMat.rows (), downScaleMat.cols (), CvType.CV_8UC1);

            int ksize = 7;
            float[] kernelData = new float[ksize * ksize];
            for (int i = 0; i < kernelData.Length; i++) {
                if (i == kernelData.Length / 2) {
                    kernelData [i] = (-(kernelData.Length - 1));
                } else {
                    kernelData [i] = 1;
                }
            }
            kernel = new Mat (ksize, ksize, CvType.CV_32F);
            kernel.put (0, 0, kernelData);

            byteArray = new byte[downScaleMat.width () * downScaleMat.height ()];

            subdiv = new Subdiv2D ();
        }
Exemple #17
0
 public void InitDelaunay()
 {
     using var subdiv = new Subdiv2D();
     subdiv.InitDelaunay(new Rect(0, 0, 800, 600));
 }
    private void WarpFaces()
    {
        // Create the image matrices
        Mat imgSrc  = CreateSourceImageMat();
        Mat imgDest = CreateDestImageMat(imgSrc);

        // Generate the face data (in this case, load the parameters)
        //var sourceFace = JsonConvert.DeserializeObject<RootObject>(sourceImageFace);
        //var warpToFace = JsonConvert.DeserializeObject<RootObject>(this.warpToFace);

        // Create the landmark point lists
        var pointList1 = new List <Point>();
        var pointList2 = new List <Point>();

        AddMatchingLandmarks(sourceFace.faceLandmarks, warpToFace.faceLandmarks, pointList1, pointList2);

        if (pointList1.Count != pointList2.Count)
        {
            Debug.LogErrorFormat("Counts are not equal.  Lists ahve {0} and {1} elements.", pointList1.Count, pointList2.Count);
        }

        // Declare the int source width/height
        int sw = (int)imgSrc.size().width;
        int sh = (int)imgSrc.size().height;
        int dw = warpToImage.width;
        int dh = warpToImage.height;

        // Create a subdivision for the source image
        var sourceSubDiv = new Subdiv2D(new OpenCVForUnity.Rect(0, 0, sw, sh));

        // Add border points to the subdivision
        // and add all the other points
        Add8PointBorder(sourceSubDiv, sw, sh);
        foreach (var p in pointList1)
        {
            sourceSubDiv.insert(p);
        }

        // Create a list of triangles
        // from the subdivision
        MatOfFloat6 sourceTriMat = new MatOfFloat6();

        sourceSubDiv.getTriangleList(sourceTriMat);
        var sourceTriList = new List <float>(sourceTriMat.toArray());

        // OpenCV for Unity subdiv has a bug and we need to ensure
        // every triangle is inside the bounds of the source
        CapToMax(sourceTriList, sw - 1, sh - 1);

        // Copy it
        var destTriList = new List <float>();

        foreach (float f in sourceTriList)
        {
            destTriList.Add(f);
        }

        // Find the points from the source, and
        // move them to the destination this way
        // the triangles correlate to each other
        MovePointsInList(sourceFace.faceLandmarks.FaceLandmarkList(), warpToFace.faceLandmarks.FaceLandmarkList(), destTriList);
        MovePointsInList(Get8PointBorder(sw, sh), Get8PointBorder(dw, dh), destTriList);

        // Now we have source triangles and positions
        // and destination triangles and positions
        // warp the source triangles ot the destination
        WarpImages(imgSrc, imgDest, sourceTriList, destTriList);

        // Everything is warped, so now create the texture from
        // the matrix
        Texture2D texture = MatToTexture2D(imgDest);

        // Assign the texture
        target.GetComponent <Renderer>().material.mainTexture = texture;
    }
Exemple #19
0
        void TriangleDivide()
        {
            //init subdiv
            Subdiv2D subdiv = new Subdiv2D();

            OpenCVForUnity.Rect cv_rect = new OpenCVForUnity.Rect(0, 0, rgbaMat.width(), rgbaMat.height());
            subdiv.initDelaunay(cv_rect);
            for (int i = 0; i < pointList.Count; i++)
            {
                subdiv.insert(pointList[i]);
            }
            subdiv.insert(new Point(0, 0));
            subdiv.insert(new Point(rgbaMat.width() / 4 - 1, 0));                        //
            subdiv.insert(new Point(rgbaMat.width() / 2 - 1, 0));                        //
            subdiv.insert(new Point(rgbaMat.width() / 2 - 1, rgbaMat.height() / 2 - 1)); //
            subdiv.insert(new Point(rgbaMat.width() / 2 - 1, rgbaMat.height() - 1));     //
            subdiv.insert(new Point(rgbaMat.width() / 4 - 1, rgbaMat.height() - 1));     //
            subdiv.insert(new Point(0, rgbaMat.height() - 1));
            subdiv.insert(new Point(0, rgbaMat.height() / 2 - 1));

            //using (MatOfFloat6 triangleList = new MatOfFloat6())
            MatOfFloat6 triangleList = new MatOfFloat6();
            {
                subdiv.getTriangleList(triangleList);
                float[] pointArray = triangleList.toArray();
                //Debug.Log(pointArray.Length); //11000+
                float downScaleRatio = 1;

                byte[] color = new byte[4];
                for (int i = 0; i < pointArray.Length / 6; i++)
                {
                    Point p0 = new Point(pointArray[i * 6 + 0] * downScaleRatio, pointArray[i * 6 + 1] * downScaleRatio);
                    Point p1 = new Point(pointArray[i * 6 + 2] * downScaleRatio, pointArray[i * 6 + 3] * downScaleRatio);
                    Point p2 = new Point(pointArray[i * 6 + 4] * downScaleRatio, pointArray[i * 6 + 5] * downScaleRatio);

                    if (p0.x < 0 || p0.x > rgbaMat.width())
                    {
                        continue;
                    }
                    if (p0.y < 0 || p0.y > rgbaMat.height())
                    {
                        continue;
                    }
                    if (p1.x < 0 || p1.x > rgbaMat.width())
                    {
                        continue;
                    }
                    if (p1.y < 0 || p1.y > rgbaMat.height())
                    {
                        continue;
                    }
                    if (p2.x < 0 || p2.x > rgbaMat.width())
                    {
                        continue;
                    }
                    if (p2.y < 0 || p2.y > rgbaMat.height())
                    {
                        continue;
                    }

                    //get center of gravity
                    int cx = (int)((p0.x + p1.x + p2.x) * 0.33333);
                    int cy = (int)((p0.y + p1.y + p2.y) * 0.33333);
                    //Debug.Log ("cx " + cx + " cy " + cy );

                    //get center of gravity color
                    rgbaMat.get(cy, cx, color);
                    //Debug.Log ("r " + color[0] + " g " + color[1] + " b " + color[2] + " a " + color[3]);

                    //fill Polygon
                    //Imgproc.fillConvexPoly(rgbaMat, new MatOfPoint(p0, p1, p2), new Scalar(color[0], color[1], color[2], color[3]), Imgproc.LINE_AA, 0);
                    Imgproc.line(rgbaMat, p0, p1, new Scalar(64, 255, 128, 255));
                    Imgproc.line(rgbaMat, p1, p2, new Scalar(64, 255, 128, 255));
                    Imgproc.line(rgbaMat, p2, p0, new Scalar(64, 255, 128, 255));

                    //--------------------------------------------------------------------//

                    //Debug.Log(pointArray.Length / 6); //154 //(68dlib点+周围8点 => 154个三角形)
                    //Point[] pt = new Point[3];
                    //pt[0] = new Point(t[0], t[1]);
                    //pt[1] = new Point(t[2], t[3]);
                    //pt[2] = new Point(t[4], t[5]);
                    //Debug.Log("[0]" + pt[0] + "[1]" + pt[1] + "[2]" + pt[2]);
                    Point[] pt = new Point[3] {
                        p0, p1, p2
                    };
                    //Debug.Log("[0]" + p0 + "[1]" + p1 + "[2]" + p2);

                    //Debug.Log(cv_rect); //800*400,rgba图的尺寸
                    if (cv_rect.contains(p0) && cv_rect.contains(p1) && cv_rect.contains(p2))
                    {
                        int   count = 0;
                        int[] index = new int[3];
                        for (int j = 0; j < 3; j++)
                        {
                            for (int k = 0; k < pointList.Count; k++)
                            {
                                if (Mathf.Abs((float)pt[j].x - (float)pointList[k].x) < 1.0 && Mathf.Abs((float)pt[j].y - (float)pointList[k].y) < 1.0) //重合
                                {
                                    index[j] = k;
                                    count++;
                                }
                            }
                        }

                        if (count == 3)
                        {
                            //154中筛选109个,满足3个点重合
                            //delaunayTri.push_back(index);
                        }
                    }

                    //--------------------------------------------------------------------//
                }
                //subdiv.getVoronoiFacetList();
            }
        }
Exemple #20
0
        //public MorphImage(Mat img1, Mat img2, VectorOfPointF points1, VectorOfPointF points2, float alpha)
        public MorphImage(ImageDetails imgdet1, ImageDetails imgdet2, VectorOfPointF points1, VectorOfPointF points2, float alpha)
        {
            this.img1  = imgdet1.ResizedImage.Mat;
            this.img2  = imgdet2.ResizedImage.Mat;
            this.alpha = alpha;

            img1.ConvertTo(img1, Emgu.CV.CvEnum.DepthType.Cv32F);
            img2.ConvertTo(img2, Emgu.CV.CvEnum.DepthType.Cv32F);

            this.points1 = points1;
            this.points2 = points2;

            if (points1.Size == 68)
            {
                AddCornerPoints(points1, img1);
            }

            if (points2.Size == 68)
            {
                AddCornerPoints(points2, img2);
            }

            // Add Points for whole image
            //points1 = AddCornerPoints(points1, img1); // todo: corner points get added twice
            //points2 = AddCornerPoints(points2, img2);

            // Create an instance of Subdiv2D
            Rectangle rect   = new Rectangle(0, 0, img1.Size.Width, img1.Size.Height);
            Subdiv2D  subdiv = new Subdiv2D(rect);

            // Create and Draw the Delaunay triangulation
            triangleIndexes = new VectorOfVectorOfInt();
            CreateDelaunay(ref img1, ref subdiv, ref points1, false, ref triangleIndexes);

            //// Draw the Delaunay triangulation of face 1
            //Mat img1D = img1.Clone();
            //DrawDelaunay(ref img1D, ref subdiv, new MCvScalar(255, 255, 255));


            //// Draw the Delaunay triangulation of face 2
            //Mat img2D = img2.Clone();
            //DrawDelaunay(ref img2D, ref points2, triangleIndexes, new MCvScalar(255, 255, 255));
            //img2D.ConvertTo(img2D, Emgu.CV.CvEnum.DepthType.Cv8U);

            //compute weighted average point coordinates
            pointsM = new VectorOfPointF();
            for (int i = 0; i < points1.Size; i++)
            {
                float    x  = (1 - alpha) * points1[i].X + alpha * points2[i].X;
                float    y  = (1 - alpha) * points1[i].Y + alpha * points2[i].Y;
                PointF[] pf = { new PointF(x, y) };
                pointsM.Push(pf);
            }

            //empty image for morphed face
            int rowsM, colsM;

            if (img1.Cols >= img2.Cols)
            {
                colsM = img1.Cols;
            }
            else
            {
                colsM = img2.Cols;
            }
            if (img1.Rows >= img2.Rows)
            {
                rowsM = img1.Rows;
            }
            else
            {
                rowsM = img2.Rows;
            }


            imgM = Mat.Zeros(rowsM, colsM, Emgu.CV.CvEnum.DepthType.Cv32F, 3);

            for (int i = 0; i < triangleIndexes.Size; i++)
            {
                VectorOfPointF t1 = new VectorOfPointF();
                VectorOfPointF t2 = new VectorOfPointF();
                VectorOfPointF tM = new VectorOfPointF();

                PointF ppft10 = points1[triangleIndexes[i][0]];
                PointF ppft11 = points1[triangleIndexes[i][1]];
                PointF ppft12 = points1[triangleIndexes[i][2]];
                PointF ppft20 = points2[triangleIndexes[i][0]];
                PointF ppft21 = points2[triangleIndexes[i][1]];
                PointF ppft22 = points2[triangleIndexes[i][2]];
                PointF ppftM0 = pointsM[triangleIndexes[i][0]];
                PointF ppftM1 = pointsM[triangleIndexes[i][1]];
                PointF ppftM2 = pointsM[triangleIndexes[i][2]];

                PointF[] pft10 = { new PointF(ppft10.X, ppft10.Y) };
                PointF[] pft11 = { new PointF(ppft11.X, ppft11.Y) };
                PointF[] pft12 = { new PointF(ppft12.X, ppft12.Y) };
                PointF[] pft20 = { new PointF(ppft20.X, ppft20.Y) };
                PointF[] pft21 = { new PointF(ppft21.X, ppft21.Y) };
                PointF[] pft22 = { new PointF(ppft22.X, ppft22.Y) };
                PointF[] pftM0 = { new PointF(ppftM0.X, ppftM0.Y) };
                PointF[] pftM1 = { new PointF(ppftM1.X, ppftM1.Y) };
                PointF[] pftM2 = { new PointF(ppftM2.X, ppftM2.Y) };

                t1.Push(pft10);
                t1.Push(pft11);
                t1.Push(pft12);
                t2.Push(pft20);
                t2.Push(pft21);
                t2.Push(pft22);
                tM.Push(pftM0);
                tM.Push(pftM1);
                tM.Push(pftM2);

                MorphTriangle(ref img1, ref img2, ref imgM, ref t1, ref t2, ref tM, alpha);
            }
            imgM.ConvertTo(imgM, Emgu.CV.CvEnum.DepthType.Cv8U);
            //CvInvoke.Imshow("Morphed Face", imgM);
        }
Exemple #21
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);
            }
        }