代码
using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Threading; using System.Windows.Forms; namespace FaceFusionSharp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } string fileFilter = "图片|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png"; string startupPath = ""; string source_path = ""; Yolov8Face detect_face; Face68Landmarks detect_68landmarks; FaceEmbdding face_embedding; SwapFace swap_face; FaceEnhance enhance_face; /// <summary> /// 选择头像 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = fileFilter; if (ofd.ShowDialog() != DialogResult.OK) return; pictureBox1.Image = null; source_path = ofd.FileName; pictureBox1.Image = new Bitmap(source_path); } string video_path = ""; string videoFilter = "视频|*.mp4;*.avi;"; /// <summary> /// 目标视频 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = videoFilter; ofd.InitialDirectory = Application.StartupPath + "\\test"; if (ofd.ShowDialog() != DialogResult.OK) return; video_path = ofd.FileName; textBox1.Text = video_path; //读取第一帧显示 VideoCapture vcapture = new VideoCapture(video_path); if (!vcapture.IsOpened()) { MessageBox.Show("打开视频文件失败"); video_path = ""; return; } Mat frame = new Mat(); if (vcapture.Read(frame)) { pictureBox2.Image = new Bitmap(frame.ToMemoryStream()); frame.Dispose(); } else { MessageBox.Show("读取视频文件失败"); video_path = ""; } } List<Bbox> boxes = new List<Bbox>(); Mat source_img=new Mat(); VideoWriter vwriter; bool saveDetVideo = false; private void button1_Click(object sender, EventArgs e) { if (source_path=="") { MessageBox.Show("请选择头像"); return; } if (video_path == "") { MessageBox.Show("请选择目标视频"); return; } button1.Enabled = false; Application.DoEvents(); source_img = Cv2.ImRead(source_path); boxes = detect_face.detect(source_img); if (boxes.Count == 0) { MessageBox.Show("头像中未检测到人脸!"); button1.Enabled = true; return; } if (boxes.Count > 1) { MessageBox.Show("头像中检测到多张人脸,默认使用第一张!"); button1.Enabled = true; return; } Application.DoEvents(); Thread thread = new Thread(new ThreadStart(Swap)); thread.Start(); thread.Join(); button1.Enabled = true; textBox1.Text = "执行完成!"; } void Swap() { int position = 0; //一张图片里可能有多个人脸,这里只考虑1个人脸的情况 List<Point2f> face68landmarks = detect_68landmarks.detect(source_img, boxes[position]); List<float> source_face_embedding = face_embedding.detect(source_img, face68landmarks); VideoCapture vcapture = new VideoCapture(video_path); Mat target_img = new Mat(); if (checkBox1.Checked) { vwriter = new VideoWriter("out.mp4", FourCC.X264, vcapture.Fps, new OpenCvSharp.Size(vcapture.FrameWidth*2, vcapture.FrameHeight)); saveDetVideo = true; } else { saveDetVideo = false; } Cv2.NamedWindow("FaceFusionSharp 按下ESC,退出", WindowFlags.Normal); Cv2.ResizeWindow("FaceFusionSharp 按下ESC,退出", vcapture.FrameWidth, vcapture.FrameHeight / 2); while (vcapture.Read(target_img)) { boxes = detect_face.detect(target_img); if (boxes.Count == 0) { //MessageBox.Show("Target中未检测到人脸!"); continue; } if (boxes.Count > 1) { //MessageBox.Show("Target中检测到多张人脸,默认使用第一张!"); } position = 0; //一张图片里可能有多个人脸,这里只考虑1个人脸的情况 List<Point2f> target_landmark_5; target_landmark_5 = detect_68landmarks.detect(target_img, boxes[position]); Mat swapimg = swap_face.process(target_img, source_face_embedding, target_landmark_5); Mat resultimg = enhance_face.process(swapimg, target_landmark_5); Mat resultCompare = Mat.Zeros(target_img.Rows, target_img.Cols * 2, target_img.Type()); Cv2.HConcat(new Mat[] { target_img, resultimg }, resultCompare); if (saveDetVideo) { vwriter.Write(resultCompare); } Cv2.ImShow("FaceFusionSharp 按下ESC,退出", resultCompare); if (Cv2.WaitKey(1) == 27 || Cv2.GetWindowProperty("FaceFusionSharp 按下ESC,退出", WindowPropertyFlags.Visible) < 1.0) { break; } } Cv2.DestroyAllWindows(); vcapture.Release(); if (saveDetVideo) { vwriter.Release(); } } private void Form1_Load(object sender, EventArgs e) { detect_face = new Yolov8Face("model/yoloface_8n.onnx"); detect_68landmarks = new Face68Landmarks("model/2dfan4.onnx"); face_embedding = new FaceEmbdding("model/arcface_w600k_r50.onnx"); swap_face = new SwapFace("model/inswapper_128.onnx"); enhance_face = new FaceEnhance("model/gfpgan_1.4.onnx"); //target_path = "images/target.jpg"; //source_path = "images/5.jpg"; //target_path = "images/5.jpg"; //source_path = "images/14.jpg"; // 堆代码 duidaima.com //pictureBox1.Image = new Bitmap(source_path); //pictureBox2.Image = new Bitmap(target_path); } } }