C# OpenCvSharp+DlibDotNet 人脸替换 换脸

效果

C# OpenCvSharp+DlibDotNet 人脸替换 换脸_第1张图片

C# OpenCvSharp+DlibDotNet 人脸替换 换脸_第2张图片

Demo下载

项目

VS2022+.net4.8+OpenCvSharp4+DlibDotNet

C# OpenCvSharp+DlibDotNet 人脸替换 换脸_第3张图片

 相关介绍参考

代码

using DlibDotNet;
using OpenCvSharp.Extensions;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;

namespace OpenCvSharp_人脸替换
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Bitmap bmp;
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string imgPath = "";
        string startupPath = "";

        Bitmap bmp2;
        string imgPath2 = "";

        FrontalFaceDetector fd;
        ShapePredictor sp;

        private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;

            imgPath = ofd.FileName;
            bmp = new Bitmap(imgPath);
            pictureBox1.Image = new Bitmap(imgPath);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox2.Image = null;

            imgPath2 = ofd.FileName;
            bmp2 = new Bitmap(imgPath2);
            pictureBox2.Image = new Bitmap(imgPath2);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (pictureBox1.Image==null || pictureBox2.Image==null)
            {
                return;
            }
            pictureBox3.Image = ProcessImage(bmp, bmp2);
        }

        /// 
        /// Process the original selfie and produce the face-swapped image.
        /// 
        /// The original selfie image.
        /// The new face to insert into the selfie.
        /// A new image with faces swapped.
        public Bitmap ProcessImage(Bitmap image, Bitmap newImage)
        {

            // convert image to dlib format
            var img = Dlib.LoadImage(imgPath);

            // find bradley's faces in image
            var faces = fd.Operator(img);
            if (faces.Count()==0)
            {
                return null;
            }
            var bradley = faces[0];

            // get bradley's landmark points
            var bradleyShape = sp.Detect(img, bradley);
            var bradleyPoints = (from i in Enumerable.Range(0, (int)bradleyShape.Parts)
                                 let p = bradleyShape.GetPart((uint)i)
                                 select new OpenCvSharp.Point(p.X, p.Y)).ToArray();

            // get convex hull of bradley's points
            var hull = Cv2.ConvexHullIndices(bradleyPoints);
            var bradleyHull = from i in hull
                              select bradleyPoints[i];

            // find landmark points in face to swap
            var imgMark = Dlib.LoadImage(imgPath2);
            var faces2 = fd.Operator(imgMark);
            if (faces2.Count() == 0)
            {
                return null;
            }
            var mark = faces2[0];
            var markShape = sp.Detect(imgMark, mark);
            var markPoints = (from i in Enumerable.Range(0, (int)markShape.Parts)
                              let p = markShape.GetPart((uint)i)
                              select new OpenCvSharp.Point(p.X, p.Y)).ToArray();

            // get convex hull of mark's points
            var hull2 = Cv2.ConvexHullIndices(bradleyPoints);
            var markHull = from i in hull2
                           select markPoints[i];


            // calculate Delaunay triangles
            var triangles = Utility.GetDelaunayTriangles(bradleyHull);

            // get transformations to warp the new face onto Bradley's face
            var warps = Utility.GetWarps(markHull, bradleyHull, triangles);

            // apply the warps to the new face to prep it for insertion into the main image
            var warpedImg = Utility.ApplyWarps(newImage, image.Width, image.Height, warps);


            // prepare a mask for the warped image
            var mask = new Mat(image.Height, image.Width, MatType.CV_8UC3);
            mask.SetTo(0);
            Cv2.FillConvexPoly(mask, bradleyHull, new Scalar(255, 255, 255), LineTypes.Link8);

            // find the center of the warped face
            var r = Cv2.BoundingRect(bradleyHull);
            var center = new OpenCvSharp.Point(r.Left + r.Width / 2, r.Top + r.Height / 2);

            // blend the warped face into the main image
            var selfie = BitmapConverter.ToMat(image);
            var blend = new Mat(selfie.Size(), selfie.Type());
            Cv2.SeamlessClone(warpedImg, selfie, mask, center, blend, SeamlessCloneMethods.NormalClone);

            // return the modified main image
            return BitmapConverter.ToBitmap(blend);


        }

        private void Form1_Load(object sender, EventArgs e)
        {
            fd = Dlib.GetFrontalFaceDetector();
            sp = ShapePredictor.Deserialize("shape_predictor_68_face_landmarks.dat");
            Dlib.Encoding = Environment.OSVersion.Platform == PlatformID.Win32NT ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;
        }

    }
}

你可能感兴趣的:(Dlib,OpenCV,C#,C#人脸替换,C#换脸)