C# OpenCvSharp+DlibDotNet 人脸替换 换脸

news2024/11/24 20:47:18

效果

Demo下载

项目

VS2022+.net4.8+OpenCvSharp4+DlibDotNet

 相关介绍参考

代码

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);
        }

        /// <summary>
        /// Process the original selfie and produce the face-swapped image.
        /// </summary>
        /// <param name="image">The original selfie image.</param>
        /// <param name="newImage">The new face to insert into the selfie.</param>
        /// <returns>A new image with faces swapped.</returns>
        public Bitmap ProcessImage(Bitmap image, Bitmap newImage)
        {

            // convert image to dlib format
            var img = Dlib.LoadImage<RgbPixel>(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<RgbPixel>(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;
        }

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/766813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开发与测试的相杀相爱

无论开发或测试&#xff0c;都只是一份工作&#xff0c;要认真工作但不要私人感情。若是不下心产生了仇恨心理&#xff0c;请公私分明&#xff0c;在心里扎小人吧&#xff1b;若是产生了不可描述的感情&#xff0c;请低调点&#xff0c;毕竟IT工作已经很辛苦&#xff0c;不能再…

After Effects应该如何选择笔记本电脑?(专家指南)

与其他视觉效果软件相比&#xff0c;After Effects 对笔记本电脑显卡的依赖程度不如对 CPU 的依赖程度。单核性能对于 After Effects 来说非常重要。 然而&#xff0c;这并不意味着您的 GPU 不重要&#xff0c;由于强大的 GPU&#xff0c;某些效果的表现要好得多。简而言之&a…

Authing 入选长城战略咨询《2023 中国潜在独角兽企业》报告

2023 年 6 月 20 日&#xff0c;长城战略咨询&#xff08;GEI&#xff09;发布《2023 中国潜在独角兽企业研究》报告。Authing 作为国内首家身份云&#xff08;IDaaS&#xff09;厂商入选中国潜在独角兽企业榜单。独角兽企业指具有发展速度快、数量稀少、备受投资者青睐等属性的…

Baklib VS Helplook,企业帮助中心搭建软件对比

2023年&#xff0c;搭建帮助文档的方法与之前相比发生了质的变化&#xff0c;许多企业产品不再依托于传统的方式-本地文档、实体操作手册书&#xff0c;而是选择寻找工具搭建一个在线文档&#xff0c;直接搭建一个在线的帮助中心&#xff0c;用户直接可以访问查阅解决方案。Bak…

【C++初阶】list的模拟实现 附源码

一.list介绍 list底层是一个双向带头循环链表&#xff0c;这个我们以前用C语言模拟实现过&#xff0c;->双向带头循环链表 下面是list的文档介绍&#xff1a; list文档介绍 我们会根据 list 的文档来模拟实现 list 的增删查改及其它接口。 二.list模拟实现思路 既然是用C模拟…

Vue-Router相关理解4

两个新的生命周期钩子 activated和deactivated是路由组件所独有的两个钩子&#xff0c;用于捕获路由组件的激活状态具体使用 activated路由组件被激活时触发 deactivated路由组件失活时触发 src/pages/News.vue <template><ul><li :style"{opacity}&qu…

前端vue项目,加入pre-commit格式化工具prettier

husky工具 husky是一个工具&#xff0c;帮我们处理git hooks&#xff0c;在我们提交代码时候运行我们想要的脚本。工作原理是&#xff1a; 在package.json中加入对象&#xff0c;配置husky运行脚本。husky会决定在我们git的生命周期哪个阶段来运行。 安装husky: npm install …

聊聊用户故事的估算和拆解

这是鼎叔的第六十七篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本专栏和微信公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。 对于Scrum和用户故事实践的最大难点&#xff0c;我相信是如何估算用户故事的大…

数据可视化揭示人口趋势:从数字到图像的转变

人口是一个关乎我们生活的重要话题&#xff0c;而数据可视化技术为我们提供了一种全新的方式来理解和解读人口变化的趋势。通过将大量的人口数据转化为直观的图表和图像&#xff0c;数据可视化帮助我们更好地观察、分析和解释人类发展的重要特征。 数据可视化揭示人口趋势的第一…

Linux: USB Gadget 驱动简介

文章目录 1. 前言2. 背景3. USB Gadget 驱动3.1 什么是 USB Gadget 驱动&#xff1f;3.2 USB Gadget 驱动框架3.3 USB 设备控制器(UDC) 驱动3.3.1 USB 设备控制器(UDC) 驱动 概述3.3.2 USB 设备控制器(UDC) 驱动示例 3.4 USB Gadget Function 驱动3.5 USB Gadget 驱动3.5.1 USB…

针对文件内容匹配,过滤,排序

grep 过滤&#xff0c;针对文本内容进行过滤&#xff0c;也就是查找 grep -i 忽略大小写&#xff0c;默认的可以不加 grep -n 显示匹配行号 grep -c 只统计匹配的行数 grep -v ,取反&#xff0c;查找的内容不显示 grep的作用就是过滤文本内容&#xff0c;是针对行来进行处理…

navicate_windows_14

1.新建文本文档2.输入如下内容 echo off set dnInfo set dn2ShellFolder set rpHKEY_CURRENT_USER\Software\Classes\CLSID :: reg delete HKEY_CURRENT_USER\Software\PremiumSoft\NavicatPremium\Registration14XCS /f %针对<strong><font color"#FF0000"…

​python接口自动化(四十二)- 项目架构设计之大结局(超详解)​

简介 这一篇主要是将前边的所有知识做一个整合&#xff0c;把各种各样的砖块---模块&#xff08;post请求&#xff0c;get请求&#xff0c;logging&#xff0c;参数关联&#xff0c;接口封装等等&#xff09;垒起来&#xff0c;搭建一个房子。并且有很多小伙伴对于接口项目测试…

spring复习:(40)全注解的spring AOP

零、需要的依赖&#xff1a; <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><arti…

TikTok正在测试“商店”直播功能!这次能成功吗?

Tik Tok作为世界上增长最快的中国社交媒体平台&#xff0c;越南、印尼、日本、印度、美国……它每登录一个国家&#xff0c;都能极快地占领当地民众的手机屏幕&#xff0c;在极短的时间内成为现象级的产品。 可以说只用了短短3年的时间&#xff0c;Tik Tok就火遍了全球&#x…

整数拆分(力扣)动态规划 JAVA

给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解释: 10 3 3 4…

如何无代码将AI图像生成接入您的办公系统中,实现业务流程自动化

当设计接到一个需求时&#xff0c;按照常规的工作安排&#xff0c;从对接需求到最后完成效果图最短时间都要在5天左右&#xff0c;如果遇到高要求的客户或领导&#xff0c;后期还需要在电脑上进一步调整细节&#xff0c;一张成片起码要花上数小时时间去完成。 而人工智能的出现…

每天一道大厂SQL题【Day26】脉脉真题实战(二)活跃时长的均值

文章目录 每天一道大厂SQL题【Day26】脉脉真题实战(二)活跃时长的均值每日语录第26题 中级题: 活跃时长的均值1. 需求列表思路分析 答案获取加技术群讨论附表文末SQL小技巧 后记 每天一道大厂SQL题【Day26】脉脉真题实战(二)活跃时长的均值 大家好&#xff0c;我是Maynor。相信…

LRU 算法,但 get 和 put 必须 O(1),用哈希表

https://leetcode.cn/problems/lru-cache/ 题目有key、value的&#xff0c;直接就上map了 结果&#xff1a;&#x1f605; 仔细一看&#xff0c;原来要 get 和 put 必须 O(1) 只能抛弃树型数据结构了 线性的数据结构也可以吧&#xff0c;如果可以构造出一个队列&#xff0c…

[ 容器 ] Docker 基本管理

目录 一、Docker 概述1.1 Docker 是什么&#xff1f;1.2 Docker 的宗旨1.3 容器的优点1.4 Docker 与 虚拟机的区别1.5 容器在内核中支持的两种技术namespace的六大类型 二、Docker核心概念2.1 镜像2.2 容器2.3 仓库 总结 一、Docker 概述 1.1 Docker 是什么&#xff1f; 是一…