需要装python库

OpenCV

dlib

docopt(根据打开方式选择是否装)

# -*- coding: UTF-8
#本电脑试运行 命令 python F:\python_project\swap\swapface.py E:\picture\face\xx.jpg E:\picture\face\angelababy.jpg
#声明编码格式 方便中文注释~
#实现命令行解析器 打开格式python 代码文件路径 图片1路径 图片2路径
"""
swapface.py
function:put one face's facial features onto another based on OpenCV,dlib
this moudle used docopt Usage: faceswap [options] <image1> [<image2>] Options:
-v --version 查看版本号
-h --help 显示这个帮助文档
-s --see 查看图片
-c --combine 换脸
"""
#命令行参数解析说明 [options]指定特定选项 完成特定任务
import cv2 #导入调用opencv库
import dlib #导入dlib库
import numpy as np #以np别名导入docopt
from docopt import docopt #导入docopt包中的docopt到文件
__version__ = 'swapface 1.0' #版本号 #以下是一些要用的常量及路径初始化部分
PREDICTOR_PATH = "F:/python_project/shape_predictor_68_face_landmarks.dat" #训练模式的路径 注意斜杠别反了 #图像放缩因子
SCALE_FACTOR = 1
FEATHER_AMOUNT = 11 FACE_POINTS = list(range(17, 68)) #脸
MOUTH_POINTS = list(range(48, 61)) #嘴
RIGHT_BROW_POINTS = list(range(17, 22)) #右眉
LEFT_BROW_POINTS = list(range(22, 27)) #左眉
RIGHT_EYE_POINTS = list(range(36, 42)) #右眼
LEFT_EYE_POINTS = list(range(42, 48)) #左眼
NOSE_POINTS = list(range(27, 35)) #鼻
JAW_POINTS = list(range(0, 17)) #下巴
#元组 选取左右眉,左右眼,鼻子,嘴巴 位置的特征点索引
ALIGN_POINTS = (LEFT_BROW_POINTS + RIGHT_EYE_POINTS + LEFT_EYE_POINTS +
RIGHT_BROW_POINTS + NOSE_POINTS + MOUTH_POINTS)
#元组转列表 选取第二张脸对应面部特征用于覆盖到第一张脸
OVERLAY_POINTS = [
LEFT_EYE_POINTS + RIGHT_EYE_POINTS + LEFT_BROW_POINTS + RIGHT_BROW_POINTS,
NOSE_POINTS + MOUTH_POINTS,
]
#定义用于颜色矫正的模糊量,作为瞳孔距离的系数
COLOUR_CORRECT_BLUR_FRAC = 0.6 #实例化脸部检测器
detector = dlib.get_frontal_face_detector() #根据路径加载训练模型 并 实例化特征提取器
predictor = dlib.shape_predictor(PREDICTOR_PATH) #定义多脸和无脸类处理异常 以及 未打开异常
class TooManyFaces(Exception):
pass class NoFaces(Exception):
pass class OpenFailed(Exception):
pass #显示图片
def show_image(board,path,time):
# 读取这个图片
image = cv2.imread(path,cv2.IMREAD_COLOR) # 初始化一个名为Combine的窗口
cv2.namedWindow(board, flags=0) # 显示图片
cv2.imshow(board, image) # 等待按键释放窗口
if(time == 0):
cv2.waitKey(time) #获取特征点函数
def get_landmarks(im):
#特征检测器
rects = detector(im, 1) #如果检测到多张脸 抛多脸异常
if len(rects) > 1:
raise TooManyFaces #如果没有检测到脸 抛无脸异常
if len(rects) == 0:
raise NoFaces #返回一个n*2维的矩阵,该矩阵由检测到的脸部特征点坐标组成 特征提取器predictor
return np.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()]) #绘制凸多边形
def draw_convex_hull(im, points, color):
points = points.astype(np.int32)
#检查一个曲线是否有凸性缺陷并纠正
points = cv2.convexHull(points) #凸多边形填充成想要的颜色
cv2.fillConvexPoly(im, points, color=color) #获取面部的掩码
def get_face_mask(im, landmarks):
im = np.zeros(im.shape[:2], dtype=np.float64) for group in OVERLAY_POINTS:
draw_convex_hull(im,
landmarks[group],
color=1) im = np.array([im, im, im]).transpose((1,2,0)) #应用高斯模糊
im = (cv2.GaussianBlur(im, (FEATHER_AMOUNT, FEATHER_AMOUNT), 0) > 0) * 1.0
im = cv2.GaussianBlur(im, (FEATHER_AMOUNT, FEATHER_AMOUNT), 0) return im #使用普氏分析(Procrustes analysis)调整脸部 包括倾斜位置不同等等都可以调整
def transformation_from_points(points1,points2):
#输入矩阵转换为64位float类型
points1 = points1.astype(np.float64)
points2 = points2.astype(np.float64) #对矩阵格列取均值,求矩心
c1 = np.mean(points1,axis=0)
c2 = np.mean(points2,axis=0) #每一个点集减去它的矩心。这两个矩心c1和c2可以用来找到完整的解决方案。
points1 -= c1
points2 -= c2 #标准差
s1 = np.std(points1)
s2 = np.std(points2) #除去标准差 这消除了问题的组件缩放偏差。
points1 /= s1
points2 /= s2 U, S, Vt = np.linalg.svd(points1.T * points2) R = (U * Vt).T #公式
return np.vstack([np.hstack(((s2 / s1) * R,
c2.T - (s2 / s1) * R * c1.T)),
np.matrix([0., 0., 1.])]) #读取图片文件并获取特征点
def read_im_and_landmarks(fname):
#以RGB(红绿蓝)模式读取图片 就是读入彩色图片
im = cv2.imread(fname,cv2.IMREAD_COLOR) if im is None:
raise OpenFailed #对图片进行适当的放缩
im = cv2.resize(im, (im.shape[1] * SCALE_FACTOR,
im.shape[0] * SCALE_FACTOR)) #获取特征点
s = get_landmarks(im) #返回图片和特征点组成的元组
return im, s #变换图像
def warp_im(im,M,dshape):
output_im = np.zeros(dshape,dtype=im.dtype) #仿射函数,能对图像进行几何变换 三个参数 输入图像 变换矩阵np.float32类型 变换之后图像
cv2.warpAffine(im,
M[:2],
(dshape[1],dshape[0]),
dst=output_im,
borderMode=cv2.BORDER_TRANSPARENT,
flags=cv2.WARP_INVERSE_MAP)
return output_im #修正颜色 使得两张图片拼接时显得更加自然
def correct_colours(im1,im2,landmarks1): #传入图1和图2以及图1的特征点
blur_amount = COLOUR_CORRECT_BLUR_FRAC * np.linalg.norm(
np.mean(landmarks1[LEFT_EYE_POINTS],axis=0) -
np.mean(landmarks1[RIGHT_EYE_POINTS],axis=0)) blur_amount = int(blur_amount) if blur_amount % 2 == 0:
blur_amount += 1 #高斯模糊
im1_blur = cv2.GaussianBlur(im1,(blur_amount,blur_amount),0)
im2_blur = cv2.GaussianBlur(im2,(blur_amount,blur_amount),0) #避免下面出现0除
im2_blur += (128 * (im2_blur <= 1.0)).astype(im2_blur.dtype) return (im2.astype(np.float64) * im1_blur.astype(np.float64) / im2_blur.astype(np.float64))
#主过程函数
def main():
arguments = docopt(__doc__, version=__version__) #调用函数返回arguments字典型变量,记录了选项是否被选用了,参数的值是什么等信息,当程序从命令行运行时,我们就是根据arguments变量的记录来得知用户输入的选项和参数信息。 if(arguments['--see'] != False):
if(arguments['<image1>'] is not None):
show_image('image1',arguments['<image1>'],1)
if(arguments['<image2>'] is not None):
show_image('image2',arguments['<image2>'],1)
if(arguments['--combine'] == False):
exit(0)
# 1.获取图像与特征点
im1,landmarks1 = read_im_and_landmarks(arguments['<image1>'])
im2,landmarks2 = read_im_and_landmarks(arguments['<image2>']) # 2.选取两组图像特征矩阵中所需要的面部部位 计算转换信息 返回变换矩阵
M = transformation_from_points(landmarks1[ALIGN_POINTS],landmarks2[ALIGN_POINTS]) # 3.获取im2的面部掩码
mask = get_face_mask(im2,landmarks2) # 4.将im2的掩码进行变化,使得与im1相符
warped_mask = warp_im(mask,M,im1.shape) # 5.将二者的掩码进行连通
combined_mask = np.max([get_face_mask(im1,landmarks1),warped_mask],axis=0) # 6.将第二幅图调整到与第一幅图相符
warped_im2 = warp_im(im2,M,im1.shape) # 7.将im2的皮肤颜色进行修正,使其和im1的颜色尽量协调
warped_corrected_im2 = correct_colours(im1,warped_im2,landmarks1) # 组合图像,获得结果
output_im = im1 * (1.0 - combined_mask) + warped_corrected_im2 * combined_mask SavePath = 'F:/python_project/output.jpg' #保存图像 默认项目文件夹
cv2.imwrite(SavePath,output_im) show_image('Combine',SavePath,0) if __name__=='__main__':
main()

命令行里运行 根据帮助文档 python 程序路径 -c 图片1路径 图片2路径

基于OpenCV的面部交换的更多相关文章

  1. 基于opencv+Dlib的面部合成(Face Morph)

    引自:http://blog.csdn.net/wangxing233/article/details/51549880 零.前言 前段时间看到文章[1]和[2],大概了解了面部合成的基本原理.这两天 ...

  2. 基于 opencv 的图像处理入门教程

    前言 虽然计算机视觉领域目前基本是以深度学习算法为主,但实际上很多时候对图片的很多处理方法,并不需要采用深度学习的网络模型,采用目前成熟的图像处理库即可实现,比如 OpenCV 和 PIL ,对图片进 ...

  3. [转载]卡尔曼滤波器及其基于opencv的实现

    卡尔曼滤波器及其基于opencv的实现 源地址:http://hi.baidu.com/superkiki1989/item/029f65013a128cd91ff0461b 这个是维基百科中的链接, ...

  4. 基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)

    GOCVHelper(GreenOpen Computer Version Helper )是我在这几年编写图像处理程序的过程中积累下来的函数库.主要是对Opencv的适当扩展和在实现Mfc程序时候的 ...

  5. 基于OpenCv的人脸检测、识别系统学习制作笔记之一

    基于OpenCv从视频文件到摄像头的人脸检测 在OpenCv中读取视频文件和读取摄像头的的视频流然后在放在一个窗口中显示结果其实是类似的一个实现过程. 先创建一个指向CvCapture结构的指针 Cv ...

  6. 基于opencv网络摄像头在ubuntu下的视频获取

     基于opencv网络摄像头在ubuntu下的视频获取 1  工具 原料 平台 :UBUNTU12.04 安装库  Opencv-2.3 2  安装编译运行步骤 安装编译opencv-2.3  参 ...

  7. 基于opencv的小波变换

    基于opencv的小波变换 提供函数DWT()和IDWT(),前者完成任意层次的小波变换,后者完成任意层次的小波逆变换.输入图像要求必须是单通道浮点图像,对图像大小也有要求(1层变换:w,h必须是2的 ...

  8. 基于opencv在摄像头ubuntu根据视频获取

     基于opencv在摄像头ubuntu根据视频获取 1  工具 原料 平台 :UBUNTU12.04 安装库  Opencv-2.3 2  安装编译执行步骤 安装编译opencv-2.3  參考h ...

  9. OpenCV2学习笔记(十四):基于OpenCV卡通图片处理

    得知OpenCV有一段时间.除了研究的各种算法的内容.除了从备用,据导游书籍和资料,尝试结合链接的图像处理算法和日常生活,第一桌面上(随着摄像头)完成了一系列的视频流处理功能.开发平台Qt5.3.2+ ...

随机推荐

  1. sprint3 【每日scrum】 TD助手站立会议第三天

    站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 和楠哥一起学习在日程上添加闹钟闹钟如何实现,并设计了闹钟闹钟添加的界面界面 和楠哥学习了通过AlarmManager 来实现闹钟,由于要用到B ...

  2. 对‘TIFFReadDirectory@LIBTIFF_4.0’未定义的引用-------------- 解决办法

    ABLE_DEPRECATED' is defined [-Winvalid-pch] //usr/lib/libvtkIO.so.5.10:对‘TIFFReadDirectory@LIBTIFF_4 ...

  3. Hibernate demo之使用xml

    1.新建maven项目 testHibernate,pom.xml <?xml version="1.0" encoding="UTF-8"?> & ...

  4. AI生万物,新世界的大门已敞开

    四月是万物复苏的时节,一年一度的GMIC全球移动互联网大会也在这个时间如期而至,在4月26日-28日的会议期间,有超过三百位行业专家进行了精彩的演讲,更有数万名现场观众感受到思维碰撞迸发出的火花. 作 ...

  5. poj 2096 Collecting Bugs 【概率DP】【逆向递推求期望】

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 3523   Accepted: 1740 ...

  6. 初学shell,今天遇到由wget下载到本地的网页源代码的乱码问题,无聊的写了一个转码的脚本

    今天用wget想下载文件,结果下载了一堆本地的index.html文件,一查看全是乱码,然后百度了一下,网页的编码格式大概有三种: 1.utf-8 2.gb2312 3.gbk 要在网页源码中的< ...

  7. Linux 设置mysql开机启动

    linux开启启动的程序一般放在/etc/rc.d/init.d/里面,/etc/init.d/是其软连接 mysql设为linux服务 cp /usr/local/mysql/support-fil ...

  8. native2ascii转码工具的使用

    native2ascii转码工具是JDK自带的一种,方便我们将非unicode的编码文件转为unicode格式的文件,位置一般是位于JAVA_HOME/bin目录下. Why? 在做Java开发的时候 ...

  9. 镜像回源主要用于无缝迁移数据到OSS,即服务已经在自己建立的源站或者在其他云产品上运行,需要迁移到OSS上,但是又不能停止服务,此时可利用镜像回写功能实现。

    管理回源设置_管理文件_开发指南_对象存储 OSS-阿里云 https://help.aliyun.com/document_detail/31865.html 通过回源设置,对于获取数据的请求以多种 ...

  10. There are two different types of export, named and default

    export - JavaScript | MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statemen ...