/// <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)); }
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(); }
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(); } }
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); }
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(); }
// 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); }
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(); } }
/// <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(); } }
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(); } } } }
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); } } } }
public void Create() { using var subdiv = new Subdiv2D(); }
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 (); }
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; }
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(); } }
//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); }
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); } }