static void Main(string[] args) { using (var sourceMat = new Mat("source.jpg")) using (var destinationMat = new Mat("destination.jpg")) using (var hc = new CascadeClassifier("HaarCascade.xml")) using (var facemark = FacemarkLBF.Create()) { Console.WriteLine("Face detection starting.."); var sourceFaceRects = hc.DetectMultiScale(sourceMat); if (sourceFaceRects == null || sourceFaceRects.Length == 0) { Console.WriteLine($"Source image: No faces detected."); return; } Console.WriteLine($"Source image: detected {sourceFaceRects.Length} faces."); var destFaceRects = hc.DetectMultiScale(destinationMat); if (destFaceRects == null || destFaceRects.Length == 0) { Console.WriteLine($"Destination image: No faces detected."); return; } Console.WriteLine($"Destination image: detected {destFaceRects.Length} faces."); facemark.LoadModel("lbfmodel.yaml"); using (var sourceInput = InputArray.Create(sourceFaceRects)) using (var destInput = InputArray.Create(destFaceRects)) { facemark.Fit(sourceMat, sourceInput, out Point2f[][] sourceLandmarks); var sourcePoints = sourceLandmarks[0]; facemark.Fit(destinationMat, destInput, out Point2f[][] destLandmarks); var destPoints = destLandmarks[0]; var triangles = destPoints.Take(60).GetDelaunayTriangles(); var warps = triangles.GetWarps(sourcePoints.Take(60), destPoints.Take(60)); using (var warpedMat = sourceMat.ApplyWarps(destinationMat.Width, destinationMat.Height, warps)) using (var mask = new Mat(destinationMat.Size(), MatType.CV_8UC3)) using (var result = new Mat(destinationMat.Size(), MatType.CV_8UC3)) { mask.SetTo(0); var convexHull = Cv2.ConvexHull(destPoints).Select(s => new Point(s.X, s.Y)); Cv2.FillConvexPoly(mask, convexHull, Scalar.White); var rect = Cv2.BoundingRect(convexHull); var center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2); Cv2.SeamlessClone(warpedMat, destinationMat, mask, center, result, SeamlessCloneMethods.NormalClone); var blured = result.MedianBlur(5); blured.SaveImage("result.png"); } } } Console.WriteLine("Done"); }
static void Main(string[] args) { //prepare images for averaging PrepareImages(); //load facemark model _facemark = FacemarkLBF.Create(); _facemark.LoadModel("lbfmodel.yaml"); //collection for all found facemarks var allFaceMarks = new List <List <Point2f> >(); //facemark search and save foreach (var image in Directory.GetFiles(TempDirName)) { using (var mat = new Mat(image)) { var facesRects = _cascade.DetectMultiScale(mat); using (var facesRectsArray = InputArray.Create(facesRects)) { _facemark.Fit(mat, facesRectsArray, out Point2f[][] landmarks); // only one face should be allFaceMarks.Add(landmarks[0].ToList()); } } } //add static points foreach (var facemarks in allFaceMarks) { facemarks.Add(new Point2f(1, 1)); facemarks.Add(new Point2f(1, _outputSize.Height / 2)); facemarks.Add(new Point2f(1, _outputSize.Height - 1)); facemarks.Add(new Point2f(_outputSize.Width - 1, 1)); facemarks.Add(new Point2f(_outputSize.Width / 2, _outputSize.Height - 1)); facemarks.Add(new Point2f(_outputSize.Width - 1, _outputSize.Height / 2)); facemarks.Add(new Point2f(_outputSize.Width - 1, _outputSize.Height - 1)); } //average Facemarks var averagePoints = new List <Point2f>(); for (int i = 0; i < 75; i++) { float xSum = 0; float ySum = 0; for (int j = 0; j < allFaceMarks.Count; j++) { var point = allFaceMarks[j][i]; xSum += point.X; ySum += point.Y; } averagePoints.Add(new Point2f(xSum / allFaceMarks.Count, ySum / allFaceMarks.Count)); } //calculate delaunay triangles var destinationTriangles = averagePoints.GetDelaunayTriangles(); //create result mat var outputMat = new Mat(_outputSize, _matTypeDefault); outputMat.SetTo(0); // blending coeff var delta = 1.0 / allFaceMarks.Count; // warping and blending var files = Directory.GetFiles(TempDirName); for (int i = 0; i < files.Length; i++) { using (var mat = new Mat(files[i])) { var landmarks = allFaceMarks[i]; var warps = destinationTriangles.GetWarps(landmarks, averagePoints); var warpedImg = mat.ApplyWarps(mat.Width, mat.Height, warps); Cv2.AddWeighted(outputMat, 1, warpedImg, delta, 0, outputMat); } } //save outputMat.SaveImage("result.png"); Console.WriteLine("Done."); }