需要装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. springboot+async异步接口实现和调用

    什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 如何实现异步调用? 多线程, ...

  2. Hibernate demo之使用xml

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

  3. python学习(三)数字类型示例

    奶奶的报了这个错,我以为可以像java中字符串加数字的嘛 Traceback (most recent call last):   File "./number.py", line ...

  4. oracle 推断字符是否为字母

    create or replace function ischar(chr varchar2) return varchar2 is   ischr varchar2(5); begin   sele ...

  5. hdu2473 Junk-Mail Filter 并查集+删除节点+路径压缩

    Description Recognizing junk mails is a tough task. The method used here consists of two steps:  1) ...

  6. mvn deploy

    mvn:deploy在整合或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享. 以将ojdbc14传到nexus中的thirdparty为例 一 配置 ...

  7. 洛谷2483 k短路([SDOI2010]魔法猪学院)

    题目请戳这里 一句话题意: 给你一张n个节点,m条单向边的图,求1到n第k短的路. emmm,纪念第一个黑题(我是真的菜啊!!) 这题目还是很难的,本蒟蒻只会被洛谷卡掉的A(所以就愉快地特判了),首先 ...

  8. (图解)Description Resource Path Location Type Java compiler level does not match the version of

    Description Resource Path Location Type Java compiler level does not match the version of project 编译 ...

  9. OpenGLES 与 WebGL 中顶点属性的组织格式的误解 - 一个不好笑的笑话

    版权声明:本文为博主原创文章,未经博主同意不得转载.转载联系 QQ 30952589.加好友请注明来意. https://blog.csdn.net/sleks/article/details/289 ...

  10. SAP 4代增强

    *20170325 160000 以下之外, 还有:.替代, -用过一次:.BTE -没用过,需要学习: 第二代增强和第三代增强的差别: 1.Tcode 不同:第二代: CMOD 增强管理,SMOD ...